watch监听用来监听某个prop或data的改变,当它们发生变化时,就会触发watch配置的函数,从而完成我们的业务逻辑。
watch监听的数据的回调函数handler(newVar,oldVar)有两个参数可用,第一个就是新的值,第二就是旧的值。
1、watch监听基本例子
<div>
<p>FullName: {{fullName}}</p>
<p>FirstName: <input type="text" v-model="firstName"></p>
</div>
new Vue({
el: '#root',
data: {
firstName: 'Dawei',
lastName: 'Lou',
fullName: ''
},
watch: {
firstName(newName, oldName) {
this.fullName = newName + ' ' + this.lastName;
}
}
})
上面的代码的效果是,当我们输入firstName后,wacth监听每次修改变化的新值,然后计算输出fullName。
2、watch监听的deep属性
watch 里面还有一个属性deep,默认值是 false,代表是否深度监听,比如我们 data 里有一个obj属性:
<div>
<p>obj.a: {{obj.a}}</p>
<p>obj.a: <input type="text" v-model="obj.a"></p>
</div>
new Vue({
el: '#root',
data: {
obj: {
a: 123
}
},
watch: {
obj: {
handler(newName, oldName) {
console.log('obj.a changed');
},
immediate: true
}
}
})
当我们在在输入框中输入数据视图改变obj.a的值时,我们发现是无效的。Vue 不能检测到对象属性的添加或删除。由于 Vue 会在初始化实例时对属性执行 getter/setter 转化过程,所以属性必须在 data 对象上存在才能让 Vue 转换它,这样才能让它是响应的。
watch: {
obj: {
handler(newName, oldName) {
console.log('obj.a changed');
},
immediate: true,
deep: true
}
}
deep的意思就是深入观察,监听器会一层层的往下遍历,给对象的所有属性都加上这个监听器,但是这样性能开销就会非常大了,任何修改obj里面任何一个属性都会触发这个监听器里的 handler。
【注意】在watch监听的handler()方法中,第一个参数监听到的最新值,而第二个参数是旧值。
3、watch应用
3.1、监听data中的属性
<div id="app">
<input type="text" v-model="firstName"> +
<input type="text" v-model="lastName"> =
<span>{{fullName}}</span>
</div>
<script>
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {
firstName: 'jack',
lastName: 'chen',
fullName: 'jack - chen'
},
methods: {},
watch: {
'firstName': function (newVal, oldVal) { // 第一个参数是新数据,第二个参数是旧数据
this.fullName = newVal + ' - ' + this.lastName;
},
'lastName': function (newVal, oldVal) {
this.fullName = this.firstName + ' - ' + newVal;
}
}
});
</script>
3.2、监听路由对象的变化
<div id="app">
<router-link to="/login">登录</router-link>
<router-link to="/register">注册</router-link>
<router-view></router-view>
</div>
<script>
var login = Vue.extend({
template: '<h1>登录组件</h1>'
});
var register = Vue.extend({
template: '<h1>注册组件</h1>'
});
var router = new VueRouter({
routes: [
{ path: "/login", component: login },
{ path: "/register", component: register }
]
});
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {},
methods: {},
router: router,
watch: {
'$route': function (newVal, oldVal) {
if (newVal.path === '/login') {
console.log('这是登录组件');
}
}
}
});
</script>
4、计算属性computed
在computed属性对象中定义计算属性的方法;在页面中使用{{方法名}}来显示计算的结果。
【监视属性】
通过通过vm对象的$watch()或watch配置来监视指定的属性;当属性变化时, 回调函数自动调用, 在函数内部进行计算。
【计算属性高级】
通过getter/setter实现对属性数据的显示和监视;计算属性存在缓存, 多次读取只执行一次getter计算。
<div id="demo">
姓: <input type="text" placeholder="First Name" v-model="firstName"><br>
名: <input type="text" placeholder="Last Name" v-model="lastName"><br>
姓名1(单向): <input type="text" placeholder="Full Name1" v-model="fullName1"><br>
姓名2(单向): <input type="text" placeholder="Full Name2" v-model="fullName2"><br>
姓名3(双向): <input type="text" placeholder="Full Name3" v-model="fullName3"><br>
<p>{{fullName1}}</p>
<p>{{fullName1}}</p>
<p>{{fullName1}}</p>
<p>{{fullName1}}</p>
<p>{{fullName3}}</p>
<p>{{fullName3}}</p>
<p>{{fullName3}}</p>
<p>{{fullName3}}</p>
</div>
<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript">
// 对Vue进行全局配置
Vue.config.productionTip = false // 不显示没使用生产环境模式的提示
const vm = new Vue({
// el: '#demo',
data: {
firstName: 'A',
lastName: 'B',
fullName2: 'A-B',
},
// 计算属性: 通过计算动态产生一个要显示的结果数据
computed: {
/*
计算属性方法: 包装getter
执行的时机:
初始显示第一个次执行, 得到初始值显示
依赖数据发生改变就会再次调用
*/
fullName1 () {
console.log('fullName1()', this)
return this.firstName + '-' + this.lastName
},
fullName3: {
get () { // 计算产生要显示的值
console.log('fullName3 get()')
return this.firstName + '-' + this.lastName
},
set (value) { // 监视值的变化
console.log('fullName3 set()', value)
const names = value.split('-')
this.firstName = names[0]
this.lastName = names[1]
}
}
},
watch: { // 指定监视vm的哪个属性的变化
firstName (value) { // 当firstName发生改变时自动回调
console.log('firstName()', value)
// 更新fullName2
this.fullName2 = value + '-' + this.lastName
}
}
})
vm.$mount('#demo')
// 监视lastName
vm.$watch('lastName', function (value) {
console.log('lastName()', value)
this.fullName2 = this.firstName + '-' + value
})
注意:所有vue控制的回调函数的this都是vm或者组件对应。使用计算属性:
(1)只用getter,计算属性就是一个函数;
(2)使用getter/setter,计算属性是一个包含getter和setter对象。