以 JSX 的方式来编写 Vue 代码

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 再次打开项目文件夹,错误就会消失

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,496评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,407评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,632评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,180评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,198评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,165评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,052评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,910评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,324评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,542评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,711评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,424评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,017评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,668评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,823评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,722评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,611评论 2 353

推荐阅读更多精彩内容