Menyelam dalam prinsip responsif


.

Baris gilir kemas kini tak segerak

var vm = new Vue({
  data:{
    a:1
  }
})

// `vm.a` 是响应式的

vm.b = 2
// `vm.b` 是非响应式的

Vue tidak membenarkan menambahkan sifat reaktif peringkat akar secara dinamik pada kejadian yang telah dibuat. Walau bagaimanapun, anda boleh menambah sifat reaktif pada objek bersarang menggunakan kaedah Vue.set(object, propertyName, value). Contohnya, untuk:

Vue.set(vm.someObject, 'b', 2)

Anda juga boleh menggunakan kaedah contoh vm.$set, yang juga merupakan alias untuk kaedah Vue.set global:

this.$set(this.someObject,'b',2)

Kadangkala anda mungkin perlu menetapkan berbilang sifat baharu pada objek sedia ada, seperti menggunakan Object.assign() atau _.extend(). Walau bagaimanapun, sifat baharu yang ditambahkan pada objek dengan cara ini tidak akan mencetuskan kemas kini. Dalam kes ini, anda harus mencipta objek baharu daripada objek asal bersama-sama dengan sifat objek yang anda ingin gabungkan. Object.assign()_.extend()。但是,这样添加到对象上的新属性不会触发更新。在这种情况下,你应该用原对象与要混合进去的对象的属性一起创建一个新的对象。

// 代替 `Object.assign(this.someObject, { a: 1, b: 2 })`
this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })

也有一些数组相关的注意事项,之前已经在列表渲染中讲过。


声明响应式属性


由于 Vue 不允许动态添加根级响应式属性,所以你必须在初始化实例前声明所有根级响应式属性,哪怕只是一个空值:

var vm = new Vue({
  data: {
    // 声明 message 为一个空值字符串
    message: ''
  },
  template: '<div>{{ message }}</div>'
})
// 之后设置 `message`
vm.message = 'Hello!'

如果你未在 data 选项中声明 message,Vue 将警告你渲染函数正在试图访问不存在的属性。

这样的限制在背后是有其技术原因的,它消除了在依赖项跟踪系统中的一类边界情况,也使 Vue 实例能更好地配合类型检查系统工作。但与此同时在代码可维护性方面也有一点重要的考虑:data 对象就像组件状态的结构 (schema)。提前声明所有的响应式属性,可以让组件代码在未来修改或给其他开发人员阅读时更易于理解。


异步更新队列


可能你还没有注意到,Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非常重要的。然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。Vue 在内部对异步队列尝试使用原生的 Promise.thenMutationObserversetImmediate,如果执行环境不支持,则会采用 setTimeout(fn, 0) 代替。

例如,当你设置 vm.someData = 'new value',该组件不会立即重新渲染。当刷新队列时,组件会在下一个事件循环“tick”中更新。多数情况我们不需要关心这个过程,但是如果你想基于更新后的 DOM 状态来做点什么,这就可能会有些棘手。虽然 Vue.js 通常鼓励开发人员使用“数据驱动”的方式思考,避免直接接触 DOM,但是有时我们必须要这么做。为了在数据变化之后等待 Vue 完成更新 DOM,可以在数据变化之后立即使用 Vue.nextTick(callback)

<div id="example">{{message}}</div>

Terdapat juga beberapa pertimbangan berkaitan tatasusunan, yang telah dibincangkan sebelum ini dalam Perenderan senarai Lulus. 🎜🎜
🎜

Isytiharkan atribut responsif

