uni-app 运行时揭秘:styleIsolation 的转化

74 阅读2分钟

背景

大家好,我是 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 就会被正确地转化为微信小程序的配置项,从而自由控制样式隔离。

交流群

有想加入 uniapp 交流群的群友,可以扫评论区的微信二维码进群