您當前的位置:首頁 > 文化

web前端---作為一位Vue工程師,這些開發技巧你都會嗎?

作者:由 Luka 發表于 文化時間:2021-11-04

路由引數解耦

一般在元件內使用路由引數,大多數人會這樣做:

export

default

{

methods

{

getParamsId

()

{

return

this

$route

params

id

}

}

}

在元件中使用 $route 會使之與其對應路由形成高度耦合,從而使元件只能在某些特定的 URL 上使用,限制了其靈活性。

正確的做法是透過 props 解耦

const

router

=

new

vueRouter

({

routes

[{

path

‘/user/:id’

component

User

props

true

}]

})

將路由的 props 屬性設定為 true 後,元件內可透過 props 接收到 params 引數

export

default

{

props

‘id’

],

methods

{

getParamsId

()

{

return

this

id

}

}

}

另外你還可以透過函式模式來返回 props

const

router

=

new

vueRouter

({

routes

[{

path

‘/user/:id’

component

User

props

route

=>

({

id

route

query

id

})

}]

})

文件:

https://

router。vuejs。org/zh/gui

de/essentials/passing-props。html

函式式元件

函式式元件是無狀態,它無法例項化,沒有任何的生命週期和方法。建立函式式元件也很簡單,只需要在模板新增 functional 宣告即可。一般適合只依賴於外部資料的變化而變化的元件,因其輕量,渲染效能也會有所提高。

元件需要的一切都是透過 context 引數傳遞。它是一個上下文物件,具體屬性檢視 文件 。這裡 props 是一個包含所有繫結屬性的物件。

函式式元件

<

template

functional

>

<

div

class

=

“list”

>

<

div

class

=

“item”

v-for

=

“item in props。list”

:key

=

“item。id”

@

click

=

“props。itemClick(item)”

>

<

p

>

{{item。title}}

p

>

<

p

>

{{item。content}}

p

>

div

>

div

>

template

>

父元件使用

<

template

>

<

div

>

<

List

:list

=

“list”

:itemClick

=

“item => (currentItem = item)”

/>

div

>

template

>

import

List

from

‘@/components/List。vue’

export

default

{

components

{

List

},

data

()

{

return

{

list

[{

title

‘title’

content

‘content’

}],

currentItem

‘’

}

}

}

文件:

https://

cn。vuejs。org/v2/guide/r

ender-function。html

樣式穿透

在開發中修改第三方元件樣式是很常見,但由於 scoped 屬性的樣式隔離,可能需要去除 scoped 或是另起一個 style 。

這些做法都會帶來副作用(元件樣式汙染、不夠優雅),樣式穿透在css預處理器中使用才生效。

我們可以使用 >>> 或 /deep/ 解決這一問題:

<

style

scoped

>

外層

>>>

el-checkbox

{

display

block

font-size

26

px

。el-checkbox__label

{

font-size

16

px

}

}

style

>

<

style

scoped

>

/

deep

/

el-checkbox

{

display

block

font-size

26

px

。el-checkbox__label

{

font-size

16

px

}

}

style

>

watch高階使用

立即執行

watch 是在監聽屬性改變時才會觸發,有些時候,我們希望在元件建立後 watch 能夠立即執行

可能想到的的方法就是在 create 生命週期中呼叫一次,但這樣的寫法不優雅,或許我們可以使用這樣的方法

export

default

{

data

()

{

return

{

name

‘Joe’

}

},

watch

{

name

{

handler

‘sayName’

immediate

true

}

},

methods

{

sayName

()

{

console

log

this

name

}

}

}

深度監聽

在監聽物件時,物件內部的屬性被改變時無法觸發 watch ,我們可以為其設定深度監聽

export

default

{

data

{

studen

{

name

‘Joe’

skill

{

run

{

speed

‘fast’

}

}

}

},

watch

{

studen

{

handler

‘sayName’

deep

true

}

},

methods

{

sayName

()

{

console

log

this

studen

}

}

}

觸發監聽執行多個方法

使用陣列可以設定多項,形式包括字串、函式、物件

export

default

{

data

{

name

‘Joe’

},

watch

{

name

‘sayName1’

function

newVal

oldVal

{

this

sayName2

()

},

{

handler

‘sayName3’

immaediate

true

}

},

methods

{

sayName1

()

{

console

log

‘sayName1==>’

this

name

},

sayName2

()

{

console

log

‘sayName2==>’

this

name

},

sayName3

()

{

console

log

‘sayName3==>’

this

name

}

}

}

