Vue和React的一些對比:哪個更適合你?

Vue和React都是目前最流行、生態最好的前端框架之一。框架本身沒有優劣之分,只有適用之別,選擇符合自身業務場景、團隊基礎的技術才是我們最主要的目的。

博主1年前用的是Vue框架,近半年轉技術棧到React框架,對於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

React

from

'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)}>Reset

button

>

<

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

NewComponent

from

'./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

NewComponent

from

'./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}123

div

>

; } }/<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

:

Hi

'/<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

classNames

from

'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"

>This

is

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-browser

div

>

; }/<code>

7.生命週期

組件的生命週期一般包含:初始化、掛載、更新、卸載四個大階段,接下來分別看下vue和reac的生命週期。

vue

vue生命週期圖示:

Vue和React的一些對比:哪個更適合你?

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之前生命週期如下:

Vue和React的一些對比:哪個更適合你?

(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)

生命週期如下:

Vue和React的一些對比:哪個更適合你?

總結:(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.length

this

.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"

>

Greet

div

>

/<code>

method:

<code>  methods: {
    greet(

event

) { console.log(

event

); } }/<code>

(2)內聯調用方法

示例:

<code>

<

div

@

click

=

"greet('hello')"

>

Greet

div

>

/<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"

>

A

button

>

/<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 me

div

>

; } } /<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 me

div

>

; } } /<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 me

div

>

; } } /<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 me

div

>

; } } /<code>

結語

以上就是博主關於react和vue的一些對比以及個人思考的上部,覺得有收穫的可以關注一波,後續中部和下部會盡快持續更新,感謝關注。

作者:笪笪來源:掘金


為感謝您對我們的認可,特意準備了一些IT入門和進階的乾貨

包括:Java、UI設計、H5前端、Python+人工智能、軟件測試和新媒體運營六大學科視頻資料。以及IT就業大禮包。

線上視頻、音頻,隨時學習觀看

關注我們並私信“資料”即可獲取。

收藏

舉報

源碼時代/<code>
/<code>

掃碼下載今日頭條

/<code>
/<code>


分享到:


相關文章: