1.单向绑定 vs 双向绑定
单向绑定就是把Model绑定到View,即当我们用 JS 改变了Model ,那么View会进行自动更新。
相应的:
双向绑定就是在单向的基础上,再把View绑定到Model上。即如果用户交互改变了View,那么代码中的Model也会随之改变。
举个表单填写的栗子🌰:
// Vue
<template>
<div>
<label for="name">姓名:</label>
<input type="text" id="name" v-model="user.name" />
<p>您输入的姓名:{{ user.name }}</p>
</div
</template>
<script> export default {
data() {
return{
user: { name: ''}
}
} }
</script>
// React
function App() {
const [user, setUser] = useState({ name: '', email: '' });
const handleChange = (event) => {
setUser({ ...user, [event.target.name]: event.target.value });
};
return (
<div>
<label>姓名:</label>
<input type="text" name="name" value={user.name} onChange={handleChange} />
</div>
); }
export default App;
由上面两段代码可知,因为 Vue 是双向绑定,所以不需要额外创建handleChange函数来处理 onchange 事件,uesr.name 会自动更新,即可以直接获取到用户的输入;而 React 是单向绑定 ,所以就得用handleChange 作为 onchange 事件的回调函数来实时获取到用户的输入。
2. 双向数据绑定的实现原理
简单来说就是 数据劫持 + 发布订阅者模式
2.1 数据劫持
-
Vue2.0 采用 Object.defineProperty() 方法来劫持数据的 getter 和 setter。当数据发生变化时,setter 会被触发,vue 能够追踪到数据的变化并作出相应的反应。
-
Vue3.0 采用的是 ES6 的 Proxy 构造函数实现数据劫持
- Proxy 允许我们创建一个对象的代理,从而拦截并自定义该对象的一些基本操作。这为实现数据绑定、数据校验、日志记录等功能提供了强大的工具。
2.2 发布订阅模式
-
Vue 维护一个被称为"依赖收集器"的数据结构(dep对象),用于跟踪属性和视图之间的依赖关系。
- 每个属性都有一个对应的依赖收集器,它存储了所有依赖该属性的视图。
-
当用户进行一些交互操作改变了视图,比如表单输入、点击按钮。Vue 组件自己内部实现了监听这些交互事件,并进行数据更新。当数据发生变化时,Vue 又会自发通知dep对象,然后dep对象会通知所有订阅了该属性的 watcher 进行视图更新。
关于dep对象:
dep对象(依赖收集器),负责收集依赖于某个数据的 watcher。当数据发生变化时,dep 会通知订阅了该数据的所有 watcher ,触发更新。【每个响应式数据都会有一个dep实例】
关于watcher:
watcher(观察者)负责监听数据的变化并执行相应的操作,比如更新视图或计算属性。