7.1.效果
7.2.插值语法实现
使用插值语法虽然可以实现效果,但如果有个需求,姓文本框输入的内容过多,在全名里做截图前三位显示,把插值{{firstName}}-{{lastName}}
改成{{firstName.slice(0,3)}}-{{lastName}}
就可以进行截取,但不建议这样做,{{}}
里的内容要尽量保证简单性,因为要考虑到以后业务逻辑的复杂性
代码
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>姓名案例_插值语法实现</title>
<!-- 引入Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="root">
姓:<input type="text" v-model="firstName"> <br/><br/>
名:<input type="text" v-model="lastName"> <br/><br/>
全名:<span>{{firstName}}-{{lastName}}</span>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
new Vue({
el:'#root',
data:{
firstName:'张',
lastName:'三'
}
})
</script>
</html>
7.3.methods 实现
{{fullName()}}
表示调取funllName()
方法的返回值,填充到标签中。{{fullName}}
表示将fullName
的属性值填充到标签中。
问题:data
中的任何一个数据发生变化时,Vue 的模板都会重新解析一边,每解析一次fullName()
方法就会调用一次,也就是firstName
和lastName
所在的文本框每输入或者删除一个值就会触发一次fullName()
方法的调用。这样会导致效率不高
代码
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>姓名案例_methods实现</title>
<!-- 引入Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="root">
姓:<input type="text" v-model="firstName"> <br/><br/>
名:<input type="text" v-model="lastName"> <br/><br/>
全名:<span>{{fullName()}}</span>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
new Vue({
el:'#root',
data:{
firstName:'张',
lastName:'三'
},
methods: {
fullName(){
console.log('@---fullName')
return this.firstName + '-' + this.lastName
}
},
})
</script>
</html>
7.4.计算属性实现
- 要显示的数据不存在,要通过计算得来。
- 在
computed
对象中定义计算属性 - 在页面中使用
{{方法名}}
来显示计算的结果。
计算属性是获取已赋值的属性进行加工和计算再生成一个新属性
在 Vue 中计算属性的配置项是computed
1.定义:要用的属性不存在,要通过已有属性计算得来。
2.原理:底层借助了Objcet.defineproperty
方法提供的getter
和setter
。
3.get
函数什么时候执行?
(1).初次读取时会执行一次。
(2).当依赖的数据发生改变时会被再次调用。
4.set
函数在数据发生改变的时候执行
5.优势:与methods
实现相比,内部有缓存机制(复用),效率更高,调试方便。
6.备注:
1.计算属性最终会出现在vm
上,直接读取使用即可。
2.如果计算属性要被修改,那必须写set
函数去响应修改,且set
中要引起计算时依赖的数据发生改变。
代码
下面代码中,页面虽然会多次调用fullName
但get()
只会初始化一次,然后把值缓存起来,后面再次调用fullName
读取就是缓存里的值,只有get()
里面的值被修改的时候,fullName
才会进行更新,例如下面代码中的x
属性改变的时候不会引起get()
的调用。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>姓名案例_计算属性实现</title>
<!-- 引入Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="root">
姓:<input type="text" v-model="firstName"> <br/><br/>
名:<input type="text" v-model="lastName"> <br/><br/>
测试:<input type="text" v-model="x"> <br/><br/>
全名:<span>{{fullName}}</span> <br/><br/>
<!-- 全名:<span>{{fullName}}</span> <br/><br/>
全名:<span>{{fullName}}</span> <br/><br/>
全名:<span>{{fullName}}</span> -->
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el:'#root',
data:{
firstName:'张',
lastName:'三',
x:'你好'
},
methods: {
demo(){
}
},
computed:{
fullName:{
//get有什么作用?当有人读取fullName时,get就会被调用,且返回值就作为fullName的值
//get什么时候调用?1.初次读取fullName时。2.所依赖的数据发生变化时。
get(){
console.log('get被调用了')
// console.log(this) //此处的this是vm
return this.firstName + '-' + this.lastName
},
//set什么时候调用? 当fullName被修改时。
set(value){
console.log('set',value)
const arr = value.split('-')
this.firstName = arr[0]
this.lastName = arr[1]
}
}
}
})
</script>
</html>
计算属性简写
只有computed
里的属性只考虑读取,不考虑修改的情况下才能使用简写形式。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>姓名案例_计算属性实现</title>
<!-- 引入Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="root">
姓:<input type="text" v-model="firstName"> <br/><br/>
名:<input type="text" v-model="lastName"> <br/><br/>
全名:<span>{{fullName}}</span> <br/><br/>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el:'#root',
data:{
firstName:'张',
lastName:'三',
},
computed:{
//完整写法
/* fullName:{
get(){
console.log('get被调用了')
return this.firstName + '-' + this.lastName
},
set(value){
console.log('set',value)
const arr = value.split('-')
this.firstName = arr[0]
this.lastName = arr[1]
}
} */
//简写
fullName(){
console.log('get被调用了')
return this.firstName + '-' + this.lastName
}
}
})
</script>
</html>
7.5. 侦听属性-watch
效果:
代码演示
实现方式一:用普通方法实现值的改变
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>天气案例</title>
<!-- 引入Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="root">
<h2>今天天气很{{info}}</h2>
<!-- 绑定事件的时候:@xxx="yyy" yyy可以写一些简单的语句 -->
<!-- <button @click="isHot = !isHot">切换天气</button> -->
<button @click="changeWeather">切换天气</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el:'#root',
data:{
isHot:true,
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽'
}
},
methods: {
changeWeather(){
this.isHot = !this.isHot
}
},
})
</script>
</html>
侦听属性
watch监视属性
- 当被侦听的属性变化时,回调函数自动调用,进行相关操作
- 侦听的属性必须存在,才能进行侦听,既可以侦听
data
,也可以侦听计算属性 - 配置项属性
**immediate:false**
,改为 true,则初始化时调用一次**handler(newValue,oldValue)**
- 侦听有两种写法
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>天气案例_侦听属性</title>
<!-- 引入Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="root">
<h2>今天天气很{{info}}</h2>
<button @click="changeWeather">切换天气</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el:'#root',
data:{
isHot:true,
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽'
}
},
methods: {
changeWeather(){
this.isHot = !this.isHot
}
},
/* watch:{
isHot:{
immediate:true, //初始化时让handler调用一下
//handler什么时候调用?当isHot发生改变时。
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue)
}
}
} */
})
vm.$watch('isHot',{
immediate:true, //初始化时让handler调用一下
//handler什么时候调用?当isHot发生改变时。
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue)
}
})
</script>
</html>
深度侦听
Vue
中的watch
默认不监测对象内部值的改变(一层)。- 配置
deep:true
可以监测对象内部值改变(多层)。
备注:
Vue
自身可以监测对象内部值的改变,但Vue
提供的watch
默认不可以!-
代码演示
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>天气案例_深度侦听</title> <!-- 引入Vue --> <script type="text/javascript" src="../js/vue.js"></script> </head> <body> <!-- 准备好一个容器--> <div id="root"> <h2>今天天气很{{info}}</h2> <button @click="changeWeather">切换天气</button> <hr/> <h3>a的值是:{{numbers.a}}</h3> <button @click="numbers.a++">点我让a+1</button> <h3>b的值是:{{numbers.b}}</h3> <button @click="numbers.b++">点我让b+1</button> <button @click="numbers = {a:666,b:888}">彻底替换掉numbers</button> {{numbers.c.d.e}} </div> </body> <script type="text/javascript"> Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。 const vm = new Vue({ el:'#root', data:{ isHot:true, numbers:{ a:1, b:1, c:{ d:{ e:100 } } } }, computed:{ info(){ return this.isHot ? '炎热' : '凉爽' } }, methods: { changeWeather(){ this.isHot = !this.isHot } }, watch:{ isHot:{ // immediate:true, //初始化时让handler调用一下 //handler什么时候调用?当isHot发生改变时。 handler(newValue,oldValue){ console.log('isHot被修改了',newValue,oldValue) } }, //侦听多级结构中某个属性的变化 /* 'numbers.a':{ handler(){ console.log('a被改变了') } } */ //侦听多级结构中所有属性的变化 numbers:{ deep:true, handler(){ console.log('numbers改变了') } } } }) </script> </html>
侦听属性_简写
简写使用场景:如果侦听属性除了
handler
没有其他配置项的话,可以进行简写代码演示
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>天气案例_监视属性_简写</title> <!-- 引入Vue --> <script type="text/javascript" src="../js/vue.js"></script> </head> <body> <!-- 准备好一个容器--> <div id="root"> <h2>今天天气很{{info}}</h2> <button @click="changeWeather">切换天气</button> </div> </body> <script type="text/javascript"> Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。 const vm = new Vue({ el:'#root', data:{ isHot:true, }, computed:{ info(){ return this.isHot ? '炎热' : '凉爽' } }, methods: { changeWeather(){ this.isHot = !this.isHot } }, watch:{ //正常写法 /* isHot:{ // immediate:true, //初始化时让handler调用一下 // deep:true,//深度监视 handler(newValue,oldValue){ console.log('isHot被修改了',newValue,oldValue) } }, */ //简写 /* isHot(newValue,oldValue){ console.log('isHot被修改了',newValue,oldValue,this) } */ } }) //正常写法 /* vm.$watch('isHot',{ immediate:true, //初始化时让handler调用一下 deep:true,//深度监视 handler(newValue,oldValue){ console.log('isHot被修改了',newValue,oldValue) } }) */ //简写 /* vm.$watch('isHot',function(newValue,oldValue){ console.log('isHot被修改了',newValue,oldValue,this) }) */ </script> </html>
计算属性 VS 侦听属性
computed
和watch
之间的区别
computed
能完成的功能,watch
都可以完成watch
能完成的功能,computed
不一定能完成,例如watch
可以进行异步操作
两个重要的小原则
- 所有被
Vue
管理的函数,最好写成普通函数,这样this
的指向才是vm
或组件实例对象 所有不被
Vue
所管理的函数(定时器的回调函数、ajax
的回调函数等、Promise
的回调函数),最好写成箭头函数,这样this
的指向才是vm
或组件实例对象代码演示
使用计算属性
new Vue({ el:'#root', data:{ firstName:'张', lastName:'三' }, computed:{ fullName(){ return this.firstName + '-' + this.lastName } } })
使用监听属性
使用侦听属性,可以针对单个属性进行异步处理,比如延迟加载
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>姓名案例_watch实现</title> <!-- 引入Vue --> <script type="text/javascript" src="../js/vue.js"></script> </head> <body> <!-- 准备好一个容器--> <div id="root"> 姓:<input type="text" v-model="firstName"> <br/><br/> 名:<input type="text" v-model="lastName"> <br/><br/> 全名:<span>{{fullName}}</span> <br/><br/> </div> </body> <script type="text/javascript"> Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。 const vm = new Vue({ el:'#root', data:{ firstName:'张', lastName:'三', fullName:'张-三' }, watch:{ firstName(val){ //箭头函数代码块里没有this,this.fullName中的this它会往自己的父级找 //setTimeout的父级就是vm,所以这里的this就是vm setTimeout(()=>{ console.log(this) this.fullName = val + '-' + this.lastName },1000); }, lastName(val){ this.fullName = this.firstName + '-' + val } } }) </script> </html>