Open dailynodejs opened 3 years ago
https://github.com/vuejs/vue-next/blob/master/packages/compiler-sfc/src/stylePreprocessors.ts
export type PreprocessLang = 'less' | 'sass' | 'scss' | 'styl' | 'stylus'
export type StylePreprocessor = {
source: string,
map: RawSourceMap | undefined,
options: {
[key: string]: any,
additionalData?: string | ((source: string, filename: string) => string),
filename: string
},
customRequire: SFCStyleCompileOptions['preprocessCustomRequire']
} => StylePreprocessorResults
export const processors: Record<PreprocessLang, StylePreprocessor> = {
less,
sass,
scss,
styl,
stylus: styl
}
function getSource(
source: string,
filename: string,
additionalData?: string | ((source: string, filename: string) => string)
) {
if (!additionalData) return source
if (isFunction(additionalData)) {
return additionalData(source, filename)
}
return additionalData + source
}
const less: StylePreprocessor = (source, map, options, load = require) => {
const nodeLess = load('less')
// ...
}
https://github.com/vuejs/vue-next/blob/master/packages/compiler-sfc/src/cssVars.ts#L35
export const cssVarRE = /\bv-bind\(\s*(?:'([^']+)'|"([^"]+)"|([^'"][^)]*))\s*\)/g
export function parseCssVars(sfc: SFCDescriptor): string[] {
const vars: string[] = []
sfc.styles.forEach(style => {
let match
const content = style.content.replace(/\/\*([\s\S]*?)\*\//g, '')
while ((match = cssVarRe.exec(content))) {
const variable = match[1] || match[2] || match[3]
if (!vars.includes(variable)) {
vars.push(variable)
}
}
})
}
源码地址:https://github.com/vuejs/vue-next/blob/master/packages/compiler-sfc/src/cssVars.ts#L73
export function genCssVarsCode(
vars: string[],
bindings: BindingMetadata,
id: string,
isProd: boolean
) {
const varsExp = genCssVarsFromList(vars, id, isProd)
const exp = createSimpleExpression(varsExp, false)
const context = createTransformContext(createRoot([]), {
prefixIdentifiers: true,
inline: true,
bindingMetadata: bindings.__isScriptSetup === false ? undefined: bindings
})
}
https://github.com/vuejs/rfcs/blob/master/active-rfcs/0043-sfc-style-variables.md
.login-tips {
font-size: 12px;
line-height: 30px;
color: v-bind(color);
}
父容器:
多个的话:
父容器:
对应的 style
转换成 font_size
源码:https://github.com/vuejs/vue-next/blob/master/packages/compiler-sfc/src/cssVars.ts#L103
export const CSS_VARS_HELPER = `useCssVars`
export function genNormalScriptCssVarsCode(
cssVars: string[],
bindings: BindingMetadata,
id: string,
isProd: boolean
): string {
return (
`\nimport { ${CSS_VARS_HELPER} as _${CSS_VARS_HELPER} } from 'vue'\n` +
`const __injectCSSVars__ = () => {\n${genCssVarsCode(
cssVars,
bindings,
id,
isProd
)}}\n` +
`const __setup__ = __default__.setup\n` +
`__default__.setup = __setup__\n` +
` ? (props, ctx) => { __injectCSSVars__(); return __setup__(props, ctx) }\n` +
` : __injectCSSVars__\n`
)
}
编译之后:
import { useCssVars as _useCssVars } from '/node_modules/.vite/vue.js?v=e62380f6'
const __injectCSSVars__ = () => {
_useCssVars(_ctx => ({
"26084dc2-font_size": (_ctx.font.size),
"26084dc2-color": (_ctx.color)
}))}
https://github.com/vuejs/vue-next/blob/master/packages/runtime-dom/src/helpers/useCssVars.ts#L17
父元素是如何加上 style 的
function setVarsOnNode(el: Node, vars: Record<string, string>) {
if (el.nodeType === 1) {
const style = (el as HTMLElement).style
for (const key in vars) {
style.setProperty(`--${key}`, vars[key])
}
}
}
key 生成的规则 https://github.com/vuejs/vue-next/blob/master/packages/compiler-sfc/src/cssVars.ts#L27
上面提到的 - 变 _
用到了工具包 hash-sum:
https://github.com/bevacqua/hash-sum
import hash from 'hash-sum'
function genVarName(id: string, raw: string, isProd: boolean): string {
if (isProd) {
return hash(id + raw)
} else {
return `${id}-${raw.replace(/([^\w-])/g, '_')}`
}
}
源码地址:https://github.com/vuejs/vue-next/tree/master/packages/compiler-sfc
facade module looks like this: