Vue.js 小技巧
- watch
组件创建的时候,我们需要获取列表、监听input框。每次发生变化的时候重新获取筛选后的列表
watch:{
//searchInputValue为 监听input框change事件
searchInputValue:{
handler:'featchPostList',
immediate:true //immediate表示创建组件的时候立马执行一次
}
}
- 组件注册(一劳永逸)
基础UI组件写多的时候,需要使用都需要先import,然后声明components
优化方法:利用webpack, 使用 require.context() 方法创建自己的(模块)上下文,从而实现自动动态require组件
参数(搜索的文件目录, 是否还应该搜索其它的子目录, 匹配文件的正则表达式)
实例:在components文件下新建global.js 文件,借助webpack动态将需要的基础组件统统打包
import Vue from "vue"
function capitalizeFirstLetter(string){
return string.chatAt(0).toUpperCase+string.slice(1)
}
//找到components文件夹下以 .vue结尾的文件
const requireComponent = requeire.context('.',false,/\.vue$/)
requireComponent.keys().forEach(fileName=>{
const componentConfig = requireComponent(fileName);
//filename: ./base.vue 去掉头尾,保留文件名
const componentName = capitalizeFirstLetter(fileName.replace(/^\.\//, '').replace(/\.\w+$/, ''))
Vue.component(componentName, componentConfig.default || componentConfig)
})
后面只需要在main.js中引入global.js文件,即可随时随地使用这些基础组件了
- router key
路由跳转的时候,有时候会是 page/a 跳转到page/b,但是跳转后数据没有更新。
原因: vue-router 判断同一个组件情况下,可复用,故create()中写的方法不执行
一般情况下,监听 $route 变化可解决
watch:{
'$route':{
handler:'resetData',
immediate:true
}
}
优雅的解决办法:给每个router-view添加一个唯一的key属性,即便公用组件,url变化了就一定会重新创建(虽然耗了一丢丢性能)
<router-view :key="$route.fullpath"></router-view>
- render函数
vue要求每一个组件都只能有一个根元素,当你有多个根元素时,vue就会给你报错
解决办法:使用render() 创建HTML 而不是使用template。
functional:true,
render(h,{props})=>{
return props.routes.map(route=>{
<li key={route.name}>
<router-link to={route}>
{route.title}
</router-link>
</li>
})
}
- 高阶组件
当我们写组件的时候,通常我们都需要从父组件传递一系列的props到子组件,同时父组件监听子组件emit过来的一系列事件
//父组件
<BaseInput
:value="value"
label="密码"
placeholder="请填写密码"
@input="handleInput"
@focus="handleFocus>
</BaseInput>
//子组件
<template>
<label>
{{ label }}
<input
:value="value"
:placeholder="placeholder"
@focus=$emit('focus', $event)"
@input="$emit('input', $event.target.value)"
>
</label>
</template>
- 类似placeholer这种dom原生的property我们其实完全可以直接从父传到子,无需声明
<input
:value="value"
v-bind="$attrs"
@input="$emit('input', $event.target.value)"
>
- attrs包含了父作用域中不作为 prop 被识别 (且获取) 的特性绑定 (class 和 style 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定,并且可以通过 v-bind="$attrs" 传入内部组件——在创建更高层次的组件时非常有用
- 注意到子组件的@focus=$emit(‘focus’, $event)"其实什么都没做,只是把event传回给父组件而已,没必要显式地申明
<input
:value="value"
v-bind="$attrs"
v-on="listeners"
>
computed: {
listeners() {
return {
...this.$listeners,
input: event =>
this.$emit('input', event.target.value)
}
}
}
- listeners包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件——在创建更高层次的组件时非常有用
需要注意的是,由于我们input并不是BaseInput这个组件的根节点,而默认情况下父作用域的不被认作 props 的特性绑定将会“回退”且作为普通的 HTML 特性应用在子组件的根元素上。所以我们需要设置inheritAttrs:false,这些默认行为将会被去掉, 以上两点的优化才能成功