【Vue3+Vite+Ts+element-plus】
超级详细 最新 vite4+vue3+ts+element-plus+eslint-prettier 项目搭建流程
【Vue3+Vite+Ts+element-plus】使用tsx实现左侧栏菜单无限层级封装
【Ts 系列】
TypeScript 从入门到进阶之基础篇(一) ts类型篇
本章我们将了解 在vue中使用tsx 语法 和我们日常vue正常开发上的一些语法区别
我们需要创建一个vue3项目 我用的是vite去创建vue3+ts 项目的 ,这里就不多讲项目的创建了 ,如果要详细的项目搭建流程可参考:超级详细 最新 vite4+vue3+ts+element-plus+eslint-prettier 项目搭建流程
在使用tsx之前 我们要安装一些插件 使我们的项目支持tsx
//下面3种安装方式选择一种 推荐pnpm
yarn add @vitejs/plugin-vue-jsx
//or
npm install @vitejs/plugin-vue-jsx -D
//or
pnpm install @vitejs/plugin-vue-jsx -D
在 vite.config.ts 文件中挂载
import vueJsx from '@vitejs/plugin-vue-jsx'
export default defineConfig({
plugins: [ vueJsx()]
})
tsconfig.json 文件中
{
// include 需要包含tsx
"include": ["src/*", "src/**/*.vue", "src/**/*.tsx", "src/**/*.jsx", "src/**/*.ts", "src/**/*.js"],
"compilerOptions": {
// 在.tsx文件里支持JSX
"jsx": "preserve",
}
}
在普通的vue 文件中 内容结构都是用 SFC 方式结构固定:template、script、style
<template>
<div>Hello World</div>
</template>
<script setup lang="ts">
</script>
<style scope>
</style>
而在tsx中 完全是一个ts文件的写法 如下
import { defineComponent } from 'vue';
export default defineComponent({
setup() {
return () => <div>Hello World</div>
}
})
在vue 文件中 我们绑定变量 是以 v-bind: 的方式或者简写的:冒号 ,而在tsx中则是以大括号的方式来绑定变量 如下面代码
//vue
<template>
<div :class="className"></div>
</template>
<script lang="ts" setup>
const className=ref('name')
</script>
//vtsx
import { defineComponent } from 'vue';
export default defineComponent({
setup() {
const className=ref('name')
return () => <div class={className}></div>
}
})
在tsx 中 是支持v-show指令 具体用法如下 与vue文件中的用法没有区别
只是写法上需要以{} 的方式 定义这是一个变化的变量
//tsx
import { defineComponent } from 'vue';
export default defineComponent({
setup() {
const isShow=ref(true)
return () => <div v-show={isShow.value}>Hello World</div>
}
})
注意 在tsx 是不支持v-if 的 ,我们可以使用条件判断语句来实现v-if的功能,一般是三目运算符
//tsx
import { defineComponent } from 'vue';
export default defineComponent({
setup() {
const isShow=ref(true)
return () => <div>{isShow.value?'Hello':'Hello 前端小羽'}</div>
}
})
在vue中 我们生成一个列表 通常是用 v-for 的方法去实现的 ,但是在tsx中是不支持 v-for写法的 所以通常是用map循环的方式来生成列表 具体代码区别如下:
//vue
<template>
<div>
<div v-for="item in list" :key="item">{{item}}</div>
</div>
</template>
<script lang="ts" setup>
const list=ref([1,2,3,4,5,6])
</script>
//vtsx
import { defineComponent } from 'vue';
export default defineComponent({
setup() {
const list=ref([1,2,3,4,5,6])
return () =>
<div>
{
list.map((item:any)=>(<div>{item}</div))
}
</div>
}
})
在vue中插槽的实现方式如下
// SFC child
<template>
<div>
<slot>默认插槽: default</slot>
<br />
<slot name="content">具名插槽:content</slot>
<br />
<slot name="main" :test="111" >作用域插槽:main</slot>
</div>
</template>
// SFC parent
<template>
<div>
<child>
<template #main="row"> {{ row.test}} </template>
<template #content>我是内容</template>
</child>
</div>
</template>
在tsx中插槽的写法2如下
// TSX child
import { defineComponent } from 'vue';
export default defineComponent({
setup(props, { slots }) {
return () => (
<div>
默认插槽: {slots.default && slots.default()}
<br />
具名插槽: {slots.content&& slots.content()}
<br />
作用域插槽:{slots.main && slots.main({ name: '我是作用域插槽的传值' })}
</div>
);
}
});
// TSX parent 第一种方式
return () => (
<Child v-slots={{
default: () => '默认',
content: () => '我是内容',
main: (props: Record<'name', string>) => + props.name
}}>
</Child>
)
// 第二种方式
return () => (
const slot={
default: () => '默认的内容是',
content: () => '我是有名称的',
main: (props: Record<'name', string>) => props.name
}
<Child v-slots={slot}>
</Child>
)
在vue 中 监听事件使用 v-on或者@ ,但是在tsx中则是以on开头,即使我们的自定义事件没有on,也要在监听的时候加上,一般都采用的是小驼峰的方式 例如@change 变成 onChange @click 变成 onClick 事件等。
注意 如果是自定义事件只需要在事件名前面加上on即可
// SFC
<template>
<div @click="hanClick">无参数</div>
<div @click="(event) => hanClick1(event)">鼠标事件参数</div>
<div @click="hanClick2('我是前端小羽')">自定义参数</div>
</template>
// TSX
return () => (
<>
<div onClick={hanClick}>无参数</div>
<div onClick={(event) => hanClick1(event)}>鼠标事件参数</div>
<div onClick={() => hanClick2('我是前端小羽')}>自定义参数</div>
</>
);
const hanClick= () => {
console.log('click');
};
const hanClick1= (e: MouseEvent) => {
console.log(e.offsetX);
};
const hanClick2= (name: string) => {
console.log(name);
};