vue中正确使用jsx语法的姿势分享
admin
2023-05-03 21:40:25
目录

            前言

            又到了愉快的摸鱼时间,我觉得不能荒废,H5页面我一直用的vant,出于对源码的好奇,我从git上拉了一份vant源码,里面竟然都是jsx写的组件,于是我开始了对在vue中使用jsx的探索

            虚拟DOM

            什么是虚拟DOM

            在这之前,先了解下虚拟DOM,vue和react框架都在内部使用了虚拟DOM,这样做的原因是通过js操作DOM的计算成本很高,虽然js更新速度很快,但是查找dom并更新的成本很高。那么有什么方法可以优化呢,vue等框架使用js对象,通过改变js对象,最后进行批量处理,一次更新DOM,所以虚拟DOM本质上就是一个js对象

            虚拟DOM的优点

            渲染函数是什么

            渲染函数是用来生成虚拟DOM的。我们在vue单文件中编写模板语法,最终会在底层实现中被编译成渲染函数

            Vue 推荐在绝大多数情况下使用模板来创建你的 HTML。然而在一些场景中,你真的需要 JavaScript 的完全编程的能力。这时你可以用渲染函数,它比模板更接近编译器。

            当出现以下场景,虽然下列写法也能实现想要的效果,但是他不仅冗长,而且我们为每个级别标题重复书写了 。当我们添加锚元素时,我们必须在每个 v-if/v-else-if 分支中再次重复它

            const { createApp } = Vue
            
            const app = createApp({})
            
            app.component('anchored-heading', {
              template: `
                

            `, props: { level: { type: Number, required: true } } })

            虽然模板在大多数组件中都非常好用,但是显然在这里它就不合适了。那么,我们来尝试使用 render 函数重写上面的例子:

            const { createApp, h } = Vue
            
            const app = createApp({})
            
            app.component('anchored-heading', {
              render() {
                return h(
                  'h' + this.level, // tag name
                  {}, // props/attributes
                  this.$slots.default() // array of children
                )
              },
              props: {
                level: {
                  type: Number,
                  required: true
                }
              }
            })
            

            jsx

            这样写渲染函数有点痛苦,有没有更接近模板的写法呢,vue提供了一个babel-plugin-jsx babel插件来让vue支持jsx写法

            我这边使用的vuecli创建的vue3 + ts项目,脚手架已经集成了jsx和ts的相关依赖

            在vue3中编写jsx的两种方式

            直接将文件后缀名从vue改成tsx或者jsx

            在vue3中,可以直接使用render选项编写

            import { defineComponent } from "vue";
            export default defineComponent({
              name: "Jsx",
              render() {
                return 

            我是一个p

            ; }, });

            也可以在setup中返回

            import { defineComponent } from "vue";
            export default defineComponent({
              name: "Jsx",
              setup() {
                return () => 

            我是p

            ; }, });

            两种方式都可以,具体看个人习惯,setup中访问不到this,但是render中可以通过this访问当前vue实例

            用法

            class绑定,和react的jsx绑定的有区别,react中使用className,vue中使用class

             setup() {
               return () => 

            我是p

            ; },

            style绑定

              setup() {
                return () => 

            我是p

            ; },

            props绑定

            // 父组件
            setup() {
                return () => (
                  

            我是父组件

            );

            // 子组件,setup的第一个参数,可以获取props里的值
              setup(props) {
                return () => 

            我是子组件{props.msg}

            ; },

            事件绑定

            setup() {
                function eventClick() {
                  console.log("点击");
                }
                return () => ;
            },
            

            组件自定义事件

            // 子组件
            import { defineComponent } from "vue";
            export default defineComponent({
              name: "Mycom",
              emits: ["event"],
              setup(props, { emit }) {
                function sendData() {
                  emit("event", "子组件传递的数据");
                }
                return () => (
                  

            自定义事件

            ); }, });

            // 父组件
            // @ts-nocheck
            // 这样写在jsx中没问题,但是在tsx中会报ts类型错误,所以我在上面忽略了当前文件ts监测@ts-nocheck
            import { defineComponent } from "vue";
            import Mycom from "./mycom";
            export default defineComponent({
              name: "Jsx",
              setup() {
                function getSon(msg: string) {
                  console.log(msg);
                }
                return () => (
                  

            ); }, });

            也可以这样解决ts类型报错

              setup() {
                function getSon(msg: string) {
                  console.log(msg);
                }
                return () => (
                  

            ); },

            插槽

            // 父组件
            setup() {
                const slots = {
                  test: () => 

            具名插槽

            , default: () =>

            默认插槽

            , }; return () => (

            ); },

            setup(props, { slots }) {
            // 子组件
                return () => (
                  

            插槽 {slots.default?.()} {slots.test?.()}

            ); },

            指令,v-if,v-for等指令在jsx中无法使用,jsx只支持v-model和v-show指令

              setup() {
                const inputData = ref("");
                return () => (
                  

            显示 隐藏 {inputData.value}

            ); },

            最后

            话不多说,我先打开vant源码,准备开启我的第一个组件源码阅读 src =>button=>button.tsx

            到此这篇关于vue中正确使用jsx的文章就介绍到这了,更多相关vue中使用jsx内容请搜索趣讯吧以前的文章或继续浏览下面的相关文章希望大家以后多多支持趣讯吧!

            参考

            相关内容

            热门资讯

            demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
            北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
            苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...