vue首次赋值不触发watch及watch和computed的区别

watch的使用

template中

 <div>名字:{{name}},年龄:{{age}}</div>

script中

 export default {
     props: {  name: String  },
     data() {  return {  age: 10  } },
     watch: {
         name(newValue, oldValue) {},
         age(newValue, oldValue) {}
     },
 }

这种情况通过watch监听的数据,当字段被第一次赋值时是不会执行监听函数的。只有值再次发生改变才会执行监听。那如何才能在第一次赋值时就执行监听函数呢?这里就需要用到immediate和handler

immediate和handler使用

在选项参数中指定 immediate: true 将立即以表达式的当前值触发回调
也就是说immediate值为true,则首次赋值时就执行handler函数,immediate值为false,则首次赋值时就不执行handler函数

 watch: {
     name: {
         handler(newValue, oldValue) {},
         immediate: true,
     },
     age: {
         handler(newValue, oldValue) {},
         immediate: true,
     },
 }

首次赋值监听时,oldValue值为undefined

deep 深度监听

当需要监听一个对象的改变时(注意这里监听的是整个对象),正常的watch无法监听到对象内部属性的改变,此时需要使用deep对对象进行深度监听

父组件

  people:{
      name:"露西"
  }

  btnClick() {
     this.people.name = "宙斯";
  }

子组件

  props: {
      people: {
          type: Object,
          //对象或数组的默认值必须从一个工厂函数返回。
          default: () => ({
              name: ""
          })
      }
  },
  watch: {
      people: {
          handler(newValue, oldValue) {
          },
          // immediate: true,  加上则首次也监听
          deep: true, //必须加上才能监听到people的变化
      },
  },

当对一个对象进行监听时,需要添加deep:true属性,此时修改对象内任意属性值都会被监听到。如果只想对对象中某一个属性进行监听,则可以使用字符串的形式监听对象某一个属性,如:

  watch: {
       'people.name': {
           handler(newValue, oldValue) {},
           deep: true,
       },
  }

deep和immediate可同时使用,表示首次绑定就触发监听函数

注意事项

1:数组的变动可直接进行监听,不需要deep属性,操作如下,若首次监听则需加immediate: true

  this.list.unshift({name: "宙斯"}) //添加到数组头部
  this.list.push({name: "宙斯"}) //添加到数组尾部

  this.list.shift() //删除数组头部一个元素
  this.list.pop() //删除数组尾部一个元素

  this.$set(this.list, 0, {name:"宙斯"}); //修改数组角标为0的数据

数组的splice方法,可用于插入、删除、替换操作,具体操作可移步到前端杂谈之splice用法

2:通过props传递对象或数组时,对象或数组的默认值必须从一个工厂函数返回,否则就会报

Invalid default value for prop “xxx”: Props with type Object/Array must use a factory function to return the default value.

  people: {
     type: Object,
     default: ()=>{}
  }

  list: {
     type: Array,
     default: ()=>[]
  }

props传递对象时,未传递的字段如何使用默认值

1:通过computed计算属性再定义一个对象,再用assign合并默认值和传递的对象,组件内则使用新定义的对象来展示数据,如

子组件

  <div> 姓名:{{privatePeople.name}} 年龄:{{privatePeople.age}} </div>

  props: {
      people: {
          type: Object,
          //数组/对象的默认值应当由一个工厂函数返回
          default: () => {}
      }
  },

  computed: {
      privatePeople() {
          let defaultPeople = {
              name: "露西",
              age: 10
          };
          return Object.assign({}, defaultPeople, this.people);
      }
  },
2:使用不带参数的v-bind=xxx

父组件

  <watch-components v-bind=people></watch-components>

  people: {
      name: "宙斯"
  }

子组件

  props: {
      name:{
          type:String,
          default:"露西"
      },
      age:{
          type:Number,
          default: 10
      }
  }
3:使用vuex对状态进行统一管理,子组件通过computed的计算属性获取存储在store中的变量

computed、watch、methods的区别和使用

computed计算属性-引用官网的示例

可监听data和props中的属性

主要用于当一些数据需要随着其它数据变动而变动时使用。如:购物车总金额

  computed: {
    fullName: function () {
      return this.firstName + ' ' + this.lastName
    }
  }
特点
1:计算属性是基于它们的响应式依赖进行缓存的。只在 相关响应式依赖 发生改变时它们才会重新求值。也就是说当computed函数所依赖的属性值没有发生改变时,调用的结果就会从缓存中读取。

这也同样意味着下面的计算属性将不再更新,因为 Date.now() 不是响应式依赖:

  computed: {
    now: function () {
      return Date.now()
    }
  }
