我们之前呢是使用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>
);
},
};
// or
const 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在组件中使用的是一样的,事件派发ctx
return (
<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;
效果图:
定义tsx样式
test.tsx
内联样式不能和className一起使用
import { defineComponent } from "vue";
import styles from "./styles.module.css";
export default defineComponent({
setup() {
return () => (
/* <div style={{ color: "blue", fontSize: "16px" }}>
tsx -内联样式
</div> */
<div className={styles.container}>
tsx -CSS Modules
</div>
);
},
});
styles.module.css
/* styles.module.css */
container { padding: 20px; border: 1px solid #ccc; }
.title { font-size: 2em; color: #333; }
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