uni-app 运行时揭秘:styleIsolation 的转化
背景
大家好,我是 uni-app 的核心开发 前端笨笨狗。本篇是 uni-app 源码分析的第三篇文章,欢迎关注!
前两天有开发者在群里面问我 uni-app 中如何配置 styleIsolation,我告诉了他正确的配置方案,也计划写篇文章揭秘 uni-app 是如何通过运行时将开发者的配置转化为原生微信小程序的配置。
指南
选项式
在 uni-app 中,开发者可以通过在页面组件中添加 options 配置项来设置 styleIsolation,示例如下:
<script>
export default {
name: 'MyComp',
options: {
styleIsolation: 'isolated'
},
}
</script>
<script>
import { defineComponent } from "vue";
export default defineComponent({
name: "MyComp",
options: {
styleIsolation: "isolated",
},
});
</script>
组合式
在使用组合式 API 的页面组件中,开发者同样可以通过 defineOptions 来设置 styleIsolation,示例如下:
<script setup>
defineOptions({
name: 'MyComp',
options: {
styleIsolation: 'isolated'
}
})
</script>
原理
createComponent 这个函数大家如果看过 vue 文件的 js 编译产物就一定不会陌生,比如
<script setup>
defineOptions({
options: {
styleIsolation: "shared",
},
});
</script>
会被编译为
const _sfc_main = {
__name: "comp",
options: {
styleIsolation: "shared"
}
setup(__props) {
return (_ctx, _cache) => {
return {};
};
}
};
wx.createComponent(_sfc_main);
也就是 script 中写的代码会被编译成一个对象,这个对象就是 vue 组件的配置项,而微信小程序又不认识 vue 组件的配置项,那么怎么把 vue 组件的配置项转化为微信小程序的配置项呢?这就要靠 uni-app 的运行时了,在 common/vendor.js 中,createComponent 函数会调用 parseComponent 函数来解析 vue 组件的配置项,parseComponent 的返回值就是微信小程序组件的配置项,也就是 Component 构造器 的参数,可以用来构造小程序原生组件。
function initCreateComponent() {
return function createComponent(vueComponentOptions) {
return Component(parseComponent(vueComponentOptions));
};
}
const createComponent = initCreateComponent();
wx.createComponent = createComponent;
当 parseComponent 解析到页面组件时,会检查组件的 options 配置项,如果发现 styleIsolation,就会将其转化为微信小程序的配置项。
function parseComponent(vueOptions) {
vueOptions = vueOptions.default || vueOptions;
const options = {
multipleSlots: true,
// styleIsolation: 'apply-shared',
addGlobalClass: true,
pureDataPattern: /^uP$/
};
// 将开发者在 options 中设置的配置项转化为微信小程序的配置项
if (vueOptions.options) {
Object.assign(options, vueOptions.options);
}
const mpComponentOptions = {
options,
// 省略其他配置项
};
return mpComponentOptions;
}
这样一来,开发者在页面组件中设置的 styleIsolation 就会被正确地转化为微信小程序的配置项,从而自由控制样式隔离。