17 vue3之tsx手写vite tsx插件
我们之前呢是使用Template去写我们模板。现在可以扩展另一种风格TSX风格
vue2 的时候就已经支持jsx写法,只不过不是很友好,随着vue3对typescript的支持度,tsx写法越来越被接受,减少我们学习react的成本 Ant Design组件库就是使用tsx语法编写的
安装插件
npm install @vitejs/plugin-vue-jsx -D
vite.config.ts配置
import vueJsx from "@vitejs/plugin-vue-jsx";export default ({ mode }: any) => {console.log("mode===>", mode);console.log(loadEnv(mode, process.cwd()));return defineConfig({plugins: [vue(),vueJsx(), //注册AutoImport({imports: ["vue"], // 引入vue的自动引入}),],});
};
修改tsconfig.json 配置文件
"jsx": "preserve","jsxFactory": "h","jsxFragmentFactory": "Fragment",
使用Tsx
在目录新建一个xxxxxx.tsx文件
tsx支持 v-model 的使用
import { ref } from 'vue'let v = ref<string>('')const renderDom = () => {return (<><input v-model={v.value} type="text" /><div>{v.value}</div></>)
}export default renderDom
v-show
import { ref } from 'vue'let flag = ref(false)const renderDom = () => {return (<><div v-show={flag.value}>景天</div><div v-show={!flag.value}>雪见</div></>)
}export default renderDom
v-if是不支持 可使用三元表达式支持
import { ref } from 'vue'let flag = ref(false)const renderDom = () => {return (<>{flag.value ? <div>景天</div> : <div>雪见</div>}</>)
}export default renderDom
v-for不支持 可使用map支持
import { ref } from 'vue'let arr = [1,2,3,4,5]const renderDom = () => {return (<>{arr.map(v=>{return <div>${v}</div>})}</>)
}export default renderDom
v-bind使用
import { ref } from 'vue'let arr = [1, 2, 3, 4, 5]const renderDom = () => {return (<><div data-arr={arr}>1</div></>)
}export default renderDom
v-on绑定事件 所有的事件都按照react风格来
- 所有事件有on开头
- 所有事件名称首字母大写
const renderDom = () => {return (<><button onClick={clickTap}>点击</button></>)
}const clickTap = () => {console.log('click');
}export default renderDom
Props 接受值
import { ref } from 'vue'type Props = {title:string
}const renderDom = (props:Props) => {return (<><div>{props.title}</div><button onClick={clickTap}>点击</button></>)
}const clickTap = () => {console.log('click');
}export default renderDom
Emit派发
type Props = {title: string
}const renderDom = (props: Props,content:any) => {return (<><div>{props.title}</div><button onClick={clickTap.bind(this,content)}>点击</button></>)
}const clickTap = (ctx:any) => {ctx.emit('on-click',1)
}
Slot
const A = (props, { slots }) => (<><h1>{ slots.default ? slots.default() : 'foo' }</h1><h2>{ slots.bar?.() }</h2></>
);const App = {setup() {const slots = {bar: () => <span>B</span>,};return () => (<A v-slots={slots}><div>A</div></A>);},
};// orconst App = {setup() {const slots = {default: () => <div>A</div>,bar: () => <span>B</span>,};return () => <A v-slots={slots} />;},
};// or you can use object slots when `enableObjectSlots` is not false.
const App = {setup() {return () => (<><A>{{default: () => <div>A</div>,bar: () => <span>B</span>,}}</A><B>{() => "foo"}</B></>);},
};
完整示例代码
三种不同写法的tsx语法
三种不同写法的tsx语法 一和3的方式用的比较多 我们这里主要是使用第三种
- 第一种返回渲染函数
-
第二种optionsApi方式
-
第三种setup函数模式
// 三种不同写法的tsx语法 一和3的方式用的比较多 我们这里主要是使用第三种
// 第一种返回渲染函数
/* export default function () {return <div>cookie</div>;
} */// 第二种optionsApi方式/*import { defineComponent } from "vue";export default defineComponent({data() {return {name: "cookie123",};},render() {return <div>{this.name}</div>;},
}); *///第三种setup函数模式
/* import { defineComponent } from "vue";
export default defineComponent({setup() {return () => <div>cookie-setup</div>;},
}); */
父组件
<template><div class=""></div><Cookie :title="'Cookie标题'" @cusemit="getStr"></Cookie><hr /><MyTSX title="MyTSX标题" @emit1="getStr"></MyTSX>
</template><script setup lang="ts">
import { ref, reactive } from "vue";
import MyTSX from "./components/MyTSX";
import Cookie from "./components/Cookie ";
let getStr = (params: string) => {console.log("a接收,,,", params);
};
</script><style lang="less" scoped></style>
子组件MyTSX.tsx
- 派发事件注意函数柯里化
// 三种不同写法的tsx语法 一和3的方式用的比较多 我们这里主要是使用第三种
// 第一种返回渲染函数
/* export default function () {return <div>cookie</div>;
} */// 第二种optionsApi方式/*import { defineComponent } from "vue";export default defineComponent({data() {return {name: "cookie123",};},render() {return <div>{this.name}</div>;},
}); *///第三种setup函数模式
/* import { defineComponent } from "vue";
export default defineComponent({setup() {return () => <div>cookie-setup</div>;},
}); */// v-show 指令
// 1.ref在tsx语法中变量中使用{flag.vue},并且值不会如在template中自动解析.value
// 2.在tsx语法中,v-if不支持可使用三元表达式代替
// v-for也是不支持的,需要使用map函数代替
// v-bind直接使用name={} <div name="666">name</div>
// props emit <button onClick={fn()}>点击</button>还未点击就触发了 需要使用函数柯里化的方式处理
// slot插槽
import { defineComponent, ref } from "vue";
type Props = {// 泛型字面量title?: string;
};
// 定义一个组件const A = (props, { slots }) => (<div><div>{slots.default ? slots.default() : "默认值"}</div>{/* 定义其他的插槽 slots.bar?.()等同上面的写法 */}<div>{slots.bar?.()}</div></div>
);
export default defineComponent({props: { title: String },emits: ["cusemit"],setup(props: Props, { emit }) {let show = ref(true);let arr = [1, 2, 3, 4, 5];let name = "666";const fn = (a: any) => {console.log("fn触发了", a);emit("cusemit", a);};const slot = {default: () => <div>default插槽值</div>,bar: () => <div>bar插槽值</div>,};return () => (<div><div v-show={show.value}>show</div>{show ? <div>显示1</div> : <div>显示0</div>}{arr.map((v) => {return <div>${v}</div>;})}<div name={name}>name</div><hr /><h3>props emit 语法</h3><div>{props?.title}</div><button onClick={() => fn(33)}>点击</button><hr /><h3>插槽 语法</h3><A v-slots={slot} /></div>);},
});
子组件cookie.tsx 与MyTSX.tsx不同的写法
import { ref } from "vue";
/*
需要注意的点
1.ref在tsx语法中变量中使用{flag.vue},并且值不会如在template中自动解析.value*/let v = ref<string>("");
let flag = ref(false);
let list = [1, 2, 3];type Props = {// 泛型字面量title: string;
};const renderDom = (props: Props, ctx: any) => {// ctx东西// 1.v-model/*return (<><input v-model={v.value} type="text" /><div>{v.value}</div></>); *///2.v-show ,v-if不支持可以使用js编程的方式去转变/* return (<div><div v-show={flag}>显示1</div><div v-show={!flag}>显示2</div>{flag ? <div>显示3</div> : <div>显示4</div>}</div>); *///3.v-for不支持,可以用map ,v-bind不支持可以用data-index,v-on不支持可以用onClick={tap} 传参使用onClick={tap1.bind(this, 66)}// props在组件中使用的是一样的,事件派发ctxreturn (<div><div>{props.title}</div>{list.map((v) => {return (<div onClick={tap} data-index={v}>${v}</div>);})}<button onClick={tap1.bind(this, 66)}>函数传参,请点击</button><button onClick={tap2.bind(this, ctx)}>派发事件,请点击</button></div>);
};
let tap = () => {console.log("click");
};
let tap1 = (v: number) => {console.log(v);
};
let tap2 = (ctx: any) => {console.log(ctx);ctx.emit("emit1", "发送");
};export default renderDom;
效果图:
18 vue3之自动引入ref插件&深入使用v-model-CSDN博客TIps 在Vue3 v-model 是破坏性更新的v-model在组件里面也是很重要的v-model 其实是一个语法糖 通过props 和 emit组合而成的默认值的改变prop:value -> modelValue;事件:input -> update:modelValue;v-bind 的 .sync 修饰符和组件的 model 选项已移除新增 支持多个v-model新增 支持自定义 修饰符 Modifiershttps://blog.csdn.net/qq_37550440/article/details/142522527?sharetype=blogdetail&sharerId=142522527&sharerefer=PC&sharesource=qq_37550440&spm=1011.2480.3001.8118