的问题导致了问题。首先,让我们来回答这样一个问题。这是完整的jsfiddle演示或codepen演示,用于将两种边框样式绑定到一个元素,右侧和底部有1px的红色边框styleA:{borderBottom:'1pxsolidred',borderRight:'1pxsolidred'};然后使用按钮(或其他)将样式更改为以下样式,1px绿色边框和1px红色右边框。styleB:{border:'1pxsolidgreen',borderRight:'1pxsolidred'};预期的结果应该是右边的边框是红色的,其他三边的边框是绿色的,但是实际的结果是所有的边都是绿色的,这里已经有问题了,再点击按钮切换样式回来了。这时候预期的结果应该和一开始一样:右边和底部出现1px的红色边框,但实际结果只是下底边框是红色的,右边的边框好像消失了。那么,右边的边框样式真的没有了吗?它从第一个开关消失了吗?(这似乎与第一个绿色边框的表现一致)。这是一个CSS错误吗?这个样式替换过程是在Vue中为我们实现的,它与虚拟节点vNode的渲染有关。接下来我们去Vue的源码看看这个问题是怎么造成的。vue更新视图机制首先,vue视图的更新是通过updateComponent进行的,updateComponent会执行一个update方法来更新视图,update会从根节点开始进行patch操作,patch操作会遍历vnode的所有vnode节点虚拟节点树依次生成,深度优先遍历方式。通常补丁操作会更新以下部分:?updateAttrs(oldVnode,vnode)1:?updateClass(oldVnode,vnode)2:?updateDOMListeners(oldVnode,vnode)3:?updateDOMProps(oldVnode,vnode)4:?updateStyle(oldVnode,vnode)5:?update(oldVnode,vnode)6:?updateDirectives(oldVnode,vnode)这里我们只需要关注第五个方法:updateStyle,那么这个方法中做了什么?看一下核心逻辑:可以看到这段代码的主要逻辑是用新样式覆盖旧样式。这里的setProp是修改element.style,它是原生CSSStyleDeclaration对象的一个??实例。先将newStyle中不存在的oldStyle样式设置为'',再将不等于oldStyle中样式值的newStyle样式设置。看起来没有问题,一切顺理成章,那么是什么原因造成了毛布的上述现象呢?一切的罪魁祸首都在于这种边框样式的速记属性。速记属性有什么特别之处?最直接的就是赋速记属性的时候,例如:border:1pxsolidgreen;此分配将转换为:borderWidth:"1px"borderStyle:"solid"borderColor:"green"borderTop:"1pxsolidgreen"borderTopColor:"green"borderTopStyle:"solid"borderTopWidth:"1px"borderRight:"1pxsolidgreen""borderRightColor:"green"borderRightStyle:"solid"borderRightWidth:"1px"borderLeft:"1pxsolidgreen"borderLeftColor:"greenStyle"border:"solid"borderLeftWidth:"1px"borderBottom:"1pxsolidgreen"borderBottomColor:"green"borderBottomStyle:"solid"borderBottomWidth:"1px"也就是说borderTop、borderLeft、borderRight、borderBottom都是赋值。原因分析那么,回到上面的切换过程,根据updateStyle的源码分析:从styleA切换到styleB时,第一个for循环,borderBottom不在oldStyle中,被清除,borderRight在oldStyle中,保留。在第二次for循环中,border不在oldStyle中,设置border的值,注意此时borderTop、borderLeft、borderRight、borderBottom也被赋值,然后borderRight等于oldStyle中保留的值,跳过本次赋值。最终的结果是borderTop、borderLeft、borderRight、borderBottom都显示了border的值。当从styleB切换回styleA时,在第一个for循环中,border不在oldStyle中,border的值被清空。这时候borderTop,borderLeft,borderRight,borderBottom也清空了,然后borderRight在oldStyle中,跳过这个赋值。在第二次for循环中,borderBottom不在oldStyle中,borderBottom被赋值,borderRight等于oldStyle中保留的值。跳过这个赋值,最后的结果只有borderBottom的值。解决方案那么,原理清楚了,什么是好的解决方案呢?这个问题已经在Vue的githubissue上提出了。见游玉玺官方回复。这个问题被定性为一个wontfix,但是也给出了一个有效的解决方案:给这个元素一个style生成的hash值。作为key,当样式有任何变化时,key也会发生变化。在Vue的更新渲染逻辑中,如果元素的key改变了,那么oldstyle就是一个空对象,就不会出现上面的问题。
