• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

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

vue 搞代码 4年前 (2022-01-08) 30次浏览 已收录 0个评论
文章目录[隐藏]

这篇文章主要给大家介绍了关于vue中正确使用jsx的相关资料,JSX就是Javascript和XML结合的一种格式,React发明了JSX,利用HTML语法来创建虚拟DOM,当遇到

前言

又到了愉快的摸鱼时间,我觉得不能荒废,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('anchore<i>本文来源gaodai$ma#com搞$代*码*网</i>d-heading', { template: ` <h1> </h1><h2> </h2><h3> </h3><h4> </h4><h5> </h5><h6> </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="{{">我是div</div>; }, 

props绑定

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

事件绑定

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

组件自定义事件

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

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

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

插槽

 // 父组件 setup() { const slots = { test: () => <div>具名插槽</div>, default: () => <div>默认插槽</div>, }; return () => ( <div> </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>显示</span><span>隐藏</span><span>{inputData.value}</span></div> ); }, 

最后

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

参考

    vue渲染函数

  • vuejsx文档
  • issues

以上就是vue中正确使用jsx语法的姿势分享的详细内容,更多请关注gaodaima搞代码网其它相关文章!


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:vue中正确使用jsx语法的姿势分享

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址