本章节,我们将为大家介绍 Vue 监听属性 watch,我们可以通过 watch 来响应数据的变化。
以下实例通过使用 watch 实现计数器:
- <div id = "app">
- <p style = "font-size:25px;">计数器: {{ counter }}p>
- <button @click = "counter++" style = "font-size:25px;">点我button>
- div>
-
- <script>
- const app = {
- data() {
- return {
- counter: 1
- }
- }
- }
- vm = Vue.createApp(app).mount('#app')
- vm.$watch('counter', function(nval, oval) {
- alert('计数器值的变化 :' + oval + ' 变为 ' + nval + '!');
- });
- script>
以下实例进行千米与米之间的换算:
- <head>
- <meta charset="utf-8">
- <title>Vue 测试实例title>
- <script src="https://unpkg.com/vue@next">script>
- head>
- <body>
- <div id = "app">
- 千米 : <input type = "text" v-model = "kilometers">
- 米 : <input type = "text" v-model = "meters">
- div>
- <p id="info">p>
- <script>
- const app = {
- data() {
- return {
- kilometers : 0,
- meters:0
- }
- },
- watch : {
- kilometers:function(val) {
- this.kilometers = val;
- this.meters = this.kilometers * 1000
- },
- meters : function (val) {
- this.kilometers = val/ 1000;
- this.meters = val;
- }
- }
- }
- vm = Vue.createApp(app).mount('#app')
- vm.$watch('kilometers', function (newValue, oldValue) {
- // 这个回调将在 vm.kilometers 改变后调用
- document.getElementById ("info").innerHTML = "修改前值为: " + oldValue + ",修改后值为: " + newValue;
- })
- script>
以上代码中我们创建了两个输入框,data属性中,kilometers 和 meters 初始值都为0。watch 对象创建了 data 对象的两个监控方法:kilometers 和 meters。
watch(异步场景),computed(数据联动)watch可以在所监听的数据后面直接加字符串形式的方法名
- html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta http-equiv="X-UA-Compatible" content="ie=edge">
- <title>Vue计算属性/侦听器/方法比较title>
- <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js">script>
- head>
- <body>
- <div id="app">
- <h1>计算属性:computedh1>
- {{fullName}}
- <h1>方法:methodsh1>
- {{fullName2()}}
- <h1>侦听器:watchh1>
- {{watchFullName}}
- <h1>年龄h1>
- {{age}}
- div>
- <script>
- var other = 'This is other';
- var app = new Vue({
- el:"#app",
- data:{
- firstName:"zhang",
- lastName:"san",
- watchFullName:"zhangsan",
- age:18,
- },
- watch: {
- firstName:function(newFirstName, oldFirstName){
- console.log("firstName触发了watch,newFirstName="+newFirstName+",oldFirstName="+oldFirstName)
- this.watchFullName = this.firstName+this.lastName+","+other
- },
- lastName:function(newLastName, oldLastName){
- console.log("lastName触发了watch,newLastName="+newLastName+",oldLastName="+oldLastName)
- this.watchFullName = this.firstName+this.lastName+","+other
- },
- watchFullName:"change"
-
- },
- computed: {
- fullName:function(){
- console.log("调用了fullName,计算了一次属性")
- return this.firstName+this.lastName+","+other;
- }
- },
- methods: {
- fullName2:function(){
- console.log("调用了fullName,执行了一次方法")
- fullName2 = this.firstName+this.lastName+","+other;
- return fullName2;
- },
- change(){
- console.log("调用了change,触发了watch")
- return this.watchFullName='111'
- }
- }
- });
- script>
- body>
- html>
handler方法就相当于普通侦听器触发的事件,从结果可以看到,组件初始化的时候,侦听器并没有handler方法,所以fullName是没有值的。
当修改以上代码,加上immediate:true,immediate:true代表watch里面声明了之后会立马执行handler里面的函数。执行相应的逻辑。组件初始化的时候,侦听器(immediate)触发handler方法
- html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta http-equiv="X-UA-Compatible" content="ie=edge">
- <title>Vue计算属性/侦听器/方法比较title>
- <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js">script>
- head>
- <body>
- <div id="app">
- <div>
- <p>FullName: {{person.fullname}}p>
- <p>FirstName: <input type="text" v-model="person.firstname">p>
- div>
- div>
- <script>
- var other = 'This is other';
- var app = new Vue({
- el: '#app',
- data(){
- return {
- person: {
- firstname: 'Menghui',
- lastname: 'Jin',
- fullname: ''
- }
- }
- },
- watch: {
- person: {
- handler(n,o){
- this.person.fullname = n.firstname + '' + this.person.lastname;
- },
- immediate: true, //刷新加载 立马触发一次handler
- deep: true // 可以深度检测到 person 对象的属性值的变化
- }
- }
- })
- script>
- body>
- html>
当在输入框中输入数据时,可以发现fullName的值并没有随之改变 这是因为vue无法检测到对象内部属性值的变化,比如person。firstname的变化
所以此时 需要用到vue的深度监听(deep)
此时加上代码 deep:true
可以发现 每次输入框数据变化 fullname 随之改变
上面的可以发现handler监听的新值和老值是一样的 这是由vue2.0的坑 由于同源导致的 可以用computed 来修改
- html>
- <html>
- <head>
- <meta charset="utf-8">
- <title>title>
-
- head>
- <body>
- <div id="app">
- <p>FullName: {{person.fullname}}p>
- <p>FirstName: <input type="text" v-model="person.firstname">p>
- div>
- <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js">script>
- <script>
- const app = new Vue({
- el: "#app",
- data() {
- return {
- person: {
- firstname: 'Menghui',
- lastname: 'Jin',
- fullname: ''
- }
- }
- },
- methods: {
-
- },
- computed: {
- person2(){
- return JSON.parse(JSON.stringify(this.person));
- }//解决深度监听新老值同源问题
- },
- watch:{
- person2:{
- handler(n,o){
- console.log(this.person);
- console.log(n.firstname);
- console.log(o.firstname);
-
- /* this.person.fullname = this.person.firstname + this.person.lastname */
- },
- /* immediate: true, */
- deep: true // 可以深度检测到 person 对象的属性值的变化
- }
- }
- })
- script>
- body>
- html>