作為一位Vue工程師,這些開發技巧你都會嗎?
阿新 • • 發佈:2020-03-22
# 路由引數解耦
一般在元件內使用路由引數,大多數人會這樣做:
``` js
export default {
methods: {
getParamsId() {
return this.$route.params.id
}
}
}
```
在元件中使用 `$route` 會使之與其對應路由形成高度耦合,從而使元件只能在某些特定的 URL 上使用,限制了其靈活性。
正確的做法是通過 `props` 解耦
``` js
const router = new VueRouter({
routes: [{
path: '/user/:id',
component: User,
props: true
}]
})
```
將路由的 `props` 屬性設定為 `true` 後,元件內可通過 `props` 接收到 `params` 引數
``` js
export default {
props: ['id'],
methods: {
getParamsId() {
return this.id
}
}
}
```
另外你還可以通過函式模式來返回 `props`
``` js
const router = new VueRouter({
routes: [{
path: '/user/:id',
component: User,
props: (route) => ({
id: route.query.id
})
}]
})
```
文件:[https://router.vuejs.org/zh/guide/essentials/passing-props.html](https://router.vuejs.org/zh/guide/essentials/passing-props.html)
# 函式式元件
函式式元件是無狀態,它無法例項化,沒有任何的生命週期和方法。建立函式式元件也很簡單,只需要在模板新增 `functional` 宣告即可。一般適合只依賴於外部資料的變化而變化的元件,因其輕量,渲染效能也會有所提高。
元件需要的一切都是通過 `context` 引數傳遞。它是一個上下文物件,具體屬性檢視[文件](https://cn.vuejs.org/v2/guide/render-function.html#%E5%87%BD%E6%95%B0%E5%BC%8F%E7%BB%84%E4%BB%B6)。這裡 `props` 是一個包含所有繫結屬性的物件。
函式式元件
``` html
>>` 或 `/deep/` 解決這一問題:
``` scss
```
``` scss
```
# watch高階使用
### 立即執行
`watch` 是在監聽屬性改變時才會觸發,有些時候,我們希望在元件建立後 `watch` 能夠立即執行
可能想到的的方法就是在 `create` 生命週期中呼叫一次,但這樣的寫法不優雅,或許我們可以使用這樣的方法
``` js
export default {
data() {
return {
name: 'Joe'
}
},
watch: {
name: {
handler: 'sayName',
immediate: true
}
},
methods: {
sayName() {
console.log(this.name)
}
}
}
```
### 深度監聽
在監聽物件時,物件內部的屬性被改變時無法觸發 `watch` ,我們可以為其設定深度監聽
``` js
export default {
data: {
studen: {
name: 'Joe',
skill: {
run: {
speed: 'fast'
}
}
}
},
watch: {
studen: {
handler: 'sayName',
deep: true
}
},
methods: {
sayName() {
console.log(this.studen)
}
}
}
```
### 觸發監聽執行多個方法
使用陣列可以設定多項,形式包括字串、函式、物件
``` js
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](https://cn.vuejs.org/v2/api/#watch)
# watch監聽多個變數
watch本身無法監聽多個變數。但我們可以將需要監聽的多個變數通過計算屬性返回物件,再監聽這個物件來實現“監聽多個變數”
``` js
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` 是事件物件的特殊變數,在一些場景能給我們實現複雜功能提供更多可用的引數
### 原生事件
在原生事件中表現和預設的事件物件相同
``` html
```
``` js
export default {
methods: {
inputHandler(msg, e) {
console.log(e.target.value)
}
}
}
```
### 自定義事件
在自定義事件中表現為捕獲從子元件丟擲的值
`my-item.vue` :
``` js
export default {
methods: {
customEvent() {
this.$emit('custom-event', 'some value')
}
}
}
```
`App.vue`
``` html
```
``` js
export default {
methods: {
customEvent(index, e) {
console.log(e) // 'some value'
}
}
}
```
文件:[https://cn.vuejs.org/v2/guide/events.html#%E5%86%85%E8%81%94%E5%A4%84%E7%90%86%E5%99%A8%E4%B8%AD%E7%9A%84%E6%96%B9%E6%B3%95](https://cn.vuejs.org/v2/guide/events.html#%E5%86%85%E8%81%94%E5%A4%84%E7%90%86%E5%99%A8%E4%B8%AD%E7%9A%84%E6%96%B9%E6%B3%95)
[https://cn.vuejs.org/v2/guide/components.html#%E4%BD%BF%E7%94%A8%E4%BA%8B%E4%BB%B6%E6%8A%9B%E5%87%BA%E4%B8%80%E4%B8%AA%E5%80%BC](https://cn.vuejs.org/v2/guide/components.html#%E4%BD%BF%E7%94%A8%E4%BA%8B%E4%BB%B6%E6%8A%9B%E5%87%BA%E4%B8%80%E4%B8%AA%E5%80%BC)
# 自定義元件雙向繫結
元件 `model` 選項:
> 允許一個自定義元件在使用 v-model 時定製 prop 和 event。預設情況下,一個元件上的 v-model 會把 value 用作 prop 且把 input 用作 event,但是一些輸入型別比如單選框和複選框按鈕可能想使用 value prop 來達到不同的目的。使用 model 選項可以迴避這些情況產生的衝突。
`input` 預設作為雙向繫結的更新事件,通過 `$emit` 可以更新繫結的值
``` html
```
``` js
export default {
props: {
value: {
type: Boolean,
default: false
}
},
methods: {
switchChange(val) {
this.$emit('input', val)
}
}
}
```
修改元件的 `model` 選項,自定義繫結的變數和事件
``` html
```
``` js
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](https://cn.vuejs.org/v2/api/#model)
# 監聽元件生命週期
通常我們監聽元件生命週期會使用 `$emit` ,父元件接收事件來進行通知
子元件
``` js
export default {
mounted() {
this.$emit('listenMounted')
}
}
```
父元件
``` html
{{item.title}}
{{item.content}}
``` 父元件使用 ``` html