响应式原理
vue3 中只需要如下的代码即可实现表单联动:
1 2 3 4 5 6 7 8 9
| <script> let text = ref('default') </script> <template> <div <input v-model="text"> <p>content: {{text}} </p> </div> </template>
|
以下是一个响应式的简单实现:
1 2 3 4 5 6 7 8 9 10 11 12
| <input type="text" id="input"> <p id="content"></p> <script> const obj = {} Object.defineProperty(obj, 'content', { set(newValue){ document.getElementById('input').value = newValue document.getElementById('content').innerHTML = newValue } }) document.addEventListener('keyup', e => obj.content = e.target.value) </script>
|
核心是使用 Object.defineProperty
函数实现双向数据绑定,触发组件的重新渲染
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| global.__fn = null
const observe = (obj) => { for (const k of Object.keys(obj)) { let internalValue = obj[k] let funs = new Set() Object.defineProperty(obj, k, { get(){ if (global.__fn) { funs.add(global.__fn) } return internalValue }, set(v){ internalValue = v for (const fn of funs) { fn() } } }) } }
const autorun = fn => { global.__fn = fn fn() global.__fn = null }
const obj = {name: 'why', age: 18} observe(obj) console.log(obj.name, obj.age) autorun(() => { console.log('重新渲染 name',obj.name) }) autorun(() => { console.log('重新渲染 age',obj.age) })
obj.name = 'kobe' obj.age = 19
console.log('------'); const o = Object.create(Object.prototype) console.log(o);
|
Vue 2.0 和 3.0 的区别
- 移除了过滤器,推荐使用计算属性和方法。