Vue中JSX的基本用法
基本用法
首先需要约定一下,使用JSX组件命名采用首字母大写的驼峰命名方式,样式可以少的可以直接基于vue-styled-components写在同一个文件中,复杂的建议放在单独的_Styles.js_文件中,当然也可以不采用CSS-IN-JS的方式,使用Less/Sass来写,然后在文件中import进来。
下面是一个通用的骨架:
import styled from 'vue-styled-components'const Container = styled.div`heigth: 100%;
`const Dashboard = {name: 'Dashboard',render() {return (<Container>内容</Container>)}
}export default Dashboard
插值
在JSX中使用单个括号来绑定文本插值
<span>Message: {this.messsage}</span>
<!-- 类似于v-html -->
<div domPropsInnerHTML={this.dangerHtml}/>
<!-- v-model -->
<el-input v-model={this.vm.name} />
在jsx中不需要把v-model
分成事件绑定和赋值二部分分开来写,因为有相应的babel插件来专门处理。
样式
在JSX中可以直接使用class="xx"
来指定样式类,内联样式可以直接写成style="xxx"
<div class="btn btn-default" style="font-size: 12px;">Button</div><!-- 动态指定 -->
<div class={`btn btn-${this.isDefault ? 'default' : ''}`}></div>
<div class={{'btn-default': this.isDefault, 'btn-primary': this.isPrimary}}></div>
<div style={{color: 'red', fontSize: '14px'}}></div>
遍历
在JSX中没有v-for
和v-if
等指令的存在,这些全部需要采用Js的方式来实现
{/* 类似于v-if */}
{this.withTitle && <Title />}{/* 类似于v-if 加 v-else */}
{this.isSubTitle ? <SubTitle /> : <Title />}{/* 类似于v-for */}
{this.options.map(option => {<div>{option.title}</div>
})}
事件绑定
事件绑定需要在事件名称前端加上on
前缀,原生事件添加nativeOn
<!-- 对应@click -->
<el-buton onClick={this.handleClick}>Click me</el-buton>
<!-- 对应@click.native -->
<el-button nativeOnClick={this.handleClick}>Native click</el-button>
<!-- 传递参数 -->
<el-button onClick={e => this.handleClick(this.id)}>Click and pass data</el-button>
注意:如果需要给事件处理函数传参数,需要使用箭头函数来实现。如果不使用箭头函数那么接收的将会是事件的对象event
属性。
高级部分
在Vue中基于jsx也可以把组件拆分成一个个小的函数式组件,但是有一个限制是必需有一个外层的包裹元素,不能直接写类似:
const Demo = () => (<li>One</li><li>Two</li>
)
必需写成:
const Demo = () => (<div><li>One</li><li>Two</li></div>
)
而在React中可以使用空标签<></>
和<react.Fragment></react.Fragment>
来实现包裹元素,这里的空标签其实只是react.Fragment
的一个语法糖。同时在React 16中直接支持返回数组的形式:
const Demo = () => [<li>One</li><li>Two</li>
]
那么在Vue中就只能通过遍历来实现类似的功能,大体思路就是把数据先定义好数据然后直接一个map
生成,当然如果说元素的标签是不同类型的那就需要额外添加标识来判断了。
{data() {return {options: ['one', 'two']}},render() {const LiItem = () => this.options.map(option => <li>{option}</li>)return (<div><ul><LiItem /></ul></div>)}
}
事件修饰符
在基础部分简单介绍了事件的绑定用法,这里主要是补充一下事件修饰符的写法。
在模板语法中Vue提供了很多事件修饰符来快速处理事件的冒泡、捕获、事件触发频率、按键识别等。可以直接查看官方文档的事件&按键修饰符部分,这里把相关内容原样搬运过来:
修饰符 | 前缀 |
---|---|
.passive
|
&
|
.capture
|
!
|
.once
|
~
|
.capture.once 或.once.capture
|
~!
|
使用方式如下:
<el-button {...{'!click': this.doThisInCapturingMode,'!keyup': this.doThisOnce,'~!mouseover': this.doThisOnceInCapturingMode
}}>Click Me!</el-button>
下面给出的事件修饰符是需要在事件处理函数中写出对应的等价操作
修饰符 | 处理函数中的等价操作 |
---|---|
.stop
|
event.stopPropagation()
|
.prevent
|
event.preventDefault()
|
.self
|
if (event.target !== event.currentTarget) return
|
按键: .enter , .13
|
if (event.keyCode !== 13) return (对于别的按键修饰符来说,可将 13 改为另一个按键码)
|
修饰键: .ctrl , .alt , .shift , .meta
|
if (!event.ctrlKey) return (将 ctrlKey 分别修改为 altKey 、shiftKey 或者 metaKey )
|
下面是在事件处理函数中使用修饰符的例子:
methods: {keyup(e) {// 对应`.self`if (e.target !== e.currentTarget) return// 对应 `.enter`, `.13`if (!e.shiftKey || e.keyCode !== 13) return// 对应 `.stop`e.stopPropagation()// 对应 `.prevent`e.preventDefault()// ...}
}
ref和refInFor
在Vue中ref
被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs
对象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件。
注意:
- 因为 ref 本身是作为渲染结果被创建的,在初始渲染的时候你不能访问它们 - 它们还不存在
$refs
不是响应式的,因此你不应该试图用它在模板中做数据绑定。
当 v-for
用于元素或组件的时候,引用信息将是包含 DOM 节点或组件实例的数组。
假如在jsx中想要引用遍历元素或组件的时候,例如:
const LiArray = () => this.options.map(option => (<li ref="li" key={option}>{option}</li>
))
会发现从this.$refs.li
中获取的并不是期望的数组值,这个时候就需要使用refInFor
属性,并置为true
来达到在模板中v-for
中使用ref
的效果:
const LiArray = () => this.options.map(option => (<li ref="li" refInFor={true} key={option}>{option}</li>
))
插槽(v-slot)
在jsx中可以使用this.$slots
来访问静态插槽的内容。
注意:在Vue 2.6.x版本后废弃了
slot
和slot-scope
,在模板中统一使用新的统一语法v-slot
指令。v-slot
只能用于Vue组件和template
标签。
<div class="page-header__title">{this.$slots.title ? this.$slots.title : this.title}
</div>
等价于模板的
<div class="page-header__title"><slot name="title">{{ title }}</slot>
</div>
在Vue官方文档中提到:**父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。**因此像下面的示例是无法正常工作的
<current-user>{{ user.firstName }}
</current-user>
在<current-user>
组件中可以访问到user
属性,但是提供的内容却是在父组件渲染的。如果想要达到期望的效果,这个时候就需要使用作用域插槽了。下面是改写后的代码,更多知识点可以直接查看官方文档的作用域插槽。
<!-- current-user组件定义部分 -->
<span><slot v-bind:user="user">{{ user.lastName }}</slot>
</span><!-- current-user 使用 -->
<current-user><template v-slot:default="slotProps">{{ slotProps.user.firstName }}</template>
</current-user>
上面的示例其实就是官方的示例,这里需要说明的是,其实在Vue中所谓的作用域插槽功能类似于React中的Render Props的概念,只不过在React中我们更多时候不仅提供了属性,还提供了操作方法。但是在Vue中更多的是提供数据供父作用域渲染展示,当然我们也可以把方法提供出去,例如:
<template><div><slot v-bind:injectedProps="slotProps">{{ user.lastName }}</slot></div>
</template><script>export default {data() {return {user: {firstName: 'snow',lastName: 'wolf'}}},computed: {slotProps() {return {user: this.user,logFullName: this.logFullName}}},methods: {logFullName() {console.log(`${this.firstName} ${this.lastName}`)}}}
</script>
在父组件中使用:
<current-user><template v-slot:default="{ injectedProps }"><div>{{ injectedProps.user.firstName }}</div><el-button @click="injectedProps.logFullName">Log Full Name</el-button></template>
</current-user>
在上面的代码中我们实际上使用解构的方式来取得injectedProps
,基于解构的特性还可以重命名属性名,在prop
为undefined
的时候指定初始值。
<current-user v-slot="{ user = { firstName: 'Guest' } }">{{ user.firstName }}
</current-user>
如果组件只有一个默认的插槽还可以使用缩写语法,将v-slot:default="slotProps"
写成v-slot="slotProps"
,命名插槽写成v-slot:user="slotProps"
,如果想要动态插槽名还可以写成v-slot:[dynamicSlotName]
,此外具名插槽同样也有缩写语法,例如 v-slot:header
可以被重写为#header
上面介绍了很多插槽相关的知识点足已说明其在开发过程中的重要性。说了很多在模板中如何定义和使用作用域插槽,现在进入正题如何在jsx中同样使用呢?
// current-user components
{data() {return {user: {firstName: 'snow',lastName: 'wolf'}}},computed: {slotProps() {return {user: this.user,logFullName: this.logFullName}}},methods: {logFullName() {console.log(`${this.firstName} ${this.lastName}`)}},render() {return (<div>{this.$scopedSlots.subTitle({injectedProps: this.slotProps})}</div>)}
}
然后在父组件中以jsx使用:
<current-user {...{scopedSlots: {subTitle: ({ injectedProps }) => (<div><h3>injectedProps.user</h3><el-button onClick={injectedProps.logFullName}>Log Full Name</el-button></div>)}
}}></current-user>
指令
这里需要注意的是在jsx中所有Vue内置的指令除了v-show
以外都不支持,需要使用一些等价方式来实现,比如v-if
使用三目运算表达式、v-for
使用array.map()
等。
对于自定义的指令可以使用v-name={value}
的语法来写,需要注意的是指令的参数、修饰符此种方式并不支持。以官方文档指令部分给出的示例v-focus
使用为例,介绍二种解决办法:
1 直接使用对象传递所有指令属性
<input type="text" v-focus={{ value: true }} />
2 使用原始的vnode指令数据格式
{directives:{focus: {inserted: function(el) {el.focus()}}},render() {const directives = [{ name: 'focus', value: true }]return (<div><input type="text" {...{ directives }} /></div>)}
}
过滤器
过滤器其实在开发过程中用得倒是不多,因为更多时候可以通过计算属性来对数据做一些转换和筛选。这里只是简单提及一下并没有什么可以深究的知识点。
在模板中的用法如下:
<!-- 在双花括号中 -->
{{ message | capitalize }}<!-- 在 `v-bind` 中 -->
<div v-bind:id="rawId | formatId"></div>
在jsx中使用方法为:
<div>{this.$options.filters('formatDate')('2019-07-01')}</div>
注意:由于Vue全局的过滤器只用于模板中,如果需要用于组件的方法中,可以把过滤器方法单独抽离出一个公共Js文件,然后引入组件中,然后用于方法中。
源码附件已经打包好上传到百度云了,大家自行下载即可~
链接: https://pan.baidu.com/s/14G-bpVthImHD4eosZUNSFA?pwd=yu27
提取码: yu27
百度云链接不稳定,随时可能会失效,大家抓紧保存哈。
如果百度云链接失效了的话,请留言告诉我,我看到后会及时更新~
开源地址
码云地址:
http://github.crmeb.net/u/defu
Github 地址:
http://github.crmeb.net/u/defu
Vue中JSX的基本用法相关推荐
- 「后端小伙伴来学前端了」Vue中 this.$set的用法 | 可用于修改对象中数组的某一个对象、 可用于更新数据到视图
夜晚有明月,梦里有佳人 前言 最近在写老师布置的vue项目,真的说实话,每天真就是在百度.google.bing等各个搜索引擎之间反复横跳,不然就是掘金搜一搜.思否搜一搜,还有CSDN看一看.我的前端 ...
- 详解Vue中watch的高级用法
转载自 详解Vue中watch的高级用法 我们通过实例代码给大家分享了Vue中watch的高级用法,对此知识点有需要的朋友可以跟着学习下. 假设有如下代码: 1 2 3 4 5 6 7 8 9 10 ...
- vue中的keep-alive的用法详细讲解
问题描述(什么是keep-alive) keep-alive顾名思义,保持活跃.保持谁活跃呢? 首先我们知道,因为vue就是组件化编程,一个.vue文件就是一个组件.就像万事万物一样,都有从出生到消亡 ...
- vue中引入路径的用法
一.Vue文件中引用路径的介绍 1.路径 ./ ./当前文件同级目录 2.路径 -/ -/当前文件上一级目录 3.@符号 @ 的作用是在你引入模块时,可以使用 @ 代替 /src 目录,避免易错的相对 ...
- vue 中provide的用法_[转]浅谈vue中provide和inject 用法
provide:Object | () => Object inject:Array | { [key: string]: string | Symbol | Object } provide ...
- VUE中$refs的基本用法
ref 有三种用法: 1.ref 加在普通的元素上,用this.$refs.(ref值) 获取到的是dom元素 2.ref 加在子组件上,用this.r e f s . ( r e f 值 ) 获 取 ...
- Vue中v-on的基础用法、参数传递和修饰符
目录 一.v-on的基本用法 使用v-on:click给button绑定监听事件以及回调函数,@是v-on:的缩写,也就是简写也可以使用@click.方法一般是需要写方法名加上(),在@click中可 ...
- vue中 this.$set的用法
当vue的data里边声明或者已经赋值过的对象或者数组(数组里边的值是对象)时,向对象中添加新的属性,如果更新此属性的值,是不会更新视图的.<template><div id=&qu ...
- vue 中provide的用法_浅谈vue中provide和inject 用法
一.概念解析 成对出现:provide和inject是成对出现的 作用:用于父组件向子孙组件传递数据 使用方法:provide在父组件中返回要传给下级的数据,inject在需要使用这个数据的子辈组件或 ...
最新文章
- 微信电视来了 微信遥控传屏弹幕统统有
- CentOS 6.5系统下安装和配置NFS服务
- java的语法树,JAVA语言语法树.doc
- 举例详细说明javascript作用域、闭包原理以及性能问题(转)
- 算法提高课-搜索-DFS之连通性模型-AcWing 1113. 红与黑:dfs和bfs两种做法
- 关于flutter列表的性能优化,你必须要了解的
- CodeForces - 504B Misha and Permutations Summation(线段树模拟康托展开与逆展开)
- python 库 全局变量_python局部变量和全局变量global
- js属性对象的hasOwnProperty方法
- 猫眼娱乐上市首日破发 收盘价14.64港元
- views.py视图函
- solidity之call相关函数
- Wincc安装教程+破解教程(包括软件下载链接——百度网盘)
- 教程:批量自动删除微博
- VScode+esp-idf:编译腾讯物联网控制台ESP32例程(esp-qcloud)
- 下载文件夹压缩为zip格式时打开报不可预料的压缩文件末端
- workman安装以及使用
- 请回答2021,爱彼迎、木鸟民宿、途家民宿年度走心PK
- python 遍历,删除,复制文件夹下所有文件
- APP商店货币化的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
热门文章
- 蓝色蝴蝶(好听的毕业歌)
- Substrate Tutorials:Start a Private Network (multi-node)
- 阿里云ACP云计算错题集1-40
- 苹果 App Store 最贵的 App,评论亮了!!
- 【计算机视觉】一个简单易上手的图像分类任务pipeline代码
- java ole excel_用OLE操作Excel
- 等保2.0三级云计算扩展要求
- Kettle读取按行分割的文件
- 基于归一化互相关函数的语音基音周期检测
- 微信小程序激活账号时,提示“此帐号已激活,请使用帐号密码直接登录”