学习Vue3 第二十五章(TSX)

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

小满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 配置


35486eb0bd1a4dabac0035384f877cbe.png


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",

e6d0ae1a4c254f13bde802f408fed4b3.png


配置完成就可以使用啦


在目录新建一个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
        }
    }
}

74dcc7da3e8d46999c651cb92c8f676b.png

c8f6b367a44c4317ae526b6501d85d16.png

737283315f6d4affac79c42801fdfa5a.png


目录
相关文章
|
1天前
|
JavaScript API UED
Vue3中的Suspense组件有什么用?
Vue3中的Suspense组件有什么用?
16 6
|
1天前
|
JavaScript 前端开发 索引
Vue3基础之v-if条件与 v-for循环
Vue3基础之v-if条件与 v-for循环
7 0
|
1天前
|
JavaScript
Vue3基础之v-bind与v-on
Vue3基础之v-bind与v-on
10 0
|
1天前
|
JavaScript 测试技术 API
Vue3中定义变量是选择ref还是reactive?
Vue3中定义变量是选择ref还是reactive?
12 2
|
1天前
|
移动开发 前端开发
ruoyi-nbcio-plus基于vue3的flowable为了适配文件上传改造VForm3的代码记录
ruoyi-nbcio-plus基于vue3的flowable为了适配文件上传改造VForm3的代码记录
17 1
|
1天前
|
JavaScript 前端开发
vue2升级到vue3的一些使用注意事项记录(四)
vue2升级到vue3的一些使用注意事项记录(四)
12 0
|
1天前
|
移动开发 前端开发
ruoyi-nbcio-plus基于vue3的flowable收回任务后重新进行提交表单的处理
ruoyi-nbcio-plus基于vue3的flowable收回任务后重新进行提交表单的处理
13 0
|
1天前
|
移动开发 前端开发
ruoyi-nbcio-plus基于vue3的flowable多租户机制
ruoyi-nbcio-plus基于vue3的flowable多租户机制
|
1天前
|
移动开发 前端开发
ruoyi-nbcio-plus基于vue3的flowable的消息中心我的消息的升级修改
ruoyi-nbcio-plus基于vue3的flowable的消息中心我的消息的升级修改
|
1天前
|
JavaScript 前端开发
vue3中使用动态组件
vue3中使用动态组件
11 0