小满Vue3(第二十五章 tsx & vite插件)_哔哩哔哩_bilibili  视频教程

完整版用法 请看 @vue/babel-plugin-jsx - npm

我们之前呢是使用Template去写我们模板。现在可以扩展另一种风格TSX风格

vue2 的时候就已经支持jsx写法,只不过不是很友好,随着vue3对typescript的支持度,tsx写法越来越被接受

1.安装插件

npm install @vitejs/plugin-vue-jsx -D

vite.config.ts 配置

学习Vue3 第二十五章(TSX)_typescript

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()]
})

2.修改tsconfig.json 配置文件

"jsx": "preserve",
"jsxFactory": "h",
"jsxFragmentFactory": "Fragment",

学习Vue3 第二十五章(TSX)_json_02

配置完成就可以使用啦

在目录新建一个xxxxxx.tsx文件

3.使用TSX

TIPS tsx不会自动解包使用ref加.vlaue ! ! !

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>
</>
);
},
};

加餐实现一个vite插件解析tsx

1.需要用到的第三方插件

npm install @vue/babel-plugin-jsx
npm install @babel/core
npm install @babel/plugin-transform-typescript
npm install @babel/plugin-syntax-import-meta
npm install @types/babel__core

插件代码

import type { Plugin } from 'vite'
import * as babel from '@babel/core'; //@babel/core核心功能:将源代码转成目标代码。
import jsx from '@vue/babel-plugin-jsx'; //Vue给babel写的插件支持tsx v-model等
export default function (): Plugin {
return {
name: "vite-plugin-tsx",
config (config) {
return {
esbuild:{
include:/\.ts$/
}
}
},
async transform(code, id) {
if (/.tsx$/.test(id)) {
//@ts-ignore
const ts = await import('@babel/plugin-transform-typescript').then(r=>r.default)
const res = babel.transformSync(code,{
plugins:[jsx,[ts, { isTSX: true, allowExtensions: true }]], //添加babel插件
ast:true, // ast: 抽象语法树,源代码语法结构的一种抽象表示。babel内部就是通过操纵ast做到语法转换。
babelrc:false, //.babelrc.json
configFile:false //默认搜索默认babel.config.json文件
})
return res?.code //code: 编译后的代码
}

return code
}
}
}

学习Vue3 第二十五章(TSX)_App_03

 

学习Vue3 第二十五章(TSX)_typescript_04

 

学习Vue3 第二十五章(TSX)_json_05