# 如何写出比别人更优秀的Vue?
# watch的灵活使用
在watch中,可以直接使用函数的字面量名称;其次,声明immediate:true表示创建组件时立马执行一次。
watch: {
inputValue: {
handler: 'getSearchList',
immediate: true
}
}
1
2
3
4
5
6
2
3
4
5
6
# 自动注册全局组件
我们可以使用require.context() (opens new window) 方法来创建自己的(模块)上下文,从而实现自动动态require组件
require.context 说明
require.context(
directory: String, // 搜索的目录
includeSubdirs: Boolean /* 可选的,默认值是 true */, // 是否搜索子目录
filter: RegExp /* 可选的,默认值是 /^\.\/.*$/,所有文件 */, // 匹配的目标文件格式
mode: String /* 可选的, 'sync' | 'eager' | 'weak' | 'lazy' | 'lazy-once',默认值是 'sync' */ // 同步还是异步
)
目录结构
|--src
|---|commponets
|-----|common
在common文件夹下新建index.js,并写入下面内容
import Vue from 'vue'
const path =require('path')
const context = require.context('./',true, /\.vue$/)
context.keys().forEach(item => {
const filename = path.basename(item)
const componentName = filename.replace(/\..+/,'')
const componentConfig = context(item)
Vue.component(componentName, componentConfig.default || componentConfig)
})
在 main.js 写入
import './commponets/common'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 高阶组件
$attrs
$listeners
.sync
$props
1
2
3
4
2
3
4
# 动态指令参数
<div v-bind:[attr]="attributeName"></div>
//简写
<div :[attr]="attributeName"></div>
<button v-on:[eventName]="handler"></button>
//简写
<button @[eventName]="handler"></button>
1
2
3
4
5
6
7
2
3
4
5
6
7
# @hook那些事
this.$once('hook:beforeDestroy', () => clearInterval(timer);)
<v-chart
@hook:mounted="loading = false"
@hook:beforeUpdated="loading = true"
@hook:updated="loading = false"
:data="data"
/>
1
2
3
4
5
6
7
2
3
4
5
6
7
# Vue.observable( object )
这是一个 Vue2.6 中新增的 API,用来让一个对象可以响应。
import Vue from 'vue'
export const state = Vue.observable({
count: 0,
})
export const mutations = {
increment() {
state.count++
}
decrement() {
state.count--
}
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# jsx模板组件
Vue.component('child', {
props: {
status: {
type: Number,
required: true
}
},
render(createElement) {
const innerHTML = ['未开始', '进行中', '可领取', '已领取'][this.status]
return createElement('button', {
class: {
active: this.status
},
attrs: {
id: 'btn'
},
domProps: {
innerHTML
},
on: {
click: () => console.log(this.status)
}
})
}
})
var app = new Vue({
el: '#app',
data: {
status: 0
}
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 动态组件
<component v-for="(item,index) in componentList" :key="index" :is="item"></component>
1
# provide/inject组合拳
provide/inject 组合以允许一个祖先组件向其所有子孙后代注入一个依赖,可以注入属性和方法,从而实现跨级父子组件通信。在开发高阶组件和组件库的时候尤其好用
// 父组件 index.vue
data() {
return {
title: 'bubuzou.com',
}
}
provide() {
return {
detail: {
title: this.title,
change: (val) => {
console.log( val )
}
}
}
}
// 孙子组件 detail.vue
inject: ['detail'],
mounted() {
console.log(this.detail.title) // bubuzou.com
this.detail.title = 'hello world' // 虽然值被改变了,但是父组件中 title 并不会重新渲染
this.detail.change('改变后的值') // 执行这句后将打印:改变后的值
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# EventBus
任意组件间通信
// main.js
Vue.prototype.$eventBus = new Vue()
// 需要订阅的地方
this.$eventBus.$on('update', val => {})
// 需要发布信息的地方
this.$eventBus.$emit('update', '更新信息')
// 需要移除订阅
this.$eventBus.$off('update', {})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 自定义指令
根据权限显示按钮
// auth.js
const AUTH_LIST = ['admin']
function checkAuth(auths) {
return AUTH_LIST.some(item => auths.includes(item))
}
function install(Vue, options = {}) {
Vue.directive('auth', {
inserted(el, binding) {
if (!checkAuth(binding.value)) {
el.parentNode && el.parentNode.removeChild(el)
}
}
})
}
export default { install }
// main.js
import Auth from './utils/auth'
Vue.use(Auth)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 使用渲染函数
<authority :auth="['admin']">
<button>提交</button>
</authority>
// authority.js
<script>
const AUTH_LIST = ['admin', 'user', 'org']
function checkAuth(auths) {
return AUTH_LIST.some(item => auths.includes(item))
}
export default {
functional: true,
props: {
auth: {
type: Array,
required: true
}
},
render(h, context) {
const { props, scopedSlots} = context
return checkAuth(props.auth) ? scopedSlots.default() : null
}
}
// main.js
import Authority from './components/authority'
Vue.component('authority', Authority)
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 自定义插件
开发 Vue 的插件应该暴露一个 install 方法。这个方法的第一个参数是 Vue 构造器,第二个参数是一个可选的选项对象。 可以通过如下4种方式来自定义插件:
MyPlugin.install = function (Vue, options) {
// 1. 添加全局方法或 property
Vue.myGlobalMethod = function () {
// 逻辑...
}
// 2. 添加全局资源
Vue.directive('my-directive', {
bind (el, binding, vnode, oldVnode) {
// 逻辑...
}
...
})
// 3. 注入组件选项
Vue.mixin({
created: function () {
// 逻辑...
}
...
})
// 4. 添加实例方法
Vue.prototype.$myMethod = function (methodOptions) {
// 逻辑...
}
}
// main.js
import MyPlugin from './plugins/plugins.js'
Vue.use(MyPlugin)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 函数式组件实现零时变量
我们在使用插槽的时候,知道有一个叫做插槽 prop 的知识,今天我们用他和函数式组件结合在一块,实现一个零时变量的组件:
// tempvar.vue
<script>
export default {
functional: true,
render(h, context) {
const { props, scopedSlots} = context
return scopedSlots.default && scopedSlots.default(props || {})
}
}
</script>
<template>
<tempvar
:var1="`hello ${user.name}`"
:var2="user.age ? user.age : '18'">
<template v-slot="{var1, var2}">
姓名: {{ var1 }}
年龄:{{ var2 }}
</template>
</tempvar>
</template>
<script>
import tempvar from '@/components/tempvar.vue'
export default {
data() {
return {
obj: {
name: 'bubuzou',
age: 12,
},
}
}
components: {
tempvar
}
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# 路由参数解耦
const router = [{
path: '/home/:type/:id',
name: 'Home',
component: Home,
props: (route) => ({
type: route.params.type,
id: route.params.id,
sex: route.query.sex,
})
}]
Home 组件加上
export default {
name: 'Home',
props: ['type', 'id', 'sex']
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
← Vue 服务端渲染首屏优化 模块热更新 →