週末在家刷如懿傳,順帶在youtube看了一個7-secret-patterns-about-vue的視頻,講得還蠻有意思的,確實有些地方意想不到。更多內容參見作者的github倉庫。
productivity Boosts
smart watchers
watch : {
msg: {
handler: 'fetchUserList', // fetchUserList is one of this.methods
immediate: true // call it on created
}
}
component Registration
用webpack的require.context來引入到處都會用到的components,注意缺點是打出來的包體積會變大,不如用到哪個引入哪個小。
// main.js
const requireComponent = require.context('.', false, /base-[\w-]+\.vue$/)
requireComponent.keys().forEach(fileName => {
const componentConfig = requireComponent(fileName)
const copmponentName = upperFirst(
camelCase(fileName.replace(/^\.\//,'').replace(/\.\w+$/,''))
)
Vue.component(componentName, componentConfig.default || componentConfig)
})
這裏先去找default再去找本身,是因爲import/export的機制與commonjs的引入機制不同。es6裏的import會自動import它的default,commonjs則不同。另外我用的是vue-cli3,在main.js中引入.vue文件,內容是在default中,不管有沒有<script>標籤。
module Registration
跟component Registration 原理一樣,但不用考慮增加了包體積的問題,相比更爲實用。注意在forEach中需要加上這句,把本身摘出去。
// index.js
if(fileName === './index.js') return
// 如果要加上namespaced, 用解構寫法
modules[moduleName] = {
namespaced: true,
...requireModule(fileName)
}
radical Tweaks
cleaner views
在router-view上掛一個key,每次都重新生成。就不用watch route 的變化了。
// html
<router-view :key="$route.params.id">
// .vue
created() {
this.getPost(this.$route.params.id)
}
transparent Wrappers
適用於表單控件,把父組件的$listeners傳給了子組件。v-on上和v-bind上都可以傳入對象,分別綁$attrs和$listeners。
<!--BaseInput.vue-->
<template>
<label>
{{ label }}
<input v-bind="$attrs" :value="value" v-on="listeners" />
</label>
</template>
<!--App.vue -->
<BaseInput placeholder="who am i" @focus="doSomething" />
listeners() {
return {
...this.$listeners,
input: event => this.$emit('input', event.target.value)
}
}
unlocked Possibilities
single-root component
適用於要列表渲染但沒有一個根元素的時候。直接render jsx。
// LI.vue
<script>
export default {
functional: true,
render(h, {props}) {
return props.route.map(route =>
<li key={route.name}>
<router-link to={route}>
{route.title}
</router-link>
</li>
)
}
}
</script>
rendering non-html
用於和第三方庫共同使用的時候,實際的渲染是第三方庫做的。主要包括三點:
- created的時候 從$parent裏拿到父組件,獲取其data來操作。
- beforeDestroy的時候,同樣獲取$parent的屬性,移除第三方庫的方法。
- 手寫render,return null。
這個代碼比較多,具體可以參見作者的sandbox