模拟 Scoped CSS
在开发过程中使用热重载来保持状态
以下主要介绍Scoped CSS的原理.
Scoped CSS
大白话版本之 Scoped CSS 原理
通过 Webpack 调用 VueJS 中相应 Loader , 给组件HTML模板添加自定义属性 (Attribute) data-v-x, 以及给组件内CSS选择器添加对应的属性选择器 (Attribute Selector) [data-v-x], 达到组件内样式只能生效与组件内HTML的效果, 代码效果如下:
<div class='lionad' data-v-lionad></div>
<style>
.lionad[data-v-lionad] {
background: @tiger-orange;
}
</style>源码跟踪
Webpack 使用其它 CSS Loader 处理 VueJS 中对应 CSS 代码之前, Vue Loader 已经替我们做了一层简单的处理, 如果组件中 style 块包含了 scoped 属性:
<!-- 某个VueJS组件中 -->
<template>
<div class='lionad'></div>
</template>
<style lang="scss" scoped>
.lionad {
background: @tiger-orange;
}
</style>下代码即判断当前SFC对象样式块中是否有scoped属性, 并插入用于 query 中, 顺带一提, 每个单文件组件被解析后, 都会生成对应组件ID, ID主要以生产/开发环境做区分, 通过文件路径+源码或是文件路径的值作为哈希特征值的形式生成, 如下:
// vue-loader/index.js
const id = hash(isProduction (shortFilePath + 'n' + source) : shortFilePath)
const hasScoped = descriptor.styles.some(s => s.scoped)
const query = `? vue&type=template${idQuery}${scopedQuery}`
const request = templateRequest = stringifyRequest(src + query)
templateImport = `import { render, staticRenderFns } from ${request}`HTML模板处理
在用于处理SFC结构中HTML模板的 templateLoader 中, 我们可以得知, query 中所设置的参数将合并为 loader options 经由 Webpack 转交 templateLoader 再转交 @vue/component-compiler-utils.compileTemplate 处理:
// vue-loader/templateLoader.js
const query = qs.parse(this.resourceQuery)
const { id } = query
const compilerOptions = Object.assign({}, options.compilerOptions, {
scopeId: query.scoped ? `data-v-${id}` : null
})
const compiled = compileTemplate({ compilerOptions })实际 compileTemplate 函数在处理内容时, 编译函数使用的是 query 中的 compiler 或 vue-template-compiler, 后者会将模板文本转换成为 JavaScript 渲染函数, 大致如下:
从HTML模版转换为AST(虚拟语法树)
AST优化,处理静态模版与动态模板
生成JS函数,用于在运行时运行时生成纯HTML










