最后有操作实例,以及监听不到的解决办法,超级详细,必须看懂!

在Vue中,用watch来响应监听数据的变化。

1.监听某一数据的变化
2.监听对象或者数组的变化
3.监听对象或者数组某一属性的变化
4.监听路由的变化

一.监听某一数据的变化

<input type="text" v-model="userName"/>
//当userName值发生变化时触发
watch: {
	userName (newName, oldName) {
		console.log(newName)
	}
}

第一种有一个缺点,就是当值第一次绑定的时候不会执行监听函数,只有当值改变的时候才会执行,
如果我们想在第一次绑定的时候执行此监听函数 则需要 设置immediate为true

//当userName值发生变化时触发
watch: {
	userName: {
		handler (newName, oldName) {
			console.log(newName)
		},
		immediate: true
	}
}

二.监听对象或者数组的变化

当需要监听对象的改变时,此时就需要设置deep为true,
如果数组或对象采用 =(直接赋值的方法)普通监听也是可以监听到的。

<input type="text" v-model="cityName.name" />
data (){
	return {
		cityName: {name:'北京'}
	}
},
watch: {
	cityName: {
		handler(newName, oldName) {
			console.log(newName)
		},
		immediate: true,
		deep: true
	}
}

三.监听对象或者数组某一属性的变化

watch添加deep:true深度监听,只能监听到属性值的变化,新增、删除属性无法监听,下方有解决方法。

watch: {
	'cityName.name': {
		handler(newName, oldName) {
			console.log(newName)
		},
		immediate: true,
		deep: true
	}
}

四.监听路由的变化

watch:{
      '$route.path':function(newVal,oldVal){
        //console.log(newVal+"---"+oldVal);
        if(newVal === '/login'){
          console.log('欢迎进入登录页面');
        } else if(newVal === '/register'){
          console.log('欢迎进入注册页面');
        }
      }
 }
watch:{
  $route(to,from){
    console.log(to.path);
  }
},

实例

Vue 不允许在已经创建的实例上动态添加新的根级响应式属性(root-level reactive property)。然而它可以使用Vue.set(object, key, value) 方法将响应属性添加到嵌套的对象上,这样对象就变成了响应式的了,以下的方法就都可以使用了,此外动态添加新的根级响应式属性还可以用=、push、pop、shift、unshift、splice、sort、reverse。(使用=的时候必须整体赋值 arr=[…],不能arr[0]=…。这样添加的属性是不具备响应式属性的,无setter/getter。)

下面展示一些 内联代码片

<template>
  <div>
    <ul>
      <li v-for="(item, index) in arr" :key="index">{{ item.name || item }}</li>
    </ul>
    <ul>
      <li v-for="(item, index) in obj" :key="index">{{ item }}</li>
    </ul>
    <button @click="tapme">点击我</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      arr: [1, 2, 3, { name: "cui" }],
      obj: {
        name: "cui",
        age: 18,
        sex: "男",
      },
    };
  },
  methods: {
    tapme() {
    	//以下的操作都是在data中的内容都是一开始就定义好的,这样才是响应式的,才能有以下的操作,若一开始只是声明了一下,却没有赋值,而是在某个操作中直接赋值的话(不是使用$set的方法(响应式)),修改后就失去了getter、setter。下面的部分操作便会失效(标注)
        //操作数组
        this.arr[0]=100; //视图不变化 watck监听不到

        this.arr = [4,5,6,{name:"liu"}] //视图变化 watch可以监听到
        this.arr[3].name = "liu"; //视图变化 watch 深度监听可以监听到 
        this.$set(this.arr,0,100) //视图变化   watch可以监听到
        this.arr.splice(0,1,100) //视图变化 watch可以监听到
        let tempArr = [...this.arr];
        tempArr[0]=100;
        this.arr = tempArr; //临时变量中转 视图变化watch可以监听到

       //操作对象
       this.obj.class = "good" //视图不变化  watck监听不到
       delete this.obj.name //视图不变化  watck监听不到

        this.obj={name:"liu",age:18,sex:"女"} //视图变化  watch可以监听到
        this.obj.name = "liu" //视图变化  watch 深度监听可以监听到
        this.$delete(this.obj,"name") //视图更新 同this.$set() watch可以监听到
        this.$set(this.obj,"email","www") // 视图变化  watch可以监听到
        this.obj = Object.assign({},this.obj,{class:"goods"}) //视图变化  watch可以监听到
    },
  },
  watch: {
    arr(){
        console.log("arr变化了")
    },
    arr: {
      handler: function () {
        console.log("arr变化了");
      },
      deep: true,
    },

    obj() {
      console.log("obj变化了");
    },
    obj: {
      handler: function () {
        console.log("obj变化了");
      },
      deep: true,
    }
  },
};
</script>