小满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 配置
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",
配置完成就可以使用啦
在目录新建一个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 } } }