watch的优化写法
我们平时总会遇到组件创建时获取列表,筛选项改变后刷新列表的需求,在watch
中的逻辑,还要在组件的created()
中再执行一遍,以下写法解决此痛点。
bad
1 2 3 4 5 6 7 8 9 10
| export default { created() { this.fetchListData() }, watch: { searchValue() { this.fetchListData() } } }
|
good
1 2 3 4 5 6 7 8
| export default { watch: { searchValue: { handler: 'fetchListData', immediate: true } } }
|
优化组件引入的代码
在开发大型应用时,很多页面用到很多公共UI库的组件,按照Vue原本的写法,每种组件都要在每个页面引用一次,真是好累,如何省事偷懒呢?
bad
1 2 3 4 5 6 7 8 9 10 11
| import BaseButton from '../components/baseButton' import BaseInput from '../components/baseInput' import BaseCard from '../components/baseCard' export default { components: { BaseButton, BaseInpur, BaseCard } }
|
good
在公共组件components
文件夹下新建一个allImport.js
文件,本质是使用webpack的一个require.context()
方法来实现代码层级的动态引入,下面注意代码的实现,重点看注释。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import Vue from 'vue' function capitalizeFirstLetter(string) { return string.charAt(0).toUpperCase() + string.slice(1) } function handleFileName(string) { return string.replace(/^\.\//, '').replace(/\.\w+&/, '') } const requireComponent = require.context('.', false, /\.vue$/) requireComponent.keys().forEach(fileName => { const componentConfig = requireComponent(fileName) const componentName = capitalizeFirstLetter(handleFileName(fileName)) Vue.component(componentName, componentConfig.default || componentConfig) })
|
在main.js
中引入这个脚本即可 import 'components/global.js'
PS: 如果是用extend
这个方法来继承Vue实例实现节省代码,每个页面的import
还是不能省略
父子组件通信的优化写法
我们Vue组件写多了就会感觉到,父组件上面要写上监听子组件emit来的事件,同时每一个属性都得绑定了传过去,无论自定义的还是click/placeholder之类原生的。这个优化方法是把一些原生得属性和事件进行简写,尤其对组件库之类改造原有HTML元素有奇效。
bad
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <template> <div> <BaseInput :value="value" label="密码" placeholder="place input your password" @input="handleInput" @focus="handleFocus"> </BaseInput> </div> </template> <template> <label> {{lable}} <input :value="value" :placeholder="placeholder" @focus="$emit('focus', $event)" @input="$emit('input', $event.target.value)" > </label> </template>
|
- 优化点1:Dom的原生属性可以通过
$attrs
这个API
来实现非声明式传递。$attr
包含的是父作用域中不作为prop
被识别的(class
/style
除外)特性。
- 优化点2:Dom的原生事件可以通过
$listeners
实现非声明式传入,$listeners
包含了父作用域中不含.native
修饰器的事件监听(v-on:),如果是更多层级,可以通过v-on="$listeners"
一层层传递到组件内部。
- 注意:默认父作用与不被认为是
props
的属性将会回退到子组件的根元素上,也就是例子中的label
上,需在当前子组件的Vue内部设置inheritAttrs: false
good
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <template> <input :value="value" v-bind="$attrs" v-on="selfListeners"> </template> <script> export default { inheritAttrs: false, computed: { selfListeners() { return { ...this.$listeners, input: event => this.$emit('input', event.target.value) } } } } </script>
|
使用Render函数来组织渲染逻辑
教程中的例子是关于省略掉根元素来考虑的,其实这种写法应该是更贴近React
的思路,所以学会用js
来生成HTML
吧
函数式组件的render
的写法
1 2 3 4 5 6 7 8 9 10 11 12 13
| Vue.component('my-router', { functional: true, render(context) { return context.props.routes.map(route => <li key={route.name}> <router-link to={route}>{route.title}</router-link> </li> ) } })
|