Vue中JSX的基本用法及高級(jí)部分
基本用法
首先需要約定一下,使用JSX組件命名采用首字母大寫的駝峰命名方式,樣式可以少的可以直接基于vue-styled-components寫在同一個(gè)文件中,復(fù)雜的建議放在單獨(dú)的_Styles.js_文件中,當(dāng)然也可以不采用CSS-IN-JS的方式,使用Less/Sass來(lái)寫,然后在文件中import進(jìn)來(lái)。
下面是一個(gè)通用的骨架:
import styled from 'vue-styled-components' const Container = styled.div` heigth: 100%; ` const Dashboard = { name: 'Dashboard', render() { return ( <Container>內(nèi)容</Container> ) } } export default Dashboard
插值
在JSX中使用單個(gè)括號(hào)來(lái)綁定文本插值
<span>Message: {this.messsage}</span> <!-- 類似于v-html --> <div domPropsInnerHTML={this.dangerHtml}/> <!-- v-model --> <el-input v-model={this.vm.name} />
在jsx中不需要把v-model
分成事件綁定和賦值二部分分開來(lái)寫,因?yàn)橛邢鄳?yīng)的babel插件來(lái)專門處理。
樣式
在JSX中可以直接使用class="xx"
來(lái)指定樣式類,內(nèi)聯(lián)樣式可以直接寫成style="xxx"
<div class="btn btn-default" style="font-size: 12px;">Button</div> <!-- 動(dòng)態(tài)指定 --> <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中沒(méi)有v-for
和v-if
等指令的存在,這些全部需要采用Js的方式來(lái)實(shí)現(xiàn)
{/* 類似于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
<!-- 對(duì)應(yīng)@click --> <el-buton onClick={this.handleClick}>Click me</el-buton> <!-- 對(duì)應(yīng)@click.native --> <el-button nativeOnClick={this.handleClick}>Native click</el-button> <!-- 傳遞參數(shù) --> <el-button onClick={e => this.handleClick(this.id)}>Click and pass data</el-button>
注意:如果需要給事件處理函數(shù)傳參數(shù),需要使用箭頭函數(shù)來(lái)實(shí)現(xiàn)。如果不使用箭頭函數(shù)那么接收的將會(huì)是事件的對(duì)象event
屬性。
高級(jí)部分
在Vue中基于jsx也可以把組件拆分成一個(gè)個(gè)小的函數(shù)式組件,但是有一個(gè)限制是必需有一個(gè)外層的包裹元素,不能直接寫類似:
const Demo = () => ( <li>One</li> <li>Two</li> )
必需寫成:
const Demo = () => ( <div> <li>One</li> <li>Two</li> </div> )
而在React中可以使用空標(biāo)簽<></>
和<react.Fragment></react.Fragment>
來(lái)實(shí)現(xiàn)包裹元素,這里的空標(biāo)簽其實(shí)只是react.Fragment
的一個(gè)語(yǔ)法糖。同時(shí)在React 16中直接支持返回?cái)?shù)組的形式:
const Demo = () => [ <li>One</li> <li>Two</li> ]
那么在Vue中就只能通過(guò)遍歷來(lái)實(shí)現(xiàn)類似的功能,大體思路就是把數(shù)據(jù)先定義好數(shù)據(jù)然后直接一個(gè)map
生成,當(dāng)然如果說(shuō)元素的標(biāo)簽是不同類型的那就需要額外添加標(biāo)識(shí)來(lái)判斷了。
{ data() { return { options: ['one', 'two'] } }, render() { const LiItem = () => this.options.map(option => <li>{option}</li>) return ( <div> <ul> <LiItem /> </ul> </div> ) } }
事件修飾符
在基礎(chǔ)部分簡(jiǎn)單介紹了事件的綁定用法,這里主要是補(bǔ)充一下事件修飾符的寫法。
在模板語(yǔ)法中Vue提供了很多事件修飾符來(lái)快速處理事件的冒泡、捕獲、事件觸發(fā)頻率、按鍵識(shí)別等??梢灾苯硬榭垂俜轿臋n的事件&按鍵修飾符部分,這里把相關(guān)內(nèi)容原樣搬運(yùn)過(guò)來(lái):
修飾符 | 前綴 |
---|---|
.passive | & |
.capture | ! |
.once | ~ |
.capture.once 或.once.capture | ~! |
使用方式如下:
<el-button {...{ '!click': this.doThisInCapturingMode, '!keyup': this.doThisOnce, '~!mouseover': this.doThisOnceInCapturingMode }}>Click Me!</el-button>
下面給出的事件修飾符是需要在事件處理函數(shù)中寫出對(duì)應(yīng)的等價(jià)操作
修飾符 | 處理函數(shù)中的等價(jià)操作 |
---|---|
.stop | event.stopPropagation() |
.prevent | event.preventDefault() |
.self | if (event.target !== event.currentTarget) return |
按鍵: .enter , .13 | if (event.keyCode !== 13) return (對(duì)于別的按鍵修飾符來(lái)說(shuō),可將 13 改為另一個(gè)按鍵碼) |
修飾鍵: .ctrl , .alt , .shift , .meta | if (!event.ctrlKey) return (將 ctrlKey 分別修改為 altKey 、shiftKey 或者 metaKey ) |
下面是在事件處理函數(shù)中使用修飾符的例子:
methods: { keyup(e) { // 對(duì)應(yīng)`.self` if (e.target !== e.currentTarget) return // 對(duì)應(yīng) `.enter`, `.13` if (!e.shiftKey || e.keyCode !== 13) return // 對(duì)應(yīng) `.stop` e.stopPropagation() // 對(duì)應(yīng) `.prevent` e.preventDefault() // ... } }
ref和refInFor
在Vue中ref
被用來(lái)給元素或子組件注冊(cè)引用信息。引用信息將會(huì)注冊(cè)在父組件的 $refs
對(duì)象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子組件上,引用就指向組件。
注意:
因?yàn)?ref 本身是作為渲染結(jié)果被創(chuàng)建的,在初始渲染的時(shí)候你不能訪問(wèn)它們 - 它們還不存在$refs
不是響應(yīng)式的,因此你不應(yīng)該試圖用它在模板中做數(shù)據(jù)綁定。
當(dāng) v-for
用于元素或組件的時(shí)候,引用信息將是包含 DOM 節(jié)點(diǎn)或組件實(shí)例的數(shù)組。
假如在jsx中想要引用遍歷元素或組件的時(shí)候,例如:
const LiArray = () => this.options.map(option => ( <li ref="li" key={option}>{option}</li> ))
會(huì)發(fā)現(xiàn)從this.$refs.li
中獲取的并不是期望的數(shù)組值,這個(gè)時(shí)候就需要使用refInFor
屬性,并置為true
來(lái)達(dá)到在模板中v-for
中使用ref
的效果:
const LiArray = () => this.options.map(option => ( <li ref="li" refInFor={true} key={option}>{option}</li> ))
插槽(v-slot)
在jsx中可以使用this.$slots
來(lái)訪問(wèn)靜態(tài)插槽的內(nèi)容。
注意:在Vue 2.6.x版本后廢棄了
slot
和slot-scope
,在模板中統(tǒng)一使用新的統(tǒng)一語(yǔ)法v-slot
指令。v-slot
只能用于Vue組件和template
標(biāo)簽。
<div class="page-header__title"> {this.$slots.title ? this.$slots.title : this.title} </div>
等價(jià)于模板的
<div class="page-header__title"> <slot name="title">{{ title }}</slot> </div>
在Vue官方文檔中提到:**父級(jí)模板里的所有內(nèi)容都是在父級(jí)作用域中編譯的;子模板里的所有內(nèi)容都是在子作用域中編譯的。**因此像下面的示例是無(wú)法正常工作的
<current-user> {{ user.firstName }} </current-user>
在<current-user>
組件中可以訪問(wèn)到user
屬性,但是提供的內(nèi)容卻是在父組件渲染的。如果想要達(dá)到期望的效果,這個(gè)時(shí)候就需要使用作用域插槽了。下面是改寫后的代碼,更多知識(shí)點(diǎn)可以直接查看官方文檔的作用域插槽。
<!-- 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>
上面的示例其實(shí)就是官方的示例,這里需要說(shuō)明的是,其實(shí)在Vue中所謂的作用域插槽功能類似于React中的Render Props的概念,只不過(guò)在React中我們更多時(shí)候不僅提供了屬性,還提供了操作方法。但是在Vue中更多的是提供數(shù)據(jù)供父作用域渲染展示,當(dāng)然我們也可以把方法提供出去,例如:
<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>
在上面的代碼中我們實(shí)際上使用解構(gòu)的方式來(lái)取得injectedProps
,基于解構(gòu)的特性還可以重命名屬性名,在prop
為undefined
的時(shí)候指定初始值。
<current-user v-slot="{ user = { firstName: 'Guest' } }"> {{ user.firstName }} </current-user>
如果組件只有一個(gè)默認(rèn)的插槽還可以使用縮寫語(yǔ)法,將v-slot:default="slotProps"
寫成v-slot="slotProps"
,命名插槽寫成v-slot:user="slotProps"
,如果想要動(dòng)態(tài)插槽名還可以寫成v-slot:[dynamicSlotName]
,此外具名插槽同樣也有縮寫語(yǔ)法,例如 v-slot:header
可以被重寫為#header
上面介紹了很多插槽相關(guān)的知識(shí)點(diǎn)足已說(shuō)明其在開發(fā)過(guò)程中的重要性。說(shuō)了很多在模板中如何定義和使用作用域插槽,現(xiàn)在進(jìn)入正題如何在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內(nèi)置的指令除了v-show
以外都不支持,需要使用一些等價(jià)方式來(lái)實(shí)現(xiàn),比如v-if
使用三目運(yùn)算表達(dá)式、v-for
使用array.map()
等。
對(duì)于自定義的指令可以使用v-name={value}
的語(yǔ)法來(lái)寫,需要注意的是指令的參數(shù)、修飾符此種方式并不支持。以官方文檔指令部分給出的示例v-focus
使用為例,介紹二種解決辦法:
1 直接使用對(duì)象傳遞所有指令屬性
<input type="text" v-focus={{ value: true }} />
2 使用原始的vnode指令數(shù)據(jù)格式
{ directives:{ focus: { inserted: function(el) { el.focus() } } }, render() { const directives = [ { name: 'focus', value: true } ] return ( <div> <input type="text" {...{ directives }} /> </div> ) } }
過(guò)濾器
過(guò)濾器其實(shí)在開發(fā)過(guò)程中用得倒是不多,因?yàn)?strong>更多時(shí)候可以通過(guò)計(jì)算屬性來(lái)對(duì)數(shù)據(jù)做一些轉(zhuǎn)換和篩選。這里只是簡(jiǎn)單提及一下并沒(méi)有什么可以深究的知識(shí)點(diǎn)。
在模板中的用法如下:
<!-- 在雙花括號(hào)中 --> {{ message | capitalize }} <!-- 在 `v-bind` 中 --> <div v-bind:id="rawId | formatId"></div>
在jsx中使用方法為:
<div>{this.$options.filters('formatDate')('2019-07-01')}</div>
注意:由于Vue全局的過(guò)濾器只用于模板中,如果需要用于組件的方法中,可以把過(guò)濾器方法單獨(dú)抽離出一個(gè)公共Js文件,然后引入組件中,然后用于方法中。
源碼附件已經(jīng)打包好上傳到百度云了,大家自行下載即可~
鏈接: https://pan.baidu.com/s/1f6KoayeRaSFiXbSYswkkeQ
提取碼: wk4p
百度云鏈接不穩(wěn)定,隨時(shí)可能會(huì)失效,大家抓緊保存哈。
開源地址
碼云地址:
http://github.crmeb.net/u/defuGithub 地址:
http://github.crmeb.net/u/defu
總結(jié)
到此這篇關(guān)于Vue中JSX的基本用法及高級(jí)部分的文章就介紹到這了,更多相關(guān)Vue中JSX用法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue 自定義指令自動(dòng)獲取文本框焦點(diǎn)的方法
今天小編就為大家分享一篇vue 自定義指令自動(dòng)獲取文本框焦點(diǎn)的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-08-08Vue?數(shù)據(jù)綁定事件綁定樣式綁定語(yǔ)法示例
這篇文章主要為大家介紹了Vue?數(shù)據(jù)綁定事件綁定樣式綁定語(yǔ)法示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07基于vue和bootstrap實(shí)現(xiàn)簡(jiǎn)單留言板功能
這篇文章主要為大家詳細(xì)介紹了基于vue和bootstrap實(shí)現(xiàn)簡(jiǎn)單留言板功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-05-05關(guān)于vue的element-ui web端引入高德地圖并獲取經(jīng)緯度
這篇文章主要介紹了關(guān)于vue的element-ui web端引入高德地圖并獲取經(jīng)緯度,高德地圖首先要去申請(qǐng)key和密鑰,文中提供了部分實(shí)現(xiàn)代碼和解決思路,感興趣的朋友可以學(xué)習(xí)一下2023-04-04解決betterScroll在vue中存在圖片時(shí),出現(xiàn)拉不動(dòng)的問(wèn)題
今天小編就為大家分享一篇解決betterScroll在vue中存在圖片時(shí),出現(xiàn)拉不動(dòng)的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-09-09