第一步:安装插件
npm install @vitejs/plugin-vue-jsx -D
第二步: 在vite.config.ts中进行引入插件和注册插件
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx' // 引入插件
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
vueJsx(), // 注册插件
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
}
})
第三步:使用方法
写一个.tsx文件,像组件一样引入页面和使用
如:xue.tsx
在页面引用 import xue from './components/xue.tsx'
在页面使用 <xue></xue>
方法一:导出渲染函数 在里面直接return标签代码
export default function () {
return (<div>东北下雪了</div>)
}
方法二: 用render渲染函数返回标签
// 在组件中引入
import {defineComponent} from 'vue';
// 它其实是一个函数,他里面可以放一个对象, 有点类似vue2的写法
// 下面定一个render渲染函数,里面返回标签,
// 注意tsx里面使用变量使用的是单花括号
import {defineComponent} from 'vue';
export default defineComponent({
data() {
return {
name: '张三'
}
},
render () {
return (<div>{this.name}</div>)
}
})
方法三:使用setup函数,然后返回一个渲染函数
import {defineComponent} from 'vue';
export default defineComponent({
setup() {
return () => (<div>广东没下雪</div>)
}
})
语法支持方面
1.v-show 支持 <div v-show={true}></div>
如果使用vue3的ref定义变量,不会自动解包,要手动解包 .value
import {defineComponent, ref} from 'vue';
export default defineComponent({
setup() {
const flag = ref(false);
return () => (<div v-show={flag.value}>广东没下雪</div>)
}
})
2.v-if 不支持,需求实现可以使用三目运算符代替
import {defineComponent, ref} from 'vue';
export default defineComponent({
setup() {
const flag = ref(false);
return () => (<>
<div>{flag.value ? <div>东北下雪了</div> : <div>广州大太阳</div>}</div>
</>)
}
})
3.v-for不支持 使用map函数代替
import {defineComponent, ref} from 'vue';
export default defineComponent({
setup() {
const flag = ref(false);
const data = [
{city:'上海'},
{city:'北京'},
{city:'广州'},
{city:'深圳'}
];
return () => (<>
{data.map(v=>{
return <div>{v.city}</div>
})}
</>)
}
})
4.v-bind或:传参不支持,直接使用 属性={属性值}
import {defineComponent, ref} from 'vue';
export default defineComponent({
setup() {
const flag = ref(false);
const data = [
{city:'上海'},
{city:'北京'},
{city:'广州'},
{city:'深圳'}
];
return () => (<>
{data.map(v=>{
return <div name={v.city}>{v.city}</div>
})}
</>)
}
})
5.v-model支持
import {defineComponent, ref} from 'vue';
interface Props{
name?:string
}
export default defineComponent({
setup(props:Props,{emit}) { // 通过emit派发事件
const v = ref<string>('');
return () => (<>
<input v-model={v.value} type='text'></input>
<div>{v.value}</div>
</>)
}
})
Vue3 TSX组件父子组件传参
1.事件直接使用on代替@,注意不能把函数直接放进去,因为在编译阶段已经调用了
这个要通过函数柯里化的方式来解决 onClick={() =>fn()}
2.props向子组件传参数
3.emit派发函数向父组件传参
函数柯里化是指将使用多个参数的函数转化成一系列使用一个参数的函数的技术, 它返回一个新的函数, 这个新函数去处理剩余的参数
import {defineComponent, ref} from 'vue';
interface Props{
name?:string
}
export default defineComponent({
props:{
name:{
type:String,
default:'重庆'
}
},
emits:['on-click'], // 派发事件名称
setup(props:Props,{emit}) { // 通过emit派发事件
const data = [
{city:'上海'},
{city:'北京'},
{city:'广州'},
{city:'深圳'}
];
const fn = (item:any) => {
console.log('触发事件'+item.city)
emit('on-click',item) // 派发事件
}
return () => (<>
<div>props:{props?.name}</div>
<hr />
{data.map(v=>{
return <div onClick={() =>fn(v)} name={v.city}>{v.city}</div>
})}
</>)
}
})
父组件使用
```
<xue name="成都来了" @on-click="getItem"></xue>
```
const getItem = (item) => {
console.log(item, '父在组件收到了');
}
插槽的用法
import {defineComponent, ref} from 'vue';
// 写一个A组件
const A = (_,{slots}) => (<>
<div>{slots.default ? slots.default() : '默认值'}</div>
{/* 可选链操作符 这里如果传了调用一下 */}
<div>{slots.foo?.()}</div>
</>)
interface Props{
name?:string
}
export default defineComponent({
props:{
name:{
type:String,
default:'重庆'
}
},
setup(props:Props,{emit}) { // 通过emit派发事件
// 插槽入参数
const slot = {
default:()=> (<div>我是default</div>),
foo:()=> (<div>我是foo slots</div>)
}
return () => (<>
<A v-slots={slot}></A>
<hr />
<div>props:{props?.name}</div>
</>)
}
})