以 JSX 的方式来编写 Vue 代码

2021-08-31  本文已影响0人  wyc0859

TSX优势

代码效验、代码提示、错误提示
支持ts里直接写标签 及 组件
还可以将组件写在函数里,结合一下动态值,然后调用函数,实现组件参数的复杂计算

//main.ts中将
import App from './App.vue'
改为:
import App from './App'

实现app.vue,用更直观的js写法,vue的h函数

// App.vue 改为 App.ts
import { createApp, defineComponent, h, reactive, ref ,PropType } from 'vue' 

export default defineComponent({
 setup() {
   const state = reactive({
     name: 'ax:',
   })  
   const numberRef = ref("bx:")
   setInterval(() => {
     state.name += 'a' 
     numberRef.value += 'b' 
   }, 2000)
   return () => { 
     const number = numberRef.value //Ref的变化会引起return 函数的重新执行,所以才会重新渲染节点,让值有更新
     return h('div', { id: 'app' }, [h('p', state.name), h('p', number)])
   }
 },
})

JSX 编中写html标签

jsx中写html标签是如何一步步进化衍变的

1、渲染函数 render

//main.ts
import { createApp, defineComponent, createVNode,h } from "vue"; 


const App2 = defineComponent({
   render() {
     return (
       //h('div', { id: 'app' }),
       createVNode('div', { id: 'app' }),
       [
         h('img', {
           alt: 'Vue logo'
         })
       ]
     )
   },
 })
 createApp(App2).mount("#app");

h函数只是createVNode的简单封装,所以把h函数替换为createVNode也是一样的

setup中使用H函数

<template>
    <diy />
</template>

<script setup>
import { ref,h } from 'vue'
const msg = ref('abc')
const diy = () => h('div',msg.value);
</script>

2、Babel 插件

如果你写了很多 render 函数,可能会觉得这样的代码写起来很痛苦,特别是对应的模板如此简单的情况下。
这就是为什么会有一个 Babel 插件,用于在 Vue 中使用 JSX 语法,它可以让我们回到更接近于模板的语法上。

  render() {
    return <div>Vue 3.0</div>;
  },

vue2有官方的babel插件
安装: npm install @vue/babel-preset-jsx @vue/babel-helper-vue-jsx-merge-props

vue3没有官方的,有阿里出的 vuejs/jsx-next
安装: npm install @vue/babel-plugin-jsx -D
还需要在babel.config.js文件中配置plugins: ["@vue/babel-plugin-jsx"]

\color{red}{注意文件后缀必须是小写TSX,不能是TS}

//App.tsx
import { defineComponent} from 'vue'  
export default defineComponent({
  setup() {   
    return () => { 
      return <div>asd</div>;
    }
  },
})



App.vue改为App.jsx需要安装扩展,不然会报错!
https://github.com/vuejs/jsx-next

npm install @vue/babel-plugin-jsx -D
新建一个 .babelrc 文件,内容如下
{
  "plugins": ["@vue/babel-plugin-jsx"]
}

最新版vue3不安装这个扩展,改为import App from './App'也是能正常运行App.tsx的

//App.vue.tsx
import { createApp, defineComponent, h, reactive, ref ,PropType } from 'vue'
import HelloWorld from './components/HelloWorld'
const img = require('./assets/logo.png') // eslint-disable-line

//setup return里可以直接放组件,也可以提出来放函数里计算后传参并返回组件
//cfg:any,在组件处不会报错,因为any代表任意,那config也是能适用的
function renderHelloWorld(num: number,cfg:Config) { 
  return <HelloWorld age={num} msg="abc" config={cfg}  />
}

//所以为了判断类型,这里也要有一个config接口
interface Config {
  name: string,
  num: number
}
export default defineComponent({
  setup() {
    const state = reactive({
      name: 'ax:',
    }) 

    const cfg: Config={
        name:"abc",
        num:321
    } 

    const numberRef = ref("bx:")
    setInterval(() => {
      state.name += 'a' 
      numberRef.value += 'b' 
    }, 2000)
    return () => {
      const number = numberRef.value 
      return (
        <div id="app">
          <img src={img} alt="Vue logo" />
          <p>{state.name}</p>
          <p>{number}</p>
          <input type="text" v-model={state.name} />
          {renderHelloWorld(12,cfg)}
        </div>
      ) 
    }
  },
})
//HelloWorld.tsx
import { defineComponent, PropType } from "vue";

interface Config {
  name: string,
  num:number
}

const PropsType = {
  msg: String,
  config: {
    type: Object as PropType<Config>,
    required: true,
  },  
  age: {
    type: Number,
    required: true,
  },
} as const;

export default defineComponent({
  props: PropsType,
  setup(props) { 
    return () => <div>abc:{props.age}--{props.config.name}++</div>;
  },
});

组件如果是vue文件,那编辑器不会有代码提示和代码检测。组件为tsx文件则可以

注意:

在vscode中ts项目引入的库,如vue有红色底线,但运行又没问题问题,那就是vscode自身的bug
解决办法:File -> Close folder然后File -> Open Folder 再次打开项目文件夹,错误就会消失

上一篇下一篇

猜你喜欢

热点阅读