Appearance

vue中使用jsx开发组件

coderzhouyu2023-11-10 10:50:37

使用 jsx 开发组件

import { defineComponent } from "vue";

// 定义子组件
const ChildComponent = defineComponent({
  name: "ChildComponent",
  setup() {
    return () => <div>ChildComponent</div>;
  },
});
// 也可以使用 render 函数
const ChildComponent = defineComponent({
  name: "ChildComponent",
  render() {
    return <div>ChildComponent</div>;
  },
});
// 定义非受控组件(就是组件内部没有状态)
const UncontrolledComponent = defineComponent({
  name: "UncontrolledComponent",
  setup() {
    return () => <input type="text" />;
  },
});
// 定义组件函数并用闭包保存调用时的参数 这种方式可以用于创建组件库
function createComponent(name, props) {
  return defineComponent({
    name,
    setup() {
      {
        props.name;
      }
      return () => <div>{name}</div>;
    },
  });
}

export default defineComponent({
  name: "App",
  // 定义 props
  props: {
    msg: String,
  },
  // 定义事件
  emits: ["update:msg"],
  setup(props, { slots, attrs, emit, expose }) {
    // 对外暴露的方法
    expose({
      // ...
    });
    // 使用 createComponent
    const ChildComponent = createComponent("ChildComponent", {
      name: "ChildComponent",
    });

    // 返回 jsx
    return () => (
      <div>
        <ChildComponent />
        {h(ChildComponent)}
        <h1>{props.msg}</h1>
        <button onClick={() => emit("update:msg", "Hello Vite + Vue + JSX")}>
          Change msg
        </button>
        {slots.default?.()}
      </div>
    );
  },
});

v-slot 在 jsx 中的使用

export default defineComponent({
  name: "App",
  setup(props, { slots }) {
    // 此处的 slots 是一个对象 可以通过解构获取到具名插槽
    const { default: defaultSlot } = slots;
    // 下面的方式可以将插槽传递给子组件
    return () => (
      <div>
        <h1>{props.msg}</h1>
        <button onClick={() => emit("update:msg", "Hello Vite + Vue + JSX")}>
          Change msg
        </button>
        {slots.default?.()}
        <ChildComponent v-slots={slots} />
      </div>
    );
  },
});

inject 和 provide 在 jsx 中的使用


import { ref, provide } from 'vue'

const Child = ()=>{
	return <GrandChild />
}

const GrandChild = defineComponent({
	name: "App",
	setup(props, { slots }) {
		// 这里注入之后就完全是一个响应数据了,在孙组件修改这个状态其他组件中也会发生变化。也就是说这种行为同样破坏了单向数据流
	    const message = inject('message')
		const add = ()=>{
			message.value = message.value + "12"
		}
    return () => (
      <>
		<p>
		Message to grand child: {{ message }}
		<button @click="add" >+</button>
		</p>
      </>
    );
  },
})

export default defineComponent({
  name: "App",
  setup(props, { slots }) {
    const message = ref('hello')
	provide('message', message)
    return () => (
      <>
        <input v-model="message">
		<Child />
      </>
    );
  },
})


参考资料: 依赖注入 | Vue.js (vuejs.org)open in new window

component 在 jsx 中的使用

component 在 jsx 中可以使用 resolveComponent 函数来获取组件

import { defineComponent, resolveComponent } from "vue";

export default defineComponent({
  name: "App",
  setup() {
    const ChildComponent = resolveComponent("ChildComponent");
    return () => (
      <div>
        <ChildComponent />
      </div>
    );
  },
});

参考资料: https://juejin.cn/post/7291463601704255545

inheritAttrs

import { defineComponent } from "vue";

export default defineComponent({
  name: "App",
  // 加入 inheritAttrs: false 后 attrs 就不会被渲染到组件的根元素上
  inheritAttrs: false,
  setup(props, { attrs }) {
    return () => (
      <div>
        <h1>{props.msg}</h1>
        <button onClick={() => emit("update:msg", "Hello Vite + Vue + JSX")}>
          Change msg
        </button>
        {slots.default?.()}
      </div>
    );
  },
});

参考资料: https://cn.vuejs.org/api/options-misc.html#inheritattrs

参考资料

https://cn.vuejs.org/guide/extras/render-function.html https://juejin.cn/post/6844903710229790734

Last Updated 2023/11/13 08:51:10