【Vue2】5. 渲染class/style属性

289 阅读2分钟

概述

前端页面一般都是 JS 负责逻辑控制,样式、布局等由CSS负责,而 CSS 的一般都是通过 class 和 style来作用于 html 的。 接下来探索一下一下 Vue2 中 class 和 style 的实现细节,代码详情class/style的渲染,主要源码是在 src/modules 目录下面

DEMO展示

App.vue

<template>
  <div class="msg" :class="className" :style="styleObj">
    {{message}}
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      message: '我是一个组件',
      className: 'test',
      styleObj: {
        color: '#f00'
      }
    }
  }
}
</script>

<style>
  .msg {
    font-size: 14px;
  }
  .test {
    background: rebeccapurple;
  }
  .t1 {
    background: rosybrown;
  }
</style>

class渲染demo:

style渲染demo:

过程解析

class/style的渲染都分为两个两个场景: 首次创建、动态更新。之所以分为这两个场景是因为真好对应了 Vue 在渲染元素的各个周期(大致有5个create、active、update、remove、destroy),创建阶段会生成元素,动态更新时,会检测哪些内容需要更新,然后按需更新,也就是diff检测,避免冗余的一些dom操作。

大致过程为:

其中 createElement 和 patchNode 都是 vdom 中的 patch(可以理解就是diff)干的活,两个阶段分别会调用相关的hook。各个阶段的hook结构为:

{
  create: [],
  activate: [],
  update: [],
  remove: [],
  destroy: []
}

而class/style都会提供各个生命周期的回调函数,以class渲染为为例,导入的实现如下:

{
  create: updateClass,
  update: updateClass
}

updateClass会将目标编译之后的 staticClass 和 class 两个属性拼接为为一个字符串:

然后将改字符串通过el.setAttribute('class', xxx)形式设置到真实的dom结构上面。

而针对style也类似,不过style设置,可以使用两种方式设置:

el.style.setProperty(name, val) // 支持第三个参数,故可以设置 important
// 或者
el.style[name] = val

总结

对应class/style, 在编译Vue模板时就会区分 static、动态类型,像class分为 staticClass 和 class,我理解这样区分还是处于一个性能的考虑,如果只有staticClass,可以只需要简单处理则可。

Vue在渲染元素预留好各个阶段的回调,通过插件形式,以一种低耦合的形式实现了对class/style的支持,同时像 attrs/ref/events等都是通过这种方式实现的。