文件:

https://

cn。vuejs。org/v2/api/#

watch

watch監聽多個變數

watch本身無法監聽多個變數。但我們可以將需要監聽的多個變數透過計算屬性返回物件,再監聽這個物件來實現“監聽多個變數”

export

default

{

data

()

{

return

{

msg1

‘apple’

msg2

‘banana’

}

},

compouted

{

msgObj

()

{

const

{

msg1

msg2

}

=

this

return

{

msg1

msg2

}

}

},

watch

{

msgObj

{

handler

newVal

oldVal

{

if

newVal

msg1

!=

oldVal

msg1

{

console

log

‘msg1 is change’

}

if

newVal

msg2

!=

oldVal

msg2

{

console

log

‘msg2 is change’

}

},

deep

true

}

}

}

事件引數$event

$event 是事件物件的特殊變數,在一些場景能給我們實現複雜功能提供更多可用的引數

原生事件

在原生事件中表現和預設的事件物件相同

<

template

>

<

div

>

<

input

type

=

“text”

@

input

=

“inputHandler(‘hello’, $event)”

/>

div

>

template

>

export

default

{

methods

{

inputHandler

msg

e

{

console

log

e

target

value

}

}

}

自定義事件

在自定義事件中表現為捕獲從子元件丟擲的值

my-item。vue :

export

default

{

methods

{

customEvent

()

{

this

$emit

‘custom-event’

‘some value’

}

}

}

App。vue

<

template

>

<

div

>

<

my-item

v-for

=

“(item, index) in list”

@

custom-event

=

“customEvent(index, $event)”

>

my-list

>

div

>

template

>

export

default

{

methods

{

customEvent

index

e

{

console

log

e

// ‘some value’

}

}

}

文件:

https://

cn。vuejs。org/v2/guide/e

vents。html

自定義元件雙向繫結

元件 model 選項:

允許一個自定義元件在使用 v-model 時定製 prop 和 event。預設情況下,一個元件上的 v-model 會把 value 用作 prop 且把 input 用作 event,但是一些輸入型別比如單選框和複選框按鈕可能想使用 value prop 來達到不同的目的。使用 model 選項可以迴避這些情況產生的衝突。

input 預設作為雙向繫結的更新事件,透過 $emit 可以更新繫結的值

<

my-switch

v-model

=

“val”

>

my-switch

>

export

default

{

props

{

value

{

type

Boolean

default

false

}

},

methods

{

switchChange

val

{

this

$emit

‘input’

val

}

}

}

修改元件的 model 選項,自定義繫結的變數和事件

<

my-switch

v-model

=

“num”

value

=

“some value”

>

my-switch

>

export

default

{

model

{

prop

‘num’

event

‘update’

},

props

{

value

{

type

String

default

‘’

},

num

{

type

Number

default

0

}

},

methods

{

numChange

()

{

this

$emit

‘update’

num

++

}

}

}

文件:

https://

cn。vuejs。org/v2/api/#

model

監聽元件生命週期

通常我們監聽元件生命週期會使用 $emit ,父元件接收事件來進行通知

子元件

export

default

{

mounted

()

{

this

$emit

‘listenMounted’

}

}

父元件

<

template

>

<

div

>

<

List

@

listenMounted

=

“listenMounted”

/>

div

>

template

>

其實還有一種簡潔的方法,使用 @hook 即可監聽元件生命週期,元件內無需做任何改變。同樣的, created 、 updated 等也可以使用此方法。

<

template

>

<

List

@

hook

mounted

=

“listenMounted”

/>

<

/template>

程式化的事件偵聽器

比如,在頁面掛載時定義計時器,需要在頁面銷燬時清除定時器。這看起來沒什麼問題。但仔細一看 this。timer 唯一的作用只是為了能夠在 beforeDestroy 內取到計時器序號,除此之外沒有任何用處。

export

default

{

mounted

()

{

this

timer

=

setInterval

(()

=>

{

console

log

Date

now

())

},

1000

},

beforeDestroy

()

{

clearInterval

this

timer

}

}

如果可以的話最好只有生命週期鉤子可以訪問到它。這並不算嚴重的問題,但是它可以被視為雜物。

我們可以透過 $on 或 $once 監聽頁面生命週期銷燬來解決這個問題:

