网站内容更新机制(Vue和React的其中最重要的区别是什么?)
优采云 发布时间: 2021-10-15 10:37网站内容更新机制(Vue和React的其中最重要的区别是什么?)
Vue 和 React 之间最重要的区别之一是它们管理数据更新的方式不同。Vue 基本上是一套基于 getter/setter 的订阅机制,依赖集合/依赖更新,而 React 使用显式的 Trigger 函数调用来更新数据,比如 setState。相比之下,Vue 的实现更细粒度。通过依赖集合,Vue 可以知道哪些数据更新需要重新计算。通过这种机制,Vue 可以优雅地实现计算属性,观察,包括 View 渲染。由于缺少这种细粒度的机制,React 往往需要一些其他的解决方案来提高性能,因此产生了诸如 PureComponent、ImmutableJS、shouldComponentUpdate 等钩子。
Vue 和 React 如何更新视图?
不同的是Vue知道组件数据中的value字段已经更新了,而React只知道组件的State发生了变化,并不知道哪些数据发生了变化。
Vue 的视图重新渲染
Vue 的订阅机制决定了它不仅知道更新了哪些数据,还知道更新数据后是否需要重新渲染当前组件和子组件的视图。这是通过“依赖采集”实现的。Vue 的视图模板会被编译成一个render 函数,并且在数据(data/props/computed)中定义了一个getter。每次调用各个组件的render函数,通过getter就可以知道哪些数据依赖哪些组件的views,下次给这些数据赋值,也就是调用setter,对应的view可以触发重新渲染,无关组件不需要再次调用render函数,节省开销。借用Vue作者做的图:(他称之为推送更新)
例如:子组件Child使用propsvalue进行渲染,父组件Parent将datavalue作为props传递给子组件Child,一秒后更新数据。
// Child.vue
export default {
name: "Child",
props: ["value"],
render(h) {
console.log("Child render");
return h("div", this.value);
}
};
// Parent.vue
import Child from "./components/Child";
export default {
data() {
return {
value: 1
};
},
components: { Child },
created() {
setTimeout(() => this.value = 2, 1000);
},
render(h) {
console.log("Parent render");
return h("div", [
h(Child, {
props: { value: this.value }
})
]);
}
};
复制代码
控制台打印:
Parent render
Parent render
//after 1000ms
Child render
Child render
复制代码
由于 Parent 组件和 Child 组件的视图都使用了 Parent 的 datavalue,因此更改 value 的值会导致父子组件重新渲染。
情况二:值不作为props传递给子组件Child,只用于组件自身的视图:
// Child.vue
export default {
name: "Child",
props: ["value"],
render(h) {
console.log("Child render");
return h("div", this.value);
}
};
// Parent.vue
import Child from "./components/Child";
export default {
data() {
return {
value: 1
};
},
components: { Child },
created() {
setTimeout(() => this.value = 2, 1000);
},
render(h) {
console.log("Parent render");
return h("div", [
h(Child),
this.value + ""
]);
}
};
复制代码
控制台打印:
Parent render
Child render
//after 1000ms
Parent render
复制代码
改变值后,父组件重新渲染,但是子组件没有重新渲染,因为子组件的render函数没有采集父组件数据值的依赖。
反应重新渲染
当 setState 被调用时,React 并不关心哪些数据发生了变化,然后触发了组件的 shouldComponentUpdate。如果返回true,则调用render,然后以相同的方式更新所有子组件。如果返回 false,则阻止渲染方法调用和子组件。更新。也就是说更新视图的控制是由shouldComponentUpdate控制的,这个方法默认返回true。(Vue 作者称之为拉取更新):
看一个例子:
function Child(props) {
console.log("Child render");
return ;
}
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
value: 1
};
}
componentDidMount() {
setTimeout(() => {
this.setState({
value: 2
});
}, 1000);
}
render() {
console.log("Parent render");
return (
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(, rootElement);
复制代码
控制台打印:
Parent render
Child render
Parent render
Child render
复制代码
即使视图不使用任何数据,调用 setState 的组件及其子组件也会重新渲染。当组件或节点较多时,更新数据可能会造成大量不必要的虚拟DOM构建,庞大的节点树也拖慢了diff的速度。这时候需要引入一些优化方案,比如 PureComponent 和 ImutableJS,PureComponent 使用 props 和 state 的浅比较来决定是否重新渲染。如果浅比较的结果相等,则组件及其子组件将不参与重新渲染。