< jam />🎜Memandangkan Vue tidak membenarkan penambahan dinamik sifat reaktif peringkat akar, anda mesti mengisytiharkan semua sifat reaktif peringkat akar sebelum memulakan tika, walaupun ia hanya nilai nol:
🎜
var vm = new Vue({
  el: '#example',
  data: {
    message: '123'
  }
})
vm.message = 'new message' // 更改数据
vm.$el.textContent === 'new message' // false
Vue.nextTick(function () {
  vm.$el.textContent === 'new message' // true
})
🎜Jika anda bukan dalam mesej dalam pilihan >data, Vue akan memberi amaran kepada anda bahawa fungsi pemaparan cuba mengakses sifat yang tidak wujud. 🎜🎜Terdapat sebab teknikal di sebalik sekatan ini Ia menghapuskan jenis sarung tepi dalam sistem penjejakan kebergantungan dan juga membolehkan kejadian Vue berfungsi dengan lebih baik dengan sistem semakan jenis. Tetapi pada masa yang sama terdapat pertimbangan penting dari segi kebolehselenggaraan kod: data objek adalah seperti skema keadaan komponen. Mengisytiharkan semua sifat reaktif di hadapan menjadikan kod komponen lebih mudah difahami apabila ia diubah suai pada masa hadapan atau dibaca oleh pembangun lain. 🎜🎜
🎜

Baris gilir kemas kini tak segerak


🎜Mungkin anda tidak perasan bahawa Vue melaksanakan secara tidak segerak semasa mengemas kini DOM. Selagi ia mendengar perubahan data, Vue akan membuka baris gilir dan menampan semua perubahan data yang berlaku dalam gelung peristiwa yang sama. Jika pemerhati yang sama dicetuskan beberapa kali, ia hanya akan ditolak ke dalam baris gilir sekali. Penyahduaan ini semasa penimbalan adalah penting untuk mengelakkan pengiraan dan operasi DOM yang tidak perlu. Kemudian, pada gelung acara seterusnya "tanda", Vue mengepam baris gilir dan melaksanakan kerja sebenar (pendua). Vue secara dalaman cuba menggunakan Promise.then asli, MutationObserver dan setImmediate untuk baris gilir tak segerak Jika persekitaran pelaksanaan tidak menyokongnya, setTimeout(fn, 0) sebaliknya. 🎜🎜Sebagai contoh, apabila anda menetapkan vm.someData = 'new value', komponen tidak akan dipaparkan semula serta-merta. Apabila baris gilir disiram, komponen dikemas kini pada gelung acara seterusnya "tandakan". Selalunya kita tidak perlu risau tentang proses ini, tetapi jika anda ingin melakukan sesuatu berdasarkan keadaan DOM yang dikemas kini, ia boleh menjadi agak rumit. Walaupun Vue.js secara amnya menggalakkan pembangun untuk berfikir dengan cara "didorong data" dan mengelakkan hubungan langsung dengan DOM, kadangkala kita perlu berbuat demikian. Untuk menunggu Vue selesai mengemas kini DOM selepas data berubah, anda boleh menggunakan Vue.nextTick(panggilan balik) sejurus selepas data berubah. Dengan cara ini fungsi panggil balik akan dipanggil selepas kemas kini DOM selesai. Contohnya: 🎜
Vue.component('example', {
  template: '<span>{{ message }}</span>',
  data: function () {
    return {
      message: '未更新'
    }
  },
  methods: {
    updateMessage: function () {
      this.message = '已更新'
      console.log(this.$el.textContent) // => '未更新'
      this.$nextTick(function () {
        console.log(this.$el.textContent) // => '已更新'
      })
    }
  }
})
methods: {
  updateMessage: async function () {
    this.message = '已更新'
    console.log(this.$el.textContent) // => '未更新'
    await this.$nextTick()
    console.log(this.$el.textContent) // => '已更新'
  }
}

Amat mudah untuk menggunakan kaedah contoh vm.$nextTick() dalam komponen kerana ia tidak memerlukan Vue global dan ini dalam fungsi panggil balik > Akan diikat secara automatik pada contoh Vue semasa: vm.$nextTick() 实例方法特别方便,因为它不需要全局 Vue,并且回调函数中的 this 将自动绑定到当前的 Vue 实例上:

rrreee

因为 $nextTick() 返回一个 PromiserrreeeOleh kerana $nextTick() mengembalikan objek Promise, jadi anda boleh menggunakan objek baharu ES2016 async/menunggu

Sintaks mencapai perkara yang sama:

rrreee

🎜