Skip to content

Vue 命令式组件实践

​ 以往封装的命令式组件往往都是通过 h 和 render,临时渲染的组件,并且文件拆分成了几个(函数文件、组件文件、样式文件),非常零散。

​ 这一次可以通过 jsx+css-in-js(@styils/vue)实现一个文件即可完成命令式组件的封装 @styils/vue: https://styils.github.io/styils/

tsx
import { Component, createApp } from "vue";
import "./index.css"; //这个只是真实DOM的样式,其实也可以不使用,将其封装成组件也可以。
// css-in-js的vue插件
import { styled } from "@styils/vue";

// 配置了样式的组件元素
// styled会创建一个组件,在传入参数时可以选择组件的tagName和对应样式,并且最终渲染时会通过class选择器给元素配置样式的。
// 消息容器
const BoxContainer = styled("div", {
  backgroundColor: "#fff",
  borderRadius: "5px",
  height: "150px",
  width: "80%",
  maxWidth: "500px",
  padding: "10px",
  boxSizing: "border-box",
});
// 按钮
const ConfirmButton = styled("button", {
  border: "none",
  padding: "5px 10px",
  backgroundColor: "skyblue",
  color: "#fff",
  cursor: "pointer",
});

// 组件配置项
const MessageBox: Component = {
  // 自定义熟悉
  props: {
    title: {
      type: String,
      required: true,
    },
  },
  // 定义的方法
  methods: {
    onHandleClick() {
      this.$emit("toClose");
    },
  },
  // 自定义事件
  emits: ["toClose"],
  // 组件的render函数
  render(ctx: any) {
    return (
      <BoxContainer>
        <div class="content">{ctx.title}</div>
        <ConfirmButton onClick={ctx.onHandleClick}>确认</ConfirmButton>
      </BoxContainer>
    );
  },
};

// 创建消息盒子的函数
export default function (title: string) {
  const container = document.createElement("div");
  container.classList.add("message_box_mask_container");
  const app = createApp(MessageBox, {
    title,
    onToClose: () => {
      app.unmount();
      container.remove();
    },
  });
  app.mount(container);
  document.body.appendChild(container);
}
import { Component, createApp } from "vue";
import "./index.css"; //这个只是真实DOM的样式,其实也可以不使用,将其封装成组件也可以。
// css-in-js的vue插件
import { styled } from "@styils/vue";

// 配置了样式的组件元素
// styled会创建一个组件,在传入参数时可以选择组件的tagName和对应样式,并且最终渲染时会通过class选择器给元素配置样式的。
// 消息容器
const BoxContainer = styled("div", {
  backgroundColor: "#fff",
  borderRadius: "5px",
  height: "150px",
  width: "80%",
  maxWidth: "500px",
  padding: "10px",
  boxSizing: "border-box",
});
// 按钮
const ConfirmButton = styled("button", {
  border: "none",
  padding: "5px 10px",
  backgroundColor: "skyblue",
  color: "#fff",
  cursor: "pointer",
});

// 组件配置项
const MessageBox: Component = {
  // 自定义熟悉
  props: {
    title: {
      type: String,
      required: true,
    },
  },
  // 定义的方法
  methods: {
    onHandleClick() {
      this.$emit("toClose");
    },
  },
  // 自定义事件
  emits: ["toClose"],
  // 组件的render函数
  render(ctx: any) {
    return (
      <BoxContainer>
        <div class="content">{ctx.title}</div>
        <ConfirmButton onClick={ctx.onHandleClick}>确认</ConfirmButton>
      </BoxContainer>
    );
  },
};

// 创建消息盒子的函数
export default function (title: string) {
  const container = document.createElement("div");
  container.classList.add("message_box_mask_container");
  const app = createApp(MessageBox, {
    title,
    onToClose: () => {
      app.unmount();
      container.remove();
    },
  });
  app.mount(container);
  document.body.appendChild(container);
}