export

default

{

mounted

()

{

this

creatInterval

‘hello’

this

creatInterval

‘world’

},

creatInterval

msg

{

let

timer

=

setInterval

(()

=>

{

console

log

msg

},

1000

this

$once

‘hook:beforeDestroy’

function

()

{

clearInterval

timer

})

}

}

使用這個方法後,即使我們同時建立多個計時器,也不影響效果。因為它們會在頁面銷燬後程序化的自主清除。

手動掛載元件

在一些需求中,手動掛載元件能夠讓我們實現起來更加優雅。比如一個彈窗元件,最理想的用法是透過命令式呼叫,就像 elementUI 的 this。$message 。而不是在模板中透過狀態切換,這種實現真的很糟糕。

先來個最簡單的例子:

import

vue

from

‘vue’

import

Message

from

‘。/Message。vue’

// 構造子類

let

Messageconstructor

=

vue

extend

Message

// 例項化元件

let

messageInstance

=

new

Messageconstructor

()

// $mount可以傳入選擇器字串,表示掛載到該選擇器

// 如果不傳入選擇器,將渲染為文件之外的的元素,你可以想象成 document。createElement()在記憶體中生成dom

messageInstance

$mount

()

// messageInstance。$el獲取的是dom元素

document

body

appendChild

messageInstance

$el

下面實現一個簡易的 message 彈窗元件

Message/index。vue

<

template

>

<

div

class

=

“wrap”

>

<

div

class

=

“message”

:class

=

“item。type”

v-for

=

“item in notices”

:key

=

“item。_name”

>

<

div

class

=

“content”

>

{{item。content}}

div

>

div

>

div

>

template

>

// 預設選項

const

DefaultOptions

=

{

duration

1500

type

‘info’

content

‘這是一條提示資訊!’

}

let

mid

=

0

export

default

{

data

()

{

return

{

notices

[]

}

},

methods

{

add

notice

=

{})

{

// name標識 用於移除彈窗

let

_name

=

this

getName

()

// 合併選項

notice

=

Object

assign

({

_name

},

DefaultOptions

notice

this

notices

push

notice

setTimeout

(()

=>

{

this

removeNotice

_name

},

notice

duration

},

getName

()

{

return

‘msg_’

+

mid

++

},

removeNotice

_name

{

let

index

=

this

notices

findIndex

item

=>

item

_name

===

_name

this

notices

splice

index

1

}

}

}

wrap

{

position

fixed

top

50

px

left

50

%

display

flex

flex-direction

column

align-items

center

transform

translateX

-50

%

);

}

message

{

——borderWidth

3

px

min-width

240

px

max-width

500

px

margin-bottom

10

px

border-radius

3

px

box-shadow

0

0

8

px

#ddd

overflow

hidden

}

content

{

padding

8

px

line-height

1。3

}

message

info

{

border-left

var

——

borderWidth

solid

#909399

background

#F4F4F5

}

message

success

{

border-left

var

——

borderWidth

solid

#67C23A

background

#F0F9EB

}

message

error

{

border-left

var

——

borderWidth

solid

#F56C6C

background

#FEF0F0

}

message

warning

{

border-left

var

——

borderWidth

solid

#E6A23C

background

#FDF6EC

}

Message/index。js

import

Vue

from

‘vue’

import

Index

from

‘。/index。vue’

let

messageInstance

=

null

let

Messageconstructor

=

Vue

extend

Index

let

init

=

()

=>

{

messageInstance

=

new

Messageconstructor

()

messageInstance

$mount

()

document

body

appendChild

messageInstance

$el

}

let

caller

=

options

=>

{

if

messageInstance

{

init

options

}

messageInstance

add

options

}

export

default

{

// 返回 install 函式 用於 Vue。use 註冊

install

vue

{

vue

prototype

$message

=

caller

}

}

main。js

import

Message

from

‘@/components/Message/index。js’

Vue

use

Message

使用

this

$messagae

({

type

‘success’

content

‘成功資訊提示’

duration

3000

})

文件:

https://

cn。vuejs。org/v2/api/#

vm-mount

作為一名web前端工程師,這些開發技巧你都會麼?

web前端---作為一位Vue工程師,這些開發技巧你都會嗎?

web前端全系列資料已經打包好了,希望能到各位!!!

標簽: 元件  name  exportdefault  item  div