vue中正确使用jsx语法的姿势分享

目录
  • 前言
  • 虚拟DOM
    • 什么是虚拟DOM
    • 虚拟DOM的优点
  • 渲染函数是什么
  • jsx
    • 在vue3中编写jsx的两种方式
    • 用法
  • 最后
  • 参考

前言

又到了愉快的摸鱼时间,我觉得不能荒废,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到操作虚拟DOM,降低查找成本
  • 通过diff比对,我们可以更快的定位数据的变化,从而更新DOM
  • 更好的ui更新
  • 抽象渲染过程,带来了实现跨平台的能力,如vue3中的createRenderer API

渲染函数是什么

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

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

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

const { createApp } = Vue

const app = createApp({})

app.component('anchored-heading', {
  template: `
    <h1 v-if="level === 1">
      <slot></slot>
    </h1>
    <h2 v-else-if="level === 2">
      <slot></slot>
    </h2>
    <h3 v-else-if="level === 3">
      <slot></slot>
    </h3>
    <h4 v-else-if="level === 4">
      <slot></slot>
    </h4>
    <h5 v-else-if="level === 5">
      <slot></slot>
    </h5>
    <h6 v-else-if="level === 6">
      <slot></slot>
    </h6>
  `,
  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 <div>我是一个div</div>;
  },
});

也可以在setup中返回

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

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

用法

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

 setup() {
   return () => <div class="test">我是div</div>;
 },

style绑定

  setup() {
    return () => <div style={{ color: "red" }}>我是div</div>;
  },

props绑定

// 父组件
setup() {
    return () => (
      <div style={{ color: "red" }}>
        <span>我是父组件</span>
        <Mycom msg={"我是父组件传的值"} />
      </div>
 );
// 子组件,setup的第一个参数,可以获取props里的值
  setup(props) {
    return () => <div>我是子组件{props.msg}</div>;
  },

事件绑定

setup() {
    function eventClick() {
      console.log("点击");
    }
    return () => <button onClick={eventClick}>按钮</button>;
},

组件自定义事件

// 子组件
import { defineComponent } from "vue";
export default defineComponent({
  name: "Mycom",
  emits: ["event"],
  setup(props, { emit }) {
    function sendData() {
      emit("event", "子组件传递的数据");
    }
    return () => (
      <div>
        <span>自定义事件</span>
        <button onClick={sendData}>传递数据</button>
      </div>
    );
  },
});
// 父组件
// @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 () => (
      <div>
        <Mycom onEvent={getSon} />
      </div>
    );
  },
});

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

  setup() {
    function getSon(msg: string) {
      console.log(msg);
    }
    return () => (
      <div>
        <Mycom {...{ onEvent: getSon }} />
      </div>
    );
  },

插槽

// 父组件
setup() {
    const slots = {
      test: () => <div>具名插槽</div>,
      default: () => <div>默认插槽</div>,
    };
    return () => (
      <div>
        <Mycom v-slots={slots}></Mycom>
      </div>
    );
},
setup(props, { slots }) {
// 子组件
    return () => (
      <div>
        <span>插槽</span>
        {slots.default?.()}
        {slots.test?.()}
      </div>
    );
  },

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

  setup() {
    const inputData = ref("");
    return () => (
      <div>
        <span v-show={true}>显示</span>
        <span v-show={false}>隐藏</span>
        <input type="text" v-model={inputData.value} />
        <span>{inputData.value}</span>
      </div>
    );
},

最后

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

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

参考

(0)

