立帖为证,今后对于知识的掌握不能在含含糊糊,要做到精准的了解知识点,做到说出来既准确! 加油!
2021 死磕Vue 从我做起
1.导航守卫
1.导航被触发。
2.在失活的组件里调用 beforeRouteLeave 守卫。
3.调用全局的 beforeEach 守卫。
4.在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
5.在路由配置里调用 beforeEnter。
6.解析异步路由组件。
7.在被激活的组件里调用 beforeRouteEnter。
8.调用全局的 beforeResolve 守卫 (2.5+)。
9.导航被确认。
10 调用全局的 afterEach 钩子。
11.触发 DOM 更新。
12.调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。
2.Mixins 混入
有些组件有些重复的 js 逻辑,如校验手机验证码,解析时间等,mixins 就可以实现这种混入 mixins 值是一个数组
简单的说就是当多个组件共用了一些数据\方法等的时候, 可以将这些数据和方法进行抽离,使用mixins的方式进行引入
mixins/show.js
export const showMixin = {
data(){
return {
shwoTag: true
}
},
methods: {
tagShow(){
this.shwoTag = !this.shwoTag
}
},
}
Home.vue
<template>
<div class="home">
<img alt="Vue logo" v-show="shwoTag" src="../assets/logo.png">
<div @click="tagShow">显示 隐藏</div>
</div>
</template>
<script>
import { showMixin } from '../mixins'
export default {
name: 'Home',
mixins: [showMixin]
}
</script>
3.$nextTick
总结: 会在DOM异步渲染完成以后执行
<template>
<div class="about">
<div ref="chrenDom">
<div v-for="item in arr" :key="item">{{item}}</div>
</div>
<h1 @click="add">增加</h1>
</div>
</template>
<script>
export default {
data(){
return {
arr: [1,2,3,4,5]
}
},
methods:{
add(){
this.arr.push(Math.random())
let HM = this.$refs.chrenDom.children.length
console.log(this.arr.length,HM) // 6 5
}
}
}
</script>
在上面这段代码里, 我么为 arr 增加一个元素后, 分别去获取 ref="chrenDom" 的子元素个数和 arr 数组的长度时, 我们惊奇的发现其数量不同, 子元素个数为5, 而 数组长度缺为6
<script>
export default {
data(){
return {
arr: [1,2,3,4,5]
}
},
methods:{
add(){
this.arr.push(Math.random())
this.$nextTick(()=>{
let HM = this.$refs.chrenDom.children.length
console.log(this.arr.length,HM) // 6 6
})
}
}
}
</script>
4.render函数的使用
<script>
export default {
data(){
return {
people: [
'A',
"B",
"C"
]
}
},
render(createElement){
return createElement(
'h1',
{},
this.people.map(name =>{
return createElement('div',{
attrs: {
class: 'test'
},
on:{
click: ()=>{
console.log('点击了')
}
}
},`${name}`)
})
)
}
}
</script>
5.组件渲染流程
render -> newVnode(虚拟DOM) -> patch(vnode, newVnode) diff算法 -> 更新视图
6.vue修改原生数组的方法
const arrayMethods = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'];
const arrayAugmentations = [];
arrayMethods.forEach((method)=> {
// 这里是原生Array的原型方法
let original = Array.prototype[method];
// 将push, pop等封装好的方法定义在对象arrayAugmentations的属性上
// 注意:是属性而非原型属性
arrayAugmentations[method] = function () {
console.log('我被改变啦!');
// 调用对应的原生方法并返回结果
return original.apply(this, arguments);
};
});
let list = ['a', 'b', 'c'];
// 将我们要监听的数组的原型指针指向上面定义的空数组对象
// 别忘了这个空数组的属性上定义了我们封装好的push等方法
list.__proto__ = arrayAugmentations;
list.push('d'); // 我被改变啦! 4
7.History实现原理
const tags = document.getElementById('tags')
window.addEventListener('DOMContentLoaded', ()=>{
console.log(location.pathname)
})
// 点击 改变 路由地址
tags.addEventListener('click', ()=>{
const state = { name: 'home' }
history.pushState(state, '', 'home') // 跳转地址
console.log('路由地址切换了')
})
// 通过 前进 后退 改变的路由 的信息监听
window.onpopstate = (e)=>{
console.log(e.state, location.pathname)
// 分别打印 state的值 和 路由地址
}
8.hash模式
const tags = document.getElementById('tags')
// 首次加载时的hash
window.addEventListener('DOMContentLoaded', ()=>{
console.log('hash', window.location.hash)
})
// 点击 改变 路由地址
tags.addEventListener('click', ()=>{
location.href = '#/user'
})
// 监听地址栏的hash变化
window.onhashchange = function(e){
console.log('oldUrl', e.oldURL)
console.log('newUrl', e.newURL)
console.log('hash', window.location.hash)
}
9.动态组件使用
<component :is="组件名称"></component>
10.指令在按钮级权限中的应用
store.js
state:{
AuthButton: {
add: true,
delete: false
}
}
Home.vue
<template>
<div class="about">
<div v-has="'add'">增加</div>
<div v-has="'delete'">删除</div>
</div>
</template>
<script>
import has from '../directives'
export default {
directives:{
has
}
}
</script>
directives.js
export default {
inserted(el, bindings, vnode){
console.log('DOM元素插入')
let stateValue = bindings.value // 获取指令值
// 获取 全局状态(Vuex)中 该用户是否拥有这个按钮的权限(true, false)
let boolean = vnode.context.$store.state.AuthButton[stateValue]
// 如果没有这个按钮的权限 就获取他的父级后 删除该元素
!boolean && el.parentNode.removeChild(el)
}
}
自定义指令的参数
bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。(拿不到父节点)
inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新
componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
unbind:只调用一次,指令与元素解绑时调用。