JSX是什么?

JSX 是一种 Javascript 的语法扩展,JSX = Javascript + XML,即在 Javascript 里面写 XML,因为 JSX 的这个特性,所以他即具备了 Javascript 的灵活性,同时又兼具 html 的语义化和直观性。

注:灵活度强的部分组件可以用JSX来代替,整个工程没有必要都使用JSX。

vue工程配置JSX相关插件

我们一般使用的渲染函数时这样的:

createElement(
'anchored-heading', {
props: {
level: 1
}
}, [
createElement('span', 'Hello'),
' world!'
]
)

对应的模板如下:

<anchored-heading :level="1">
<span>Hello</span> world!
</anchored-heading>

如果这样使用原生的方式来写比较麻烦,那么我可以借助babel插件。

如果是babel7.x那么需要安装如下插件

npm i @vue/babel-preset-jsx @vue/babel-helper-vue-jsx-merge-props -D

配置的babel.config.js:

module.exports = {
presets: [
[
'@vue/babel-preset-jsx',
{
vModel: false,
compositionAPI: true,
},
],
],
}

如果是babel6.x那么需要安装如下插件

npm install\
babel-plugin-syntax-jsx\
babel-plugin-transform-vue-jsx\
babel-helper-vue-jsx-merge-props\
babel-preset-env\
--save-dev

.babelrc:

{
"presets": ["env"],
"plugins": ["transform-vue-jsx"]
}

如果使用的vuecli2脚手架,那么默认安装了babel6.x相关的插件,不需要再重复安装。

详细可参考:《jsx-vue2》

JSX基础用法

我们新建一个HelloWorld组件,以前都是HelloWorld.vue的文件,现在我们可以使用HelloWorld.js来创建这个组件,下面以HelloWorld组件为例进行讲解。

自定义组件

我们在HelloWorld组件中也可以使用自定义的组件,HelloWorld.js代码如下:

const ButtonCounter = {
name: "button-counter",
props: ["count"],
methods: {
onClick() {
this.$emit("changeNum", this.count + 1);
}
},
render() {
return <button onClick={this.onClick}>数量:{this.count}</button>;
}
}; export default {
name: "HelloWorld",
props: {
msg: String
},
data() {
return {
count: 0
};
},
methods: {
// 改变button按钮数量
changeNum(val) {
this.count = val;
}
},
render() {
const { count } = this; // 解构
return (
<div class="hello-world-content">
<ButtonCounter style={{ marginTop: "20px" }} count={count} onChangeNum={this.changeNum}></ButtonCounter>
</div>
);
}
};

普通属性、行内样式、动态class与style

const ButtonCounter = {
name: "button-counter",
props: ["count"],
methods: {
onClick() {
this.$emit("changeNum", this.count + 1);
}
},
render() {
return <button onClick={this.onClick}>数量:{this.count}</button>;
}
}; export default {
name: "HelloWorld",
props: {
msg: String
},
data() {
return {
count: 0,
text: "Hello World!",
msgClass: "msg-class",
isGreen: true
};
},
methods: {
// 改变button按钮数量
changeNum(val) {
this.count = val;
}
},
render() {
const { count, text } = this; // 解构
return (
<div class="hello-world-content">
<p style="color:red">{text}</p>
<p class={this.msg ? this.msgClass : ""}>动态绑定class,传递过来的消息:{this.msg}</p>
<p style={this.isGreen ? "color: green" : ""}>动态绑定style,传递过来的消息:{this.msg}</p>
<input placeholder="placeholder属性"></input>
<ButtonCounter style={{ marginTop: "20px" }} count={count} onChangeNum={this.changeNum}></ButtonCounter>
</div>
);
}
};

展示效果:

DOM渲染结构如下:

常用指令

v-html、v-if、v-for、v-model常用指令在JSX中无法使用,需要使用其他方式来实现。

v-html

在JSX中,如果要设置DOM的innerHTML,需要用到domProps

组件使用:

<HelloWorld msg="<div class='custom-div'>这是自定义的DOM</div>"> </HelloWorld>

组件代码:

export default {
name: "HelloWorld",
props: {
msg: String
},
data() {
return {};
},
methods: {},
render() {
return <div domPropsInnerHTML={this.msg}></div>;
}
};

渲染DOM结果:

v-for

使用map来实现:

render() {
const list = [1,2,3]
return(
<div>
{ list.map(item => <button>按钮{item}</button>) }
</div>
)
}

v-if

简单示例:

render() {
const bool = false;
return <div>{bool ? <button>按钮1</button> : <button>按钮2</button>}</div>;
}

复杂示例:

render() {
let num = 3
if(num === 1){ return( <button>按钮1</button> ) }
if(num === 2){ return( <button>按钮2</button> ) }
if(num === 3){ return( <button>按钮3</button> ) }
}

v-model

注:新版 vue-cli4 中,已经默认集成了 JSX 语法对 v-model 的支持,可以直接使用

<input v-model={this.value}>

如果是老项目比如脚手架vuecli2,那么需要安装插件babel-plugin-jsx-v-model,同时在.babelrc文件中加入如下插件配置:

"plugins": ["jsx-v-model"]

使用示例:

export default {
name: "HelloWorld",
props: {
msg: String
},
data() {
return {
value: "abc"
};
},
watch: {
value(val) {
console.log("this.model内容:" + val);
}
},
methods: {},
render() {
return (
<div>
<input v-model={this.value} placeholder="普通文本" />
</div>
);
}
};

监听事件、事件修饰符

监听事件

监听事件想到用 onChange, onClick等。

需要注意的是,传参数不能使用 onClick={this.handleClick(params)},这样子会每次 render 的时候都会自动执行一次方法。

应该使用 bind,或者箭头函数来传参。

组件示例代码:

export default {
name: "HelloWorld",
props: {
msg: String
},
data() {
return {};
},
methods: {
handleClick(val) {
alert(val);
}
},
render() {
return (
<div>
<button type="button" onClick={this.handleClick.bind(this, 11)}>
方式一
</button>
<button type="button" onClick={() => this.handleClick(22)}>
方式二
</button>
</div>
);
}
};

用监听事件来实现v-model:

methods: {
input(e) {
this.value = e.target.value;
}
},
render() {
return (
<div>
<input type="text" value={this.value} onInput={this.input} />
</div>
);
}

也可以调整为:

<input type="text" value={this.value} onInput={(e) => (this.vaue = e.target.value)} />

还可以使用对象的方式去监听事件:

export default {
name: "HelloWorld",
props: {
msg: String
},
data() {
return {
value: ""
};
},
watch: {
value(val) {
console.log("this.model的内容:" + val);
}
},
methods: {
handleInput(e) {
this.value = e.target.value;
},
handleFocus(e) {
console.log(e.target);
}
},
render() {
return (
<div>
<input type="text" value={this.value} {...{ on: { input: this.handleInput, focus: this.handleFocus } }} />
</div>
);
}
};

nativeOn仅对于组件,用于监听原生事件,也可以使用对象的方式去监听事件:

{...{nativeOn:{click: this.handleClick}}}

事件修饰符

和指令一样,除了个别的之外,大部分的事件修饰符都无法在JSX中使用。

  • .stop : 阻止事件冒泡,在JSX中使用event.stopPropagation()来代替
  • .prevent:阻止默认行为,在JSX中使用event.preventDefault() 来代替
  • .self:只当事件是从侦听器绑定的元素本身触发时才触发回调,使用下面的条件判断进行代替
if (event.target !== event.currentTarget){
return
}

.enter与keyCode: 在特定键触发时才触发回调

if(event.keyCode === 13) {
// 执行逻辑
}

除了上面这些修饰符之外,尤大大对于.once,.capture,.passive,.capture.once做了优化,简化代码:

export default {
name: "HelloWorld",
props: {
msg: String
},
methods: {
handleClick(e) {
console.log("click事件:" + e.target);
},
handleInput(e) {
console.log("input事件:" + e.target);
},
handleMouseDown(e) {
console.log("mousedown事件:" + e.target);
},
handleMouseUp(e) {
console.log("mouseup事件" + e.target);
}
},
render() {
return (
<div
{...{
on: {
// 相当于 :click.capture
"!click": this.handleClick,
// 相当于 :input.once
"~input": this.handleInput,
// 相当于 :mousedown.passive
"&mousedown": this.handleMouseDown,
// 相当于 :mouseup.capture.once
"~!mouseup": this.handleMouseUp
}
}}
>
点击模块
</div>
);
}
};

结合第三方UI库组件

不仅仅在 render 函数里面使用 JSX,而且还可以在 methods 里面返回 JSX,然后在 render 函数里面调用这个方法。并且也可以直接使用例如elementui等ui组件。

示例:

export default {
name: "HelloWorld",
props: {
msg: String
},
data() {
return {
visible: false
};
},
methods: {
renderFooter() {
return (
<div>
<el-button onClick={() => (this.visible = false)}>确定</el-button>
<el-button onClick={() => this.closeDialog()}>取消</el-button>
</div>
);
},
openDialog() {
this.visible = true;
},
closeDialog() {
this.visible = false;
}
},
render() {
const footerHTML = this.renderFooter();
return (
<div>
<button onClick={() => this.openDialog()}>打开弹框</button>
<el-dialog visible={this.visible} title="弹框提示" width="200px" show-close={true} before-close={() => (this.visible = false)}>
<div>弹框内容</div>
<template slot="footer">{footerHTML}</template>
</el-dialog>
</div>
);
}
};

效果图:

插槽

普通插槽与具名插槽

示例:

<HelloWorld>
<template slot="default">默认内容</template>
<template slot="footer">
<el-button type="primary">确定</el-button>
<el-button>取消</el-button>
</template>
</HelloWorld>

HelloWorld组件代码:

export default {
name: "HelloWorld",
render() {
return (
<div>
<div class="default">{this.$slots.default}</div>
<div class="footer">{this.$slots.footer}</div>
</div>
);
}
};

作用域插槽

示例:

<HelloWorld>
<template v-slot:content="{ name, age }">
<div>姓名:{{ name }}</div>
<div>年龄:{{ age }}</div>
</template>
</HelloWorld>

HelloWorld组件代码:

export default {
name: "HelloWorld",
render() {
return (
<div>
<div class="content">{this.$scopedSlots.content({ name: "张三", age: 20 })}</div>
</div>
);
}
};

子组件通过{this.$scopedSlots.content({ name: "张三", age: 20 })}指定插槽的名称为content,并将含有name,age属性的对象数据传递给父组件,父组件就可以在插槽内容中使用子组件传递来的数据。

参考:

vue中如何使用JSX?的更多相关文章

  1. 在Vue中使用JSX,很easy的

    摘要:JSX 是一种 Javascript 的语法扩展,JSX = Javascript + XML,即在 Javascript 里面写 XML,因为 JSX 的这个特性,所以他即具备了 Javasc ...

  2. 在vue中使用jsx语法

    什么是JSX? JSX就是Javascript和XML结合的一种格式.React发明了JSX,利用HTML语法来创建虚拟DOM.当遇到<,JSX就当HTML解析,遇到{就当JavaScript解 ...

  3. vue中使用jsx

    vue中使用jsx 为什么需要使用jsx呢?这个需要搞清楚 其实vue官方也说了,对于那些非常多v-if v-else的情况,就可以尝试使用render函数或者jsx,不过render函数写简单的结构 ...

  4. vue中使用JSX报错,如何解决

    Support for the experimental syntax 'jsx' isn't currently enabled (32:12): 30 | }, 31 | render() { & ...

  5. 记录在vue中使用jsx时踩过的坑

    使用方法及细节就不一一说了. 1.给input或者textarea绑定value时,出现失效的问题.解决方法:https://github.com/vuejs/babel-plugin-transfo ...

  6. Vue 中渲染字符串形式的组件标签

    在vue中如果要渲染字符串形式的标签,vue 提供了 v-html 指令,可以很方便的渲染出来.但是如果这个标签是一个组件,或者element-ui 的组件时,就不能解析出来了,因为v-html 只能 ...

  7. vue中的页面渲染方案

    一.模板渲染 <div id="J_render_app"> <ul v-if="items.length"> <li v-for ...

  8. 理解MVVM在react、vue中的使用

    理解MVVM在react.vue中的使用 一:什么是MVC.为什么不用MVC 1:MVC的含义: M(modal):是应用程序中处理数据逻辑的部分. V (view)  :是应用程序中数据显示的部分. ...

  9. vue用template还是JSX?

    各自特点 template 模板语法(HTML的扩展) 数据绑定使用Mustache语法(双大括号) <span>{{title}}<span> JSX JavaScript的 ...

  10. TS 基础及在 Vue 中的实践:TypeScript 都发布 5.0 版本啦,现在不学更待何时!

    大家好,我是 Kagol,OpenTiny 开源社区运营,TinyVue 跨端.跨框架组件库核心贡献者,专注于前端组件库建设和开源社区运营. 微软于3月16日发布了 TypeScript 5.0 版本 ...

随机推荐

  1. SpringCloud 微服务简介

    一.认识微服务随着互联网行业的发展,对服务的要求也越来越高,服务架构也从单体架构逐渐演变为现在流行的微服务架构.这些架构之间有怎样的差别呢? 1.单体架构:将业务的所有功能集中在一个项目中开发,打成一 ...

  2. Swift开发基础05-可选项

    可选项定义 可选项,一般也叫可选类型,它允许将值设置为nil 在类型名称后面加个问号? 来定义一个可选项 var name: String? = "Jack" name = nil ...

  3. js 异步 任务 题目解析(chatgpt bug了?)

    最近遇到一道题如下,求输出结果 感觉还是蛮有意思的,找chatgpt做了一下 我是题 async function async1(){ console.log('1'); await async2() ...

  4. 图表绘制之RepeatNode的妙用

    图表绘制之RepeatNode的妙用 前言 最近接到许多大屏项目,其中有一个智慧大楼的项目,大致是由3d场景+数据图表组成,需要能监控实时数据.安防 监控.出入统计以及消防安全等功能如下图 但是在开发 ...

  5. Microsoft宣布将在开发人员会议上专注于.NET Aspire

    2024年7月15日微软宣布,其开发执行团队将在下个月的开发者大会上聚焦于使用 .NET Aspire 的云原生开发,以及结合人工智能的"现代 SQL"在 Microsoft Fa ...

  6. .NET Core 3.x 基于Autofac的AOP缓存

    一.依赖包 二.定义一个简单的缓存接口 /// <summary> /// 简单的缓存接口,只有查询和添加,以后会进行扩展 /// </summary> public inte ...

  7. Pandas库学习笔记(3)---Pandas Series

    Pandas Series Pandas Series基本操作 pandas.Series Series结构如下: pandas.Series(data, index, dtype, copy) 构造 ...

  8. Django Template层之Template概述

    Django Template层之Template概述 by:授客 QQ:1033553122 实践环境 Python版本:python-3.4.0.amd64 下载地址:https://www.py ...

  9. Python版WGCNA分析和蛋白质相互作用PPI分析教程

    在前面的教程中,我们介绍了使用omicverse完成基本的RNA-seq的分析流程,在本节教程中,我们将介绍如何使用omicverse完成加权基因共表达网络分析WGCNA以及蛋白质相互作用PPI分析. ...

  10. DASCTF 2023 & 0X401七月暑期挑战赛【PWN】(FileEditor篇)

    DASCTF 2023 & 0X401七月暑期挑战赛[PWN](FileEditor篇) 题目保护情况(保护全家桶) 64位ida逆向 模拟了一个类似vim的功能,有打开文件,打印内容,插入行 ...