相关推荐

  • vue组件jsx语法的具体使用

    如果使用render函数来写比较复杂的vue组件,对于可读性和可维护性都很不友好,而使用jsx就会让我们回到更接近于模板的语法.babel转译器会将jsx转译为render函数渲染. 配置 需要用到babel插件 安装 npm install\ babel-plugin-syntax-jsx\ babel-plugin-transform-vue-jsx\ babel-helper-vue-jsx-merge-props\ babel-preset-env\ --save-dev .babelr

  • vue jsx 使用指南及vue.js 使用jsx语法的方法

    vue  jsx  语法与 react  jsx  还是有些不一样,在这里记录下. let component = null// if 语句 if (true) { component = ( <div></div> ); } else { component = ( <div></div> ); } var ul = ( <ul> {component} </ul> ); // map 语句 var coms = limit.map

  • Vue中jsx不完全应用指南小结

    前言:文章不介绍任务背景知识,没有原理说明,偏向于实践的总结和经验分享. 文章所有的代码是基于Vue CLI 3.x版本,不会涉及到一步步通过Webpack来配置JSX所需要的知识点. 在使用Vue开发项目时绝大多数情况下都是使用模板来写HTML,但是有些时候页面复杂又存在各种条件判断来显示/隐藏和拼凑页面内容,或者页面中很多部分存在部分DOM结构一样的时候就略显捉襟见肘,会写大量重复的代码,会出现单个.vue文件过长的情况,这个时候我们就需要更多的代码控制,这时候可以使用渲染函数. 渲染函数想

  • 详解利用jsx写vue组件的方法示例

    前言 本文主要给大家介绍的是关于利用jsx写vue组件,下面话不多说,来一起看看详细的介绍吧. 我们平常写vue的组件时,一般都是用的是模版,这种方式看起来比较简洁,而且vue作者也推荐使用这个方式,但是这种方式也有一些它的弊端,例如模版调试麻烦,或者在一些场景下模版描述可能没那么简单和方便. 下面我们要讲的是如何在vue里面写jsx,知道react的人应该都知道jsx,jsx的一个特性就是非常灵活,虽然有的人觉得jsx很丑陋,把逻辑都写到模版的感觉,但萝卜青菜各有所爱,适合自己适合团队的就是最

  • 详解如何使用webpack在vue项目中写jsx语法

    本文介绍了如何使用webpack在vue项目中写jsx语法,分享给大家,具体如下: 我们知道Vue 2.0中对虚拟DOM的支持.我们可以通过JavaScript动态的创建元素,而不用在template中写HTML代码.虚拟DOM最终将被渲染为真正的DOM. data: { msg: 'Hello world' }, render (h) { return h( 'div', { attrs: { id: 'my-id' }, [ this.msg ] ); } 渲染后的内容为: <div id=

  • Vue 3.0中jsx语法的使用

    Vue 3.0 正式发布了,喜大普奔

  • 在 Vue 中使用 JSX 及使用它的原因浅析

    本文 GitHub https://github.com/qq44924588... 上已经收录,更多往期高赞文章的分类,也整理了很多我的文档,和教程资料.欢迎Star和完善,大家面试可以参照考点复习,希望我们一起有点东西. Vue.js 具有简单的 API 和几个选项,可用于在我们的组件中定义HTML模板. 我们可以使用 <template> 标签选项,在根组件实例上定义 template 属性,或者使用单文件组件. 上面的选项很棒并且可以完美地工作,但是,在您的应用程序的生命周期中,有时会

  • 在vue中使用jsx语法的使用方法

    什么是JSX? JSX就是Javascript和XML结合的一种格式.React发明了JSX,利用HTML语法来创建虚拟DOM.当遇到<,JSX就当HTML解析,遇到{就当JavaScript解析. 我为什么要在vue中用JSX? 想折腾一下呗,开玩笑.最开始是因为近期在学习react,在里面体验了一把jsx语法,发现也并没有别人说的很难受的感觉啊,于是就想尝试在vue中也试下,废话不多说,先来用代码来看下两者的区别吧. ps:vue中大部分场景是不需要用render函数的,还是用模板更简洁直观

  • 详解Vue如何支持JSX语法

    通常开发vue我们使用的是模板语法,其实还有和react相同的语法,那就是render函数,同样支持jsx语法. Vue 的模板实际是编译成了 render 函数. 1.传统的createElement方法 createElement( 'anchored-heading', { props: { level: 1 } }, [ createElement('span', 'Hello'), ' world!' ] ) 渲染成下面这样 <anchored-heading :level="1

  • vue+render+jsx实现可编辑动态多级表头table的实例代码

    最近项目需要实现可编辑的动态多级表头表格,看了两天的文章,始终没有找到我想要的效果,在了解了render+jsx的基础用法后,自己基于element-ui封装了一个,数据格式参考element-ui table的数据.实现如下: 1.scoresTable <script> import scoresColumn from "./scoresColumn"; export default { components: { scoresColumn }, render: fun

随机推荐