Vue和React都是目前最流行、生態最好的前端框架之一。框架本身沒有優劣之分,只有適用之別,選擇符合自身業務場景、團隊基礎的技術才是我們最主要的目的。
博主1年前用的是Vue框架,近半年轉技術棧到React框架,對於Vue和React都有一些基本的瞭解。接下來將與大家一起走近Vue和React,共同探討它們的差異。(比如你正在用vue,對react感興趣也可以看下兩者之間的用法差異,反之亦然)
整體內容概覽:
由於內容較長,將分上、中、下三部分和大家一起共同探討(有不同意見的歡迎文章下方一起探討交流,感謝支持)。
1.背景
vue
Google 前工程師尤雨溪於 2014 年創建了這個框架。Vue是一套用於構建用戶界面的漸進式框架。與其它大型框架不同的是,Vue 被設計為可以自底向上逐層應用。Vue 的核心庫只關注視圖層,不僅易於上手,還便於與第三方庫或既有項目整合。
react
與 Vue 不同,react 庫是由 Facebook 創建的。最初是為了 Facebook 廣告流量管理創建的。那時 Facebook 遇到了維護和編碼方面的問題。它以動態創建和交互式 UI 的能力而聞名。
2.核心思想
vue與react都推崇組件式的開發理念,但是在設計的核心思想上有很大差別。
vue
vue的整體思想仍然是擁抱經典的html(結構)+css(表現)+js(行為)的形式,vue鼓勵開發者使用template模板,並提供指令供開發者使用(v-if、v-show、v-for等等),因此在開發vue應用的時候會有一種在寫經典web應用(結構、表現、行為分離)的感覺。另一方面,在針對組件數據上,vue2.0通過Object.defineProperty對數據做到了更細緻的監聽,精準實現組件級別的更新。
react
react整體上是函數式的思想,組件使用jsx語法,all in js,將html與css全都融入javaScript,jsx語法相對來說更加靈活,我一開始剛轉過來也不是很適應,感覺寫react應用感覺就像是在寫javaScript。當組件調用setState或props變化的時候,組件內部render會重新渲染,子組件也會隨之重新渲染,可以通過shouldComponentUpdate或者PureComponent可以避免不必要的重新渲染(個人感覺這一點上不如vue做的好)。
3.組件形式
vue
vue組件定義使用xx.vue文件來表示,vue組件將html、css、js組合到一起,模板部分使用數據使用{{}},形式如下:
<code><
div
> {{name}}div
>template
><
script
>
export
default
{name
:'NewComponent'
, data() {return
{name
:'xx'
} } }script
><
style
scoped
>style
> /<code>
組件使用:
<code><new
-component name="xx"
/>/<code>
react
react推薦使用jsx或者js文件來表示組件,react支持class組件和function組件2種形式,react使用{}包裹變量,這點需要注意。
注意: 組件名稱必須以大寫字母開頭。React 會將以小寫字母開頭的組件視為原生 DOM 標籤。例如,
代表 HTML 的 div 標籤,而 則代表一個組件,並且需在作用域內使用 Welcome。(1)class組件
<code>import
Reactfrom
'react'
;class
NewComponent
extends
React
.Component
{constructor
(props) {super
(props);this
.state = {name
:'xx'
}; } render() { rerurn(<
div
>{name}div
>); } }export
default
NewComponent;/<code>
(2)function組件
hooks的出現賦予了function組件管理state的能力。
<code>import
React, { useState }from
'react'
;function
NewComponent
() {const
[name, setName] = useState(''
);return
(<
div
>{name}div
>); }export
default
NewComponent;/<code>
4.數據管理(props、data vs state)
組件數據管理通常包含2部分,來自父組件的數據props與自身的數據。
vue與react中的props都是單向數據流的,父級prop的更新會向下流動到子組件中,但是反過來則不行。prop可以是數組或對象,用於接收來自父組件的數據。
vue
props
vue中的props支持傳遞靜態或動態props,靜態props一般傳遞字符串。
<code><
blog-post
title
="My journey with Vue"
>blog-post
>/<code>
靜態prop傳遞布爾值true可以這樣寫,傳值false仍然需要使用動態prop傳值。
<code>/<code>
動態賦值使用v-bind,可以簡寫為:。
<code>"tile">blog-post
><
blog-post
:title
="tile"
>blog-post
>/<code>
動態prop常用來傳遞對象、數組、布爾值(false值,true值可以直接傳屬性)等。
<code>:title="post.title + ' by ' + post.author.name"
>/<code>
data
vue中使用data來管理組件的數據,vue 將會遞歸將 data 的屬性轉換為 getter/setter,從而讓 data 的屬性能夠響應數據變化。對象必須是純粹的對象 (含有零個或多個的 key/value 對)。一旦觀察過,不需要再次在數據對象上添加響應式屬性。因此推薦在創建實例之前,就聲明所有的根級響應式屬性。
當一個組件被定義,data必須聲明為返回一個初始數據對象的函數。
<code>export
default
{name
:'NewComponent'
,data
() { return { name:'xxx'
, age:12
} } }/<code>
當需要在組件內部修改數據時,可以直接通過vue實例修改:
<code> methods: { changeName() {this
.name ='new Name'
; } }/<code>
react
props
react中的props也與vue一樣可以傳遞靜態或動態props,靜態props一般傳遞字符串。
函數組件和class組件都可以使用props,函數組件使用props參數獲取父組件傳下來的props。
函數組件獲取props:
<code>function
Welcome
(props
) {return
<
h1
>Hello, {props.name}h1
>; }const
element =<
Welcome
name
="Sara"
/> ; 複製代碼/<code>
class組件使用this.props獲取組件props:
<code>class
Welcome
extends
React
.Component
{constructor
(props) {super
(props); } render() {const
{ name } =this
.props;return
<
div
>{name}div
>; } }/<code>
動態props:
<code><
Welcome
name
={name}
/>/<code>
state
react中使用state來管理組件內的數據,hooks的出現使得函數組件也具備管理state的能力。
class組件state
class組件在構造函數(constructor)中定義組件內數據(state),修改數據必須通過setState修改,不能直接修改state,這點非常重要。
class組件使用state:
<code>class
Welcome
extends
React
.Component
{constructor
(props) {super
(props);this
.state = { name:'xx'
};this
.changeName =this
.changeName.bind(this
); } changeName() {this
.setState({ name:'new name'
}); } render() {const
{ name } =this
.state;return
this.changeName}>{name}
; } }/<code>
關於class組建的setState有以下兩點說明:
- 1.setState更新是異步的,但是在setTimeout和原生事件中是同步的。
- 2.setState更新的是組件的部分數據,react會自動將數據合併。
當需要使用上一個state值時,可以讓 setState() 接收一個函數而不是一個對象。這個函數用上一個 state 作為第一個參數,將此次更新被應用時的 props 做為第二個參數:
<code>this
.setState((state, props)
=> ({ counter: state.counter + props.increment })); /<code>
function組件useState
react 16.0之前函數組件只是純的渲染組件,hooks的出現賦予了函數組件管理state的能力。
useState返回一個state,以及更新state的函數。如果新的 state 需要通過使用先前的 state 計算得出,那麼可以將函數傳遞給 setState。該函數將接收先前的 state,並返回一個更新後的值。
<code>import
React, { useState }from
'react'
;function
Counter
({initialCount}
) {const
[count, setCount] = useState(initialCount);return
(<>
Count: {count}<
button
onClick
={()
=> setCount(initialCount)}>Resetbutton
><
button
onClick
={()
=> setCount(prevCount => prevCount - 1)}>-button
><
button
onClick
={()
=> setCount(prevCount => prevCount + 1)}>+button
>>
); }/<code>
關於setState有以下三點說明:
1.與 class 組件中的 setState 方法不同,useState 不會自動合併更新對象。2.只能在函數最外層調用 Hook。不要在循環、條件判斷或者子函數中調用。3.只能在 React 的函數組件或自定義hook中調用 Hook。不要在其他 JavaScript 函數中調用。
5.組件數據交互
組件數據交互是指父子組件、兄弟組件、跨層組件之間傳遞數據。 兄弟組件之間可以通過事件總線或者通過父組件傳遞數據,這裡就不詳細贅述。
5.1.父子組件數據交互(props+自定義事件 vs props+回調)
對於父子組件數據交互,vue中使用prop+自定義事件實現,react通過props+回調實現。
vue
vue中父組件通過props傳遞數據給子組件,子組件使用$emit觸發自定義事件,父組件中監聽子組件的自定義事件獲取子組件傳遞來的數據。
子組件使用$emit傳遞自定義事件myEvent:
<code><
template
><
div
@click
="changeName"
>{{name}}div
>template
><
script
>
export
default
{name
:'NewComponent'
, data() {return
{name
:'xxx'
,age
:12
} },methods
: { changeName() {this
.name ='new Name'
;this
.$emit('myEvent'
,this
.name); } } }script
>/<code>
父組件使用@myEvent監聽自定義事件,回調函數參數是子組件傳回的數據:
<code><
template
><
div
><
new-component
@myEvent
="getName"
>new-component
>div
>template
><
script
>
import
NewComponentfrom
'./NewComponent'
;export
default
{components
: { NewComponent }, data() {return
{} },methods
: { getName(name) {console
.log(name) } } }script
> /<code>
react
react中父組件使用props傳遞數據和回調函數給子組件,子組件通過props傳下來的回調函數返回數據,父組件通過回調函數獲取子組件傳遞上來的數據。
子組件通過props接收父組件傳下來的回調事件:
<code>import
React, { useState }from
'react'
;function
Children
(props
) {const
{ myEvent } = props;const
[name, setName] = useState('xxx'
);const
changeName =()
=> { setName('new name'
); myEvent('new name'
); };return
<
div
onClick
={changeName}
>{name}div
>; }/<code>
父組件通過回調事件獲取子組件傳遞的參數:
<code>function
Parent
() {const
changeName =name
=> {console
.log(name); };return
<
Children
myEvent
={changeName}
>Children
> ; }/<code>
5.2.跨組件數據交互(provide/inject vs Context)
vue和react都支持跨組件傳遞數據,vue中主要通過provide / inject實現,react中主要通過Context實現。
vue
vue中通過provide / inject在祖先組件向所有子孫後代注入一個依賴,不論組件層次有多深,並在起上下游關係成立的時間裡始終生效。
祖先組件中定義provide選項,provide選項應該是一個對象或返回一個對象的函數。
<code><
template
><
div
><
new-component
@myEvent
="getName"
>new-component
>div
>template
><
script
>
import
NewComponentfrom
'./NewComponent'
;export
default
{provide
: {message
:'This is a big news'
},components
: { NewComponent }, data() {return
{} },methods
: { getName(name) {console
.log(name) } } }script
> /<code>
子組件通過inject選項獲取祖先組件的provide選項值,inject選項應該是一個字符串數組或者對象。
<code><
template
><
div
>{{message}}div
>template
><
script
>
export
default
{name
:'Children'
,inject
: ['message'
], data() {return
{} } }script
>/<code>
注意:provide 和 inject 綁定並不是可響應的。這是刻意為之的。然而,如果你傳入了一個可監聽的對象,那麼其對象的屬性還是可響應的。
react
Context 提供了一個無需為每層組件手動添加 props,就能在組件樹間進行數據傳遞的方法。
在父組件創建一個Context對象,通過Context.provider的value屬性向消費組件傳值。
<code>import
React, { useState }from
'react'
;const
MyContext = React.createContext({theme
:'black'
});function
Parent
() {const
changeName =name
=> {console
.log(name); };return
(<
MyContext.Provider
value
={{
theme:
'white
' }}><
Children
myEvent
={changeName}
>Children
>;MyContext.Provider
>); }/<code>
消費組件獲取Context有2種方式:
(1)class組件通過contextType獲取最近Context上的那個值。
<code>class
DeepChildren1
extends
React
.Component
{constructor
(props) {super
(props); }static
contextType = MyContext; render() {return
<
div
>{this.context.theme}123div
>; } }/<code>
(2)函數式組件通過Context.Consumer訂閱到Context的變更。
<code>function
DeepChildren
(props
) {return
(<
MyContext.Consumer
> { (value) => (<
div
>{value.theme}div
> ) }MyContext.Consumer
>); }/<code>
關於Context需要注意:
當Provider的父組件進行重渲染時,consumers組件會重新渲染,並且沒有辦法避免,應該儘量避免使用Context。
6.class與style
關於class與style處理上,vue與react也存在較大差異。
vue
vue對class與style特意做了增強,可以傳字符串、對象、數組。
class
(1)給class綁定字符串:
<code>class
="hello"
>div
>(2)給class綁定對象:
<code>class
="static"
:class
="{ active: isActive, 'text-danger': hasError }"
>div
>data如下:
<code>data:
{
isActive:
true
,
hasError:
false
}
/<code>HTML 將被渲染為:
<code>class
="static active"
>div
>(3)給class綁定數組:
<code>:class=
"[activeClass, errorClass]"
>/<code>data如下:
<code>data
: {activeClass
:'active'
, errorClass:'text-danger'
}/<code>HTML 將被渲染為:
<code>class
="active text-danger"
>div
>(4)class還可以直接綁定到組件上,這一點react並不支持。
聲明組件如下:
<code>Vue
.component
('my-component'
, {template
: '/<code>在使用它的時候添加一些 class:
<code>class
="baz boo"
>my-component
>/<code>HTML 將被渲染為:
<code>class="foo bar baz boo">Hi
/<code>style
style用來綁定內聯樣式,支持傳對象、數組,使用需要添加瀏覽器引擎前綴的 CSS 屬性時,如 transform,Vue.js 會自動偵測並添加相應的前綴。
(1)傳對象,CSS 屬性名可以用駝峰式 (camelCase) 或短橫線分隔 (kebab-case,記得用引號括起來) 來命名:
<code>:style=
"{ color: activeColor, fontSize: fontSize + 'px' }"
>/<code>data如下:
<code>data
: {activeColor
:'red'
, fontSize:20
}/<code>HTML將被渲染為:
<code><
div
style
="color: red; font-size: 20px;"
>div
>/<code>(2)傳數組將多個樣式應用到同一個元素上
<code>:style=
"[baseStyles, overridingStyles]"
>/<code>data如下:
<code>baseStyles
: {fontSize
:'20px'
, color:'blue'
},overridingStyles
: {height
:'80px'
}/<code>HTML將被渲染為:
<code><
div
style
="font-size: 20px; color: blue; height: 80px;"
>div
>/<code>react
react使用className用於指定css的class,react中不能直接為組件指定class。
className
react中className一般傳值字符串常量或者字符串變量,不能傳遞數組或者對象語法。
(1)傳字符串常量:
<code>function
NewComponent
() {return
<
div
className
="container"
>This is New Component.div
>; }/<code>(2)傳字符串變量:
<code>function
NewComponent
() {const
newClass ='conrainer'
return
<
div
className
={newClass}
>This is New Component.div
>; }/<code>(3)傳遞多個class,可以使用es6的模板字符串實現:
<code>function
NewComponent
() {const
newClass ='conrainer'
return
<
div
className
={
`${newClass
}new-container
`}>This is New Component.div
>; }/<code>當需要傳遞數組或者對象語法時,可以引入classnames庫實現:
<code>import
classNamesfrom
'classnnames'
;function
NewComponent
() {const
newClass ='container'
;return
<
div
className
={classNames(newClass,
'newContainer
', {bar:
true
}, ['new-class
', {c:
true
}])}>This is New Component.div
>; }/<code>html將被渲染為:
<code>class=
"container newContainer bar new-class c"
>Thisis
New Component./<code>style
通常不推薦將 style 屬性作為設置元素樣式的主要方式。在多數情況下,應使用 className 屬性來引用外部 CSS 樣式表中定義的 class。style 在 React 應用中多用於在渲染過程中添加動態計算的樣式。
style接收一個對象
<code>const
divStyle = {color
:'blue'
,backgroundImage
:'url('
+ imgUrl +')'
, };function
HelloWorldComponent
() {return
<
div
style
={divStyle}
>Hello World!div
>; }/<code>注意:樣式不會自動補齊前綴。如需支持舊版瀏覽器,請手動補充對應的樣式屬性:
<code>const
divStyle = {WebkitTransition
:'all'
,msTransition
:'all'
};function
ComponentWithTransition
() {return
<
div
style
={divStyle}
>This should work cross-browserdiv
>; }/<code>7.生命週期
組件的生命週期一般包含:初始化、掛載、更新、卸載四個大階段,接下來分別看下vue和reac的生命週期。
vue
vue生命週期圖示:
vue生命週期包含:
- beforeCreate
實例組件剛創建,元素DOM和數據都還沒有初始化,暫時不能在這個週期裡面進行任何操作。 - created
數據data已經初始化完成,方法也已經可以調用,但是DOM未渲染。調用後臺接口獲取數據可以在這個階段完成。 - beforeMount
DOM未完成掛載,數據也初始化完成,但是數據的雙向綁定還是顯示{{}},虛擬DOM結構已經生成。 - mounted
數據和DOM都完成掛載,在上一個週期佔位的數據把值給渲染進去。這個週期適合執行初始化需要操作DOM的方法。 - beforeUpdate
頁面數據改變了都會觸發,在更新前觸發,此時的數據還是未更新前的數據,沒有數據改變則不執行。 - updated
頁面數據改變都會觸發,在更新完成之後觸發,此時的數據是更新後的數據。
注意:在這裡操作數據很容易引起卡死。
- beforeDestroy
組件銷燬之前執行,在這個週期裡仍然可以訪問data和method,多組件間通信需要發佈信息時可以在該階段完成。 - destroyed
當離開組件對應頁面時組件銷燬時觸發,主要用於取消一些副作用(取消事件監聽、取消定時器、取消不必要的請求等)
react
react生命週期分為16.0之前和16.0之後:
16.0之前
react16.0之前生命週期如下:
(1)初始化
- constructor
是class組件的默認方法,常用來初始化state或者設置屬性等。
<code>class
Counter
extends
React
.component
{constructor
(props){super
(props);this
.state = {count
:0
};this
.color ='red'
; } }/<code>
(2)掛載階段
- componentWillMount()
組件掛載之前調用,並且只會調用一次。 - render
render是一個React組件必須定義的生命週期函數,用來渲染DOM。 並必須 return 一個React元素(描述組件,即UI),不負責組件實際渲染工作,之後由React自身根據此元素去渲染出頁面DOM。
不要在render裡面修改state,會引起死循環導致卡死。
- componentDidMount()
組件掛在完成之後調用,在這個階段可以獲取真實dom元素,常用來發起異步請求獲取數據。
(3)更新階段
當通過setState修改state或父組件重新render引起props更新,都會引起子組件的重新render。
- componentWillReceiveProps(nextProps)
props發生變化以及父組件重新渲染時都會觸發該生命週期函數。在該階段可以通過參數nextProps獲取變化後的props參數, 通過this.props訪問之前的props。該生命週期內可以進行setState。 - shouldComponentUpdate(nextProps,nextState)
組件每次setState或者父組件重新render都會引起子組件render,可以使用該鉤子比較nextProps,nextState及當前組件的this.props,this.state的狀態用來判斷是否需要重新渲染。默認返回true,需要重新render,返回false則不觸發渲染。
一般我們通過該鉤子來優化性能,避免子組件不必要的渲染。
- componentWillUpdate(nextProps, nextState)
當組件收到新的 props 或 state 時,會在渲染之前調用。使用此作為在更新發生之前執行準備更新的機會。初始渲染不會調用此方法。
注意:不能在此方法中調用this.setState
- componentDidUpdate(prevProps, prevState) 此方法在組件更新後被調用。首次渲染不會執行此方法。當組件更新後,可以在此處對DOM進行操作。
注意:可以在componentDidUpdate()中直接調用setState(),但是它必需被包裹在一個條件語句裡,否則會導致死循環。
(4)卸載階段
- componentWillUnmount()
會在組件卸載及銷燬之前直接調用。在此方法中執行必要的清理操作,例如,清除 timer,取消網絡請求或清除在componentDidMount() 中創建的訂閱等。
注意:componentWillUnmount() 中不應調用 setState(),因為該組件將永遠不會重新渲染。
16.0之後
react 16.0之後移除的生命週期函數:
- componentWillMount
- componentWillReceiveProps
- componentWillUpdate
但是為了向下兼容,react並未刪除這三個生命週期,新增以 UNSAFE_ 前綴為別名的三個函數 UNSAFE_componentWillMount()、
UNSAFE_componentWillReceiveProps()、
UNSAFE_componentWillUpdate()。
新增的生命週期函數:
- static getDerivedStateFromProps(nextProps, prevState)
- getSnapshotBeforeUpdate(prevProps, prevState)
生命週期如下:
總結:(1)初始化階段保持不變(2)掛載階段: getDerivedStateFromProps => render => componentDidMount(3)更新階段 getDerivedStateFromProps => shoudeComponentUpdate => render => getSnapshotBeforeUpdate => componentDidUpdate(4)卸載階段保持不變
接下來重點介紹getDerivedStateFromProps、getSnapshotBeforeUpdate兩個方法。
(1)static getDerivedStateFromProps(props, state)
getDerivedStateFromProps 會在調用 render 方法之前調用,並且在初始掛載及後續更新時都會被調用。它應返回一個對象來更新 state,如果返回 null 則不更新任何內容。
當state的值在任何時候都取決於props的時候適用該方法。
示例如下:
<code>class
ScrollingList
extends
React
.Component
{constructor
(props) {super
(props); }static
getDerivedStateFromProps(nextProps, prevState) {if
(nextProps.type !== prevState.type) {return
{type
: nextProps.type, }; }return
null
; } render() {return
(<
div
>{/* ...contents... */}div
> ); } }/<code>
(2)getSnapshotBeforeUpdate(prevProps, prevState)
getSnapshotBeforeUpdate() 在最近一次渲染輸出(提交到 DOM 節點)之前調用。它使得組件能在發生更改之前從 DOM 中捕獲一些信息(例如,滾動位置)。此生命週期的任何返回值將作為參數傳遞給 componentDidUpdate()。此用法並不常見,但它可能出現在 UI 處理中,如需要以特殊方式處理滾動位置的聊天線程等。應返回 snapshot 的值(或 null)。
示例如下:
<code>class
ScrollingList
extends
React
.Component
{constructor
(props) {super
(props);this
.listRef = React.createRef(); } getSnapshotBeforeUpdate(prevProps, prevState) {if
(prevProps.list.lengththis
.props.list.length) {const
list =this
.listRef.current;return
list.scrollHeight - list.scrollTop; }return
null
; } componentDidUpdate(prevProps, prevState, snapshot) {if
(snapshot !==null
) {const
list =this
.listRef.current; list.scrollTop = list.scrollHeight - snapshot; } } render() {return
(this.listRef}>{ }
); } }/<code>
8.事件處理(@Click vs onClick)
vue與react在針對事件處理上的用法上也有較大不同。
vue
vue中使用 v-on 指令監聽 DOM 事件,並在觸發時運行一些 JavaScript 代碼。通常使用v-on接收一個需要調用的方法名稱。
(1)直接綁定方法,不傳任何參數,回調函數參數是瀏覽器事件event對象。
示例:
<code><
div
@click
="greet"
>Greetdiv
>/<code>
method:
<code> methods: { greet(event
) { console.log(event
); } }/<code>
(2)內聯調用方法
示例:
<code><
div
@click
="greet('hello')"
>Greetdiv
>/<code>
method:
<code>methods: { greet(message) {this
.message = message; } }/<code>
有時也需要在method中訪問原生DOM事件,可以將$event顯式傳入method中。
<code>/<code>
method:
<code>methods: { greet(message,event
) {this
.message = message; } }/<code>
(3)事件修飾符和按鍵修飾符
Vue.js為事件添加了事件修飾符和按鍵修飾符(個人感覺這個是vue做的很好的點,讓用戶更加聚焦數據邏輯,無需花費更多的精力處理DOM事件細節)。
Ⅰ. 事件修飾符
在事件處理程序中調用 event.preventDefault() 或 event.stopPropagation() 是非常常見的需求。為了解決這個問題,Vue.js 為 v-on 提供了事件修飾符,修飾符是由點開頭的指令後綴來表示的。
- .stop:阻止事件繼續傳播
- .prevent:阻止事件默認行為
- .capture:添加事件監聽器時使用事件捕獲模式
- .self:當前元素觸發時才觸發事件處理函數
- .once:事件只觸發一次
- .passive:告訴瀏覽器你不想阻止事件的默認行為,不能和.prevent一起使用。
示例:
<code><
a
v-on:click.stop
="doThis"
>a
><
form
v-on:submit.prevent
="onSubmit"
>form
><
a
v-on:click.stop.prevent
="doThat"
>a
><
form
v-on:submit.prevent
>form
><
div
v-on:click.capture
="doThis"
>...div
><
div
v-on:click.self
="doThat"
>...div
><
a
v-on:click.once
="doThis"
>a
><
button
@click.ctrl.exact
="onCtrlClick"
>Abutton
>/<code>
④ 鼠標按鈕修飾符這些修飾符會限制處理函數僅響應特定的鼠標按鈕。
- .left
- .right
- .middle
關於v-on處理事件的好處:1.掃一眼 HTML 模板便能輕鬆定位在 JavaScript 代碼裡對應的方法。2.因為你無須在 JavaScript 裡手動綁定事件,你的 ViewModel 代碼可以是非常純粹的邏輯,和 DOM 完全解耦,更易於測試。3.當一個 ViewModel 被銷燬時,所有的事件處理器都會自動被刪除。你無須擔心如何清理它們。
react
React 元素的事件處理和 DOM 元素的很相似,但是有一點語法上的不同:
- React 事件的命名採用小駝峰式(camelCase),而不是純小寫。
- 使用 JSX 語法時你需要傳入一個函數作為事件處理函數,而不是一個字符串。
(1)事件處理程序不傳參數
在class組件中使用回調函數,需要顯式綁定this或者使用箭頭函數。
不傳參數時,默認參數是e,這是一個合成事件。React 根據 W3C 規範來定義這些合成事件,所以你不需要擔心跨瀏覽器的兼容性問題。
在React中不能通過返回false的方式阻止默認行為,你必須顯式的使用preventDefault。
顯示綁定this:
<code>class
NewComponent
extends
React
.Component
{constructor
(props) {super
(props);this
.handleClick =this
.handleClick.bind(this
); } handleClick(e) { e.preventDefault();console
.log(e.target); } render() {return
<
div
onClick
={this.handleClick}
>Click mediv
>; } } /<code>
箭頭函數:
<code>class
NewComponent
extends
React
.Component
{constructor
(props) {super
(props); } handleClick =(
e
) => { e.preventDefault();console
.log(e.target); }; render() {return
<
div
onClick
={this.handleClick}
>Click mediv
>; } } /<code>
(2)事件處理程序傳遞參數
通常我們會為事件處理函數傳遞額外的參數,有兩種方式向事件處理函數傳遞參數:
Ⅰ. 箭頭函數傳遞參數通過箭頭函數的方式,事件對象e必需顯示的進行傳遞。
<code>class
NewComponent
extends
React
.Component
{constructor
(props) {super
(props);this
.handleClick =this
.handleClick.bind(this
); } handleClick(e, message) { e.preventDefault();console
.log(message); }; render() {return
<
div
onClick
={(e)
=> this.handleClick(e, 'hello')}>Click mediv
>; } } /<code>
Ⅱ. 通過bind形式傳遞參數e作為第二個參數傳遞,事件對象以及更多的參數將會被隱式的傳遞。
<code>class
NewComponent
extends
React
.Component
{constructor
(props) {super
(props); } handleClick(message, e) { e.preventDefault();console
.log(message); }; render() {return
<
div
onClick
={this.handleClick.bind(this,
'hello
')}>Click mediv
>; } } /<code>
結語
以上就是博主關於react和vue的一些對比以及個人思考的上部,覺得有收穫的可以關注一波,後續中部和下部會盡快持續更新,感謝關注。
作者:笪笪來源:掘金
為感謝您對我們的認可,特意準備了一些IT入門和進階的乾貨
包括:Java、UI設計、H5前端、Python+人工智能、軟件測試和新媒體運營六大學科視頻資料。以及IT就業大禮包。
線上視頻、音頻,隨時學習觀看
關注我們並私信“資料”即可獲取。
收藏
舉報
源碼時代/<code>/<code>掃碼下載今日頭條
/<code>/<code>