2:计算属性必须有return返回
watch侦听属性-引用官网的示例

可监听data和props中的属性
主要用于当需要在数据变化时执行异步或开销较大的操作时使用,如搜素框

  watch: {
    question(newValue, oldValue) {
      this.axios() //执行异步逻辑
    }
  }
特点
1:watch中的函数名称必须和data或props中的属性名称一致
2:watch中函数有两个参数,第一个是newValue新值,第二个是oldValue旧值。
methods:函数方法

主要用于写一段业务逻辑

区别
  • computed计算属性结果会被缓存,只有依赖的属性发生改变才会重新计算,主要用于当一些数据需要随着其它数据变动而变动时使用
  • watch侦听属性用来侦听对象或属性的变化,然后执行对应回调,回调函数内主要用于执行某些业务逻辑,如异步操作或开销较大的操作
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Vue.js 中的 `watch` 选项默认是同步执行的,但是如果你在 `watch` 回调函数中进行异步操作时,可能会遇到赋值异步的问题。这是因为 JavaScript 中的异步操作,例如 `setTimeout` 和 `fetch` 等,会先于同步代码执行完毕,所以当异步操作完成时,`watch` 回调函数可能已经执行完毕,并且已经将新值赋值给了对应的数据。 为了解决这个问题,Vue.js 提供了一个 `$nextTick` 方法,可以让回调函数在 DOM 更新之后再执行。你可以在 `watch` 回调函数中使用 `$nextTick` 方法来确保赋值异步操作的正确性,例如: ```javascript watch: { myData: { handler(newValue) { // 异步操作,例如 fetch fetch('/api/data').then(res => { // 赋值异步 this.myData = res.data; // 在下一个 tick 中执行回调函数 this.$nextTick(() => { console.log('myData 已更新'); }); }); }, immediate: true, }, }, ``` 在上面的例子中,当 `myData` 的值发生改变时,`handler` 回调函数会执行异步操作,并在异步操作完成后将新值赋值给 `myData`。然后,在下一个 tick 中,`$nextTick` 方法会执行回调函数并打印出 `'myData 已更新'`。这样就能确保赋值异步操作的正确性了。 ### 回答2: 在Vue中,watch选项是用来监听数据变化的,常用于对数据的变化做一些逻辑处理或者触发一些副作用操作。当我们在watch选项中赋值时,它的执行是异步的。 具体来说,当我们给watch选项赋值时,这个赋值操作会将要执行的回调函数添加到一个队列中,等到代码执行完毕之后再去执行这个队列中的回调函数。这样可以避免频繁的执行计算属性或者渲染组件,优化性能。 例如,我们有一个data属性名为count,同时有一个watch选项监听了count的变化: ``` data: { count: 0 }, watch: { count: function() { this.asyncFn(); } }, methods: { asyncFn: function() { setTimeout(function() { console.log(this.count); }, 1000); } } ``` 当我们修改count的值时,比如点击按钮来改变count的值,那么watch回调的执行会被推迟到下一个事件循环中,也就是说,在按钮的点击事件处理函数执行完之后,watch回调才会被执行。 这种异步的执行机制使得我们可以更好地控制代码的执行时机,避免了一些不必要的重复执行,提升了代码的性能。但同时也要注意,在异步的情况下,我们可能会遇到一些问题,比如依赖顺序的问题,这时我们可以使用Vue提供的nextTick方法来解决。 ### 回答3: 在vue中,watch属性是用于监听数据变化的。当数据变化时,watch会自动执行对应的响应函数。一般情况下,watch赋值是同步的,也就是说,当数据改变时,watch会立即执行相应的函数。 然而,在某些情况下,我们可能会遇到watch赋值异步的情况。具体来说,当我们在watch中对数据进行赋值操作时,有时候这个赋值操作可能是异步的,也就是说,watch函数并不会立即执行,而是等待赋值操作完成后再执行。 为什么会出现watch赋值异步的情况呢?这主要是由于vue的响应式系统机制所致。在vue中,数据的变化会触发一系列的操作,包括触发getter和setter函数、重新渲染组件等。而这些操作是在vue的下一个事件循环中执行的,也就是说,赋值操作在当前的事件循环中并不会立即生效,而是需要等待下一个事件循环才能生效。 对于这种情况,我们可以采用一些方法来确保watch赋值操作是同步的。例如,可以在watch函数中使用$nextTick方法来延迟执行异步操作,确保赋值操作生效。另外,也可以使用computed属性来替代watch属性,因为computed属性的赋值操作是同步的。 总之,虽然在某些情况下watch赋值是异步的,但我们可以通过一些手段来确保watch赋值操作是同步的,以满足我们的需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值