Vue JSX、自定义 v-model
博客地址:https://ainyi.com/92
最初用到 JSX,就是做这个博客的时候。iview 表格组件,不支持像 element 那样直接写 html 代码渲染,只能通过 render 函数渲染,也就是 JSX 语法
这个说起来不陌生,JSX 是 react 框架的老本行了,玩 react 的同学肯定对这个也玩的很溜(最近在公司做的某些项目也是 react)
那我还是记录一下在 Vue JSX 的使用吧
JSX 定义
JSX 是一种 JavaScript 的语法扩展,多运用于 React 架构中。JSX = Javascript + XML,即在 Javascript 里面写 XML,即具备 Javascript 的灵活性,又有 html 的语义化和直观性
应用场景
有人说,Vue 的模板语法简单易上手,实现的功能也几乎足够。JSX 不好上手,写起来代码量也多,用来干啥呢
那你就忽略了 JavaScript 的灵活性了
- 一些复杂表单的实现
在这插播一个使用 vue 模板语法实现复杂表单的传送门:Element 动态渲染、移除表单并添加验证 & 动态添加、移除验证 - 函数式组件
函数式组件
简单说一下函数式组件
函数式组件就是函数是组件。使用过 React 的同学,应该不会对函数式组件感到陌生
函数式组件,我们可以理解为没有内部状态,没有生命周期钩子函数,没有 this(不需要实例化的组件)
在日常开发中,经常会开发一些纯展示性的业务组件,比如一些详情页面,列表界面等,它们有一个共同的特点是只需要将外部传入的数据进行展现,不需要有内部状态,不需要在生命周期钩子函数里面做处理,这时候你就可以考虑使用函数式组件
export default {
// 通过配置 functional 属性指定组件为函数式组件
functional: true,
// 组件接收的外部属性
props: {
avatar: {
type: String
}
},
/**
* 渲染函数
* @param {*} h
* @param {*} context 函数式组件没有 this, props, slots 等,都在 context 上面挂着
*/
render(h, context) {
const { props } = context
if (props.avatar) {
return <img src={props.avatar}></img>
}
return <img src="default-avatar.png"></img>
}
}
使用函数式组件的原因:
- 最主要最关键的原因是函数式组件不需要实例化,无状态,没有生命周期,所以渲染性能要好于普通组件
- 函数式组件结构比较简单,代码结构更清晰
函数式组件与普通组件的区别
- 函数式组件需要在组件上声明functional
- 函数式组件不需要实例化,所以没有 this,this通过render函数的第二个参数来代替
- 函数式组件没有生命周期钩子函数,不能使用计算属性、watch 等等
- 函数式组件不能通过 $emit 对外暴露事件,调用事件只能通过context.listeners.click的方式调用外部传入的事件
- 因为函数式组件是没有实例化的,所以在外部通过ref去引用组件时,实际引用的是 HTMLElement
- 函数式组件的props可以不用显示声明,所以没有在props里面声明的属性都会被自动隐式解析为 prop,而普通组件所有未声明的属性都被解析到 $attrs 里面,并自动挂载到组件根元素上面(可以通过 inheritAttrs 属性禁止)
模板语法声明函数式组件
在 Vue2.5 之前,使用函数式组件只能通过 JSX 的方式,在之后可以通过模板语法来声明函数式组件
<!-- 在template 上面添加 functional属性 -->
<template functional>
<img :src="props.avatar ? props.avatar : 'default-avatar.png'" />
</template>
<!-- 上面第 6 条,可以省略声明 props -->
了解 createElement
学习 JSX 之前,先了解 createElement
字面意思,创建元素 大名鼎鼎的虚拟DOM应该都知道吧,就是它的返回值 => 插播一个以前写过的VNode传送门:virtual DOM
关于 createElement 方法,有三个参数:
- 第一个参数主要用于提供 dom 的 html 内容,类型可以是字符串、对象或函数。比如 “div” 就是创建一个 div 标签
- 第二个参数(类型是对象)主要用于设置这个 dom 的一些样式、属性、传的组件的参数、绑定事件之类,具体可以参考 官方文档 里这一小节的说明
- 第三个参数(类型是数组,数组元素类型是 VNode)主要用于说是该节点下有其他结点的话,就放在这里
使用例子:
export default {
methods: {
$_handleChangeUser(value) {
this.formInline.user = value
}
},
render(h) {
return h(
'ElForm',
{
props: {
inline: true,
model: this.formInline
},
staticClass: 'demo-form-inline'
},
[
h(
'ElFormItem',
{
props: {
label: '用户名'
}
},
[
h('ElInput', {
props: {
value: this.formInline.user
},
attrs: {
placeholder: '请输入用户名'
},
on: {
input: this.$_handleChangeUser
}
})
]
)
]
)
}
}
看起来写法十分复杂,若页面上这么多元素,频繁使用 createElement 方法难免代码臃肿,这时就应该使用 JSX 代替 createElement 了
JSX
我们再来用 JSX 语法重新实现上面的代码
methods: {
$_handleInputUser(value) {
this.formInline.user = value
}
},
render(h) {
return (
<el-form inline model={this.formInline} class="demo-form-inline">
<el-form-item label="用户名">
<el-input
value={this.formInline.user}
onInput={this.$_handleInputUser}
placeholder="请输入用户名"
></el-input>
</el-form-item>
</el-form>
)
}
跟 react 一模一样了
将 h 作为 createElement 的别名 是 Vue 生态系统中的一个通用惯例,实际上也是 JSX 所要求的
从 Vue 的 Babel 插件的 3.4.0 版本开始,我们会在以 ES2015 语法声明的含有 JSX 的任何方法和 getter 中 (不是函数或箭头函数中) 自动注入const h = this.$createElement,这样就可以去掉 (h) 参数了。对于更早版本的插件,如果 h 在当前作用域中不可用,应用会报错
Vue JSX 中指令的使用
我们使用 Vue 模板语法,指令用的爽歪歪,像 v-model, v-if, v-for, @, 插槽等等
但是,这些都在 JSX 中无法使用。那么如何实现相同的功能呢
注意:新版 vue-cli4 中,已经默认集成了 JSX 语法对 v-model 的支持,可以直接使用
<input v-model={this.value}>
如果你的项目比较老,也可以安装插件 babel-plugin-jsx-v-model 来进行支持
自定义 v-model
v-model 是 Vue 提供的一个语法糖,它本质上是由 value 属性 + input 事件组成的(都是原生的默认属性)
所以在 JSX 中,我们可以通过传递 value 属性并监听 input 事件来实现数据的双向绑定
export default {
data() {
return {
name: ''
}
},
methods: {
// 监听 onInput 事件进行赋值操作
$_handleInput(e) {
this.name = e.target.value
}
},
render() {
// 传递 value 属性 并监听 onInput事件
return <input value={this.name} onInput={this.$_handleInput}></input>
}
}
封装组件如下:
子组件
<template>
<div>
<input :value="value" @change="$_handleChange" />
</div>
</template>
<script>
export default {
props: {
value: {
type: String,
default: ''
}
},
data() {
return {}
},
methods: {
$_handleChange(e) {
this.$emit('input', e.target.value)
}
}
}
</script>
父组件
<template>
<div class="home">
<krry-input v-model="say"></krry-input>
</div>
</template>
<script>
export default {
name: 'Home',
components: {
KrryInput: () => import('@/components/KrryInput')
},
data() {
return {
say: 'haha'
}
}
}
</script>
再次重申:新版 vue-cli4 中,已经默认集成了 JSX 语法对 v-model 的支持,可以直接使用 <input v-model={this.value}>
el-form 的 :model 属性
注意 el-form 的 :model 属性,在 JSX 中是这样写的 props={{ model: this.data }},比较特别
<el-form
ref="form"
labelWidth="140px"
rules={this.rules}
props={{ model: this.data }}>
<el-form-item label="券码编号: ">
<el-input v-model={this.data.voucherCode}></el-input>
</el-form-item>
<el-form>
v-if | v-for
这两个就比较常见,搞 react 都知道,v-if 可以使用三元表达式,true or false 来渲染组件;v-for 就使用 map 方法来实现
const list = ['宫', '商', '角', '徵', '羽']
return (
<ul>
{ list.map(ele => <li>{ele}</li>) }
</ul>
)
v-html | v-text
在 JSX 里面,如果要设置 dom 元素的 innerHTML,就用到 domProps
export default {
data() {
return {
content: '<div>这是我的自定义的 html 元素</div>'
}
},
render() {
// v-html 指令在 JSX 的写法是 domPropsInnerHTML
return <div domPropsInnerHTML={this.content}></div>
}
}
v-text 就没啥好说的了,<div domPropsInnerText={this.content}></div>
还不如直接使用 <div>{this.content}</div>
监听事件
监听事件想到用 onChange, onClick
需要注意的是,传参数不能使用 onClick={this.removePhone(params)},这样子会每次 render 的时候都会自动执行一次方法
应该使用 bind,或者箭头函数来传参
<button type="button" onClick={this.handleClick.bind(this, 11)}></button>
<button type="button" onClick={() => this.handleClick(11)}></button>
除此之外,还可以使用对象的方式去监听事件
render() {
return (
<el-input
value={this.content}
on={{
focus: this.$_handleFocus,
input: this.$_handleInput
}}
nativeOn={{
click: this.$_handleClick
}}
></el-input>
)
}
使用范围
不仅仅在 render 函数里面使用 JSX,而且还可以在 methods 里面返回 JSX,然后在 render 函数里面调用这个方法
JSX 还可以直接赋值给变量
methods: {
$_renderFooter() {
return (
<div>
<el-button>确定</el-button>
<el-button>取消</el-button>
</div>
)
}
},
render() {
const buttons = this.$_renderFooter()
return (
<el-dialog visible={this.visible}>
<div>弹窗内容</div>
<template slot="footer">{buttons}</template>
</el-dialog>
)
}
博客地址:https://ainyi.com/92
Vue JSX、自定义 v-model的更多相关文章
- vue jsx 使用指南
vue jsx 使用指南 vue jsx 语法与 react jsx 还是有些不一样,在这里记录下. let component = null // if 语句 if (true) { compone ...
- Vue基础-自定义事件的表单输入组件、自定义组件的 v-model
Vue 测试版本:Vue.js v2.5.13 学习 Vue 的自定义事件的表单输入组件,觉得文档讲的不太细致,所以这里再细化一下: 如果不用 v-model,代码应该是这样: <myinput ...
- vue jsx与render的区别及基本使用
vue template语法简单明了,数据操作与视图分离,开发体验友好.但是在某些特定场合中,会限制一些功能的扩展,如动态使用过滤器.解析字符串类型的模板文件等.以上功能的实现可以借助vue的rend ...
- element-ui 通用表单封装及VUE JSX应用
一.存在及需要解决的问题 一般在做后台OA的时候会发现表单重复代码比较多,且逻辑基本一样,每次新加一个表单都需要拷贝基本一致的代码结构,然后只是简单地修改对应的字段进行开发 二.预期结果 提取重复的表 ...
- Vue 3自定义指令开发
本文由葡萄城技术团队原创并首发 转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 什么是指令(directive) 在Angular和Vue中都有Direct ...
- 最简单的方式理解Vue的自定义指令与混合
vue.js 自定义指令 钩子函数:bindinsertedupdatecomponentUpdatedunbind 钩子函数完整实例:html: <div id="hook-argu ...
- Vue.js自定义指令的用法与实例
市面上大多数关于Vue.js自定义指令的文章都在讲语法,很少讲实际的应用场景和用例,以致于即便明白了怎么写,也不知道怎么用.本文不讲语法,就讲自定义指令的用法. 自定义指令是用来操作DOM的.尽管Vu ...
- vue中自定义组件(插件)
vue中自定义组件(插件) 原创 2017年01月04日 22:46:43 标签: 插件 在vue项目中,可以自定义组件像vue-resource一样使用Vue.use()方法来使用,具体实现方法: ...
- vue 通过自定义指令实现 置顶操作;
项目需求:要求当前项目每个页面滑到超出一屏的距离时,出现 backTop 按钮,点击则回到最顶端:俗称置顶操作: 因为涉及到的页面较多,每个页面都加肯定显得重复累赘,最终想到了 Vue 的自定义指令 ...
随机推荐
- 数据库整理(三) SQL基础
数据库整理(三) SQL基础 SQL语言的特点 集数据定义语言(DDL),数据操纵语言(DML),数据控制语言(DCL)功能于一体. 可以独立完成数据库生命周期中的全部活动: ●定义和修改.删除关 ...
- ZooKeeper开机启动的俩种方式
两种方式可以实现开机自启动 第一种:直接修改/etc/rc.d/rc.local文件 在/etc/rc.d/rc.local文件中需要输入两行, 其中export JAVA_HOME=/usr/jav ...
- 第二章、Web中使用shiro(实现登陆)
虽然Apache Shiro的核心设计目标允许它用于保护任何基于JVM的应用程序(如命令行应用程序,服务器守护程序,Web应用程序等),但本指南将着重讨论最常见的用例:确保运行的Web应用程序一个Se ...
- (二)、JAVA运行时数据区域
根据<Java 虚拟机规范(Java SE 7版)>规定,Java虚拟机所管理的内存,将会包括以下几个运行时数据区域: 注: 1.由所有线程共享的数据区: 对应 java内存模型的主内存, ...
- 韩顺刚-tcp报文头协议详细分析第一包数据:序号是0,发送数据的长度是0,因为没有收到对端的数据,所以确认号是0, Syn的标志位设置成1,这里没有发送的数据,只发送TCP的20个字节的头部
TCP报文段首部格式 大部分TCP报文头部都是20个字节,有的数据包要加上选项. 上面一行代表4个字节,源端口和目的端口都是2个字节. TCP协议是面向字节流的协议 TCP是一段一段分块的发送数据的 ...
- elasticSearch数据库、skywalking集群部署
Centos6上面安装elasticsearc数据库的集群 安装的是6.3.2版本,安装之前首先要先安装jdk1.8版本 安装之前首先需要关闭防火墙 Centos6 sudo service ipta ...
- Python3-gevent模块-单线程下的"并发"-协程
博客转载 http://www.cnblogs.com/alex3714/articles/5248247.html http://www.cnblogs.com/tkqasn/p/5705338.h ...
- SpringBoot--swagger搭建、配置及使用
一. 作用: 1. 接口的文档在线自动生成. 2. 接口测试. 二.模块介绍 Swagger是一组开源项目,其中主要要项目及功能如下: 1.Swagger Codegen: 通过Codegen 可以将 ...
- (私人收藏)古风PPT高级灰蓝传艺
古风PPT高级灰蓝传艺 https://pan.baidu.com/s/1ADgTfif8i6JqKORLXhTHHgn05p
- java语言进阶(四)_Map_斗地主案例
第一章 Map集合 1.1 概述 现实生活中常会看到这样的一种集合:IP地址与主机名,身份证号与个人,系统用户名与系统用户对象等,这种一一对应的关系,就叫做映射.Java提供了专门的集合类用来存放这种 ...