vue中如何使用JSX?
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?的更多相关文章
- 在Vue中使用JSX,很easy的
摘要:JSX 是一种 Javascript 的语法扩展,JSX = Javascript + XML,即在 Javascript 里面写 XML,因为 JSX 的这个特性,所以他即具备了 Javasc ...
- 在vue中使用jsx语法
什么是JSX? JSX就是Javascript和XML结合的一种格式.React发明了JSX,利用HTML语法来创建虚拟DOM.当遇到<,JSX就当HTML解析,遇到{就当JavaScript解 ...
- vue中使用jsx
vue中使用jsx 为什么需要使用jsx呢?这个需要搞清楚 其实vue官方也说了,对于那些非常多v-if v-else的情况,就可以尝试使用render函数或者jsx,不过render函数写简单的结构 ...
- vue中使用JSX报错,如何解决
Support for the experimental syntax 'jsx' isn't currently enabled (32:12): 30 | }, 31 | render() { & ...
- 记录在vue中使用jsx时踩过的坑
使用方法及细节就不一一说了. 1.给input或者textarea绑定value时,出现失效的问题.解决方法:https://github.com/vuejs/babel-plugin-transfo ...
- Vue 中渲染字符串形式的组件标签
在vue中如果要渲染字符串形式的标签,vue 提供了 v-html 指令,可以很方便的渲染出来.但是如果这个标签是一个组件,或者element-ui 的组件时,就不能解析出来了,因为v-html 只能 ...
- vue中的页面渲染方案
一.模板渲染 <div id="J_render_app"> <ul v-if="items.length"> <li v-for ...
- 理解MVVM在react、vue中的使用
理解MVVM在react.vue中的使用 一:什么是MVC.为什么不用MVC 1:MVC的含义: M(modal):是应用程序中处理数据逻辑的部分. V (view) :是应用程序中数据显示的部分. ...
- vue用template还是JSX?
各自特点 template 模板语法(HTML的扩展) 数据绑定使用Mustache语法(双大括号) <span>{{title}}<span> JSX JavaScript的 ...
- TS 基础及在 Vue 中的实践:TypeScript 都发布 5.0 版本啦,现在不学更待何时!
大家好,我是 Kagol,OpenTiny 开源社区运营,TinyVue 跨端.跨框架组件库核心贡献者,专注于前端组件库建设和开源社区运营. 微软于3月16日发布了 TypeScript 5.0 版本 ...
随机推荐
- Vscode连接虚拟机报错
Vscode 连接虚拟机报错问题解决 问题解释 Permission denied, please try again.出现这个问题通常表示身份验证失败. 可能的原因有 SSH用户密码错误 SSH端口 ...
- Simple WPF: S3实现MINIO大文件上传并显示上传进度
最新内容优先发布于个人博客:小虎技术分享站,随后逐步搬运到博客园. 创作不易,如果觉得有用请在Github上为博主点亮一颗小星星吧! 目的 早两天写了一篇S3简单上传文件的小工具,知乎上看到了一个问题 ...
- 用户数据报协议UDP
UDP的首部格式如下: (1) 源端口,源端口号.在需要对方回信时选用.不需要时可用全0. ⑵目的端口,目的端口号.这在终点交付报文时必须使用. ⑶长度,UDP用户数据报的长度,其最小值是8(仅有首部 ...
- PN转Modbus RTU模块连接ACS4QQ变频器通信
一台完整的机器在出厂前由许多部件组成.但是,由于各种原因,这些组件来自不同的制造商,导致设备之间的通信协议存在差异.Modbus和Profinet代表两种不同的通信协议,Profinet通常用于较新的 ...
- oeasy教您玩转vim - 11 - # 向前向后
向前向后 回忆上节课内容 我们上次强化了起手势 回忆了基本的移动方式 hjkl 除 hjkl 外,据说还有更厉害的移动方式 是什么呢? 下素材 #这个素材,我们下载过,重温一下 wget github ...
- C#全局键盘监听(Hook)的使用
一.为什么需要全局键盘监听? 在某些情况下应用程序需要实现快捷键执行特定功能,例如大家熟知的QQ截图功能Ctrl+Alt+A快捷键,只要QQ程序在运行(无论是拥有焦点还是处于后台运行状态),都可以按下 ...
- SQL Server 清除一个数据库下所有表数据,保留表结构
用法:在需要清空数据的数据库创建并执行存储过程,该存储过程并不会影响其他数据库 请小心使用这些脚本,确保在生产环境之前备份您的数据库.️ 存储过程: CREATE PROCEDURE ClearAll ...
- 火山引擎VeDI数据技术分享:两个步骤,为Parquet降本提效
更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 作者:王恩策.徐庆 火山引擎 LAS 团队 火山引擎数智平台 VeDI 是火山引擎推出的新一代企业数据智能平台,基 ...
- 【Project】JS的Map对象前后交互问题
这是我在项目中写的一个Map对象: let map = new Map(); for (let i = 0; i < type_checked_value.length; i++) { let ...
- 最快视频转绘-AnimateDiff-Lightning
最快视频转绘-AnimateDiff-Lightning Video-to-Video Generation AnimateDiff-Lightning 非常适合视频到视频的生成.使用 Control ...