vue修改编码_传统项目使用Vue时,为了提高性能需要修改Vue源码,可行吗?

更新:题主更新了题目描述,所以答案也相应做一下变动。使用一个 render 渲染出整个 DOM 树,则当任意变化发生时,肯定会重新 render 和 diff patch 整个组件的,这和 Watcher 机制没什么关系。看来你和你的项目经理根本连问题的方向都搞错了啊,你们对 Vue 的理解比我原本想象的还要糟糕,就别老想着改 Vue 源码了。(包括你最开始发的那张图也是错的,虽然在 Vue 1 里面数据是直接绑定到 directive 的,但是你们用的是 Vue 2,Vue 2 是基于 Virtual DOM 的)

几百个节点,指的是 DOM 节点吧?如果从业务组件的维度看,一个不可能需要这么多吧。如果一个组件由比较多的 DOM 节点组成,应该考虑如何把它抽象成一个 Vue 组件,这样才有可能避免无效 render.

每增加一个组件,应该生成一个 uuid 作为 key,不然当你插入或者删除一个组件的时候,Vue 在 diff 的时候无法正常进行新旧匹配,造成后面大量 DOM 的更新而严重影响性能。

每次用户操作,都让服务端重新下发一份新的 data,这个设计也明显是非常有问题的。当你使用一个全新的 data 替换旧 data,即使两个 data 长得一模一样,也会导致组件和子组件全部重新 render(除非组件的 prop 都是基本数据类型)。

以上 render 均指 vm 的 render,不表示 DOM 的更新。

以下是原答案:

你在截图里面提到了 shouldComponentUpdate,我就简单说一下 Vue 和 React 在避免无效 re-render 上的一些策略。

在 React 和 Vue 的 App 中,都需要解决一个问题:即当状态树的一部分变化时,如何让和这一部分状态有关的组件重新渲染,无关的组件不渲染。

React 是默认会始终渲染的(setState 之后组件和子组件都会重新渲染),但是提供了 shouldComponentUpdate 方法让用户自己实现,以决定某个组件是否要重新渲染。另外 React 也提供了 PureComponent 基类,它默认实现了 shouldComponentUpdate :如果 state 或者 props 未变化则不重新渲染。

而 Vue 也本身就默认有类似 PureComponent 的特性,但是更「智能」:如果组件渲染时使用到的 data 和 props 都没有改变,则不重新渲染。

但是 React 的 PureComponent 和 Vue 在这方面的实现原理是完全不同的:PureComponent 是基于 Immutable 思想的,任何对象或数组应该看做「值」。如果要更新一个值,应该返回一个新的值,不应该直接修改原值。这样就可以直接通过 === 判断前后两个值是否发生了变化。

Vue 则基于 getter setter 实现了一套 Reactivity System,通过 getter 建立 data 和 componentRender 之间的依赖关系,通过 setter 在修改数据之后触发 notify 执行 componentRender. 于是当数据变化时,只有依赖了这个数据的组件才会重新渲染,非相关组件并不会重新渲染。

这是 Vue 已经实现好的特性,你不能解决或者修复一个并不存在的问题。

回到你的问题上,假如有以下 demo 代码:

export default {

name: 'A',

data () {

return {

b: 1,

c: {name: 'Jack'},

}

},

}

当你将 data.b 修改为 2,父组件 A 和 子组件 B 都是会重新渲染的,而子组件 C 是不会重新渲染的。为什么父组件 A 也会重新渲染?因为是 A 的渲染依赖了 data.b (B 并不依赖 data.b,B 只是依赖 props.b)

而当你将 c.name 修改为 'Lucy' 时,只有组件 C 重新渲染了,因为只有 C 依赖了 c.name。

在第一种情况中,避免 A 组件重新渲染的方法是有的:把顶层组件的 data 移动到组件外部,比如使用 Vuex 的 store 中,然后子组件 B 和 C 直接从 store 中取数据,这样 A 不依赖状态,就不会重新渲染。

但是问题应该并非出在这里。如我前面所述,只有父组件的渲染是多余的,正常情况下其他兄弟组件并不会产生多余的渲染,不应该会对性能造成明显影响。你应该看看是不是其他地方出现了问题,比如更新数据的方式对不对,或者有没有其他一些隐藏的地方导致大量组件出现不必要的 unmount/mount 过程,或者纯粹是 App 树结构过于庞大。

先用调试工具 profile 一下,先把问题给真正定位出来。最好是把父组件和更新数据部分的代码贴一下。

Vue 的这套东西并不是没有缺陷,举几个例子:父组件通过字面量对象给子组件传递属性(),会导致每次父组件渲染都触发子组件渲染,理论上 Vue 本身是有办法解决这个问题的,即在编译期就把这种字面量转化为 computed properties. 但是开发者完全可以避免这种情况,即自行使用 computed 代替。

对于你能肯定不会变化的复杂数据结构,Vue 也会给它遍历绑上 setter getter,这是多余的,但是程序并不知道。对于这种类型的数据,我们可以使用 Object.feeze 把它冻结。

总之千万别想着把 Vue 源码改一下就能解决你的性能问题。因为首先 Vue 本身就有这种优化;其次是 Vue 已经迭代这么久了,要是真的有这种银弹,改几行 Watcher 的代码性能就蹭蹭蹭上去了,早就改了。最后是如果你真的对 Vue 细节有足够了解,能通过改 Vue 源码解决问题,那么也完全可以在你的应用代码里面进行优化(参考我说的例子)。

现实情况往往是你改了Watcher 之后性能没上去,BUG 倒折腾出了一堆。

你可能感兴趣的:(vue修改编码)