likes
comments
collection
share

2022你该掌握的Vue知识点

作者站长头像
站长
· 阅读数 9

作为前端开发者,我们最熟悉的技术栈莫过于Vue、React, 那么接下来我将分享一些自己对Vue使用的一些笔记

ref应用组件和DOM

ref使用在DOM上
<template>
    <div ref="refDom"></div>
</template>

mounted() {
  console.log(this.$refs.refDom);  // <div></div>
}

2022你该掌握的Vue知识点 ref使用在DOM上,我们可以拿到整个DOM元素

ref使用在组件上
<template>
    <div>
        <tree ref="refCompoent"></tree>
    </div>
</template>

mounted() {
  console.log(this.$refs.refCompoent);
}

2022你该掌握的Vue知识点

2022你该掌握的Vue知识点 ref使用在组件上,可以拿到整个组件的实例

v-if和v-show

<template>
    <div>
        <div class ="show_dom" ref="refDom" v-show="showMe"></div>
    </div>
</template>

data () {
    return {
       showMe: false
    }
}

2022你该掌握的Vue知识点 通过 Elements 我们可以看到使用v-show的时候,DOM中是有存在,但是未被渲染,使用display:none; 将其隐藏了,这里补充一下display:none; opacity:0; visibilty:visible; 的区别:

  • display:none会让元素完全从渲染树中消失,渲染时不再占据任何空间,不能点击

  • visibilty:hidden不会让元素从渲染树上消失,渲染元素继续占据空间,只是内容不可见,不能点击

  • opacity:0不会让元素在渲染树中消失,渲染元素继续占据空间,只是内容不可见,可以点击继承

  • display:none和opacity:0; 是非继承属性,子孙节点消失由于子元素从渲染树消失造成,通过修改子孙节点属性无法显示

  • visibilty:hidden; 是继承属性,子孙节点消失由于继承了hidden,通过设置

  • visibilty:visible; 可以让子元素节点显示继承

  • display:none: 修改元素会造成文档重排,读屏器不会读取display:none元素内容,性能消耗较大

  • visibilty:hidden: 修改元素只会造成本元素的重绘,读屏器读取visibilty:hidden元素内容,性能优化较少
  • opacity:0: 修改元素会造成重绘,性能消耗较少
<template>
    <div>
        <div class ="show_dom" ref="refDom" v-if="showMe"></div>
    </div>
</template>

2022你该掌握的Vue知识点

需要注意到的是使用了v-if是不会有DOM在DOM树中的,会被注释掉,如果我们需要频繁的切换DOM,使用v-show更加合适,反之v-if

父组件和子组件生命周期钩子函数执行顺序

可以分为四个部分,分别是:

首次加载过程

beroreCreate => 父created =>父beforeMount

beroreCreate => 子 created => 子beforeMount => 子mounted =>父mounted

更新过程
子组件更新过程

beforeUpdate => 子beforeUpdate => 子updated => 父 updated

父组件更新过程

beforeUpdate => 父updated

销毁过程

beforeDestroy => 子beforeDestroy => 子 destroyed => 父 destroyed

初次渲染过程

  1. 解析模板为render函数 (或在开发环境已完成, vue-loader
  2. 触发响应式,监听data属性 getter setter
  3. 执行render函数,生成vnode, patch(elem, vnode)

2022你该掌握的Vue知识点

computed和watch的区别

  • computed

  • 计算属性,依赖其他属性,当其他属性改变的时候下一次获取computed值时也会改变,computed的值会有缓存

  • watch

  • 类似于数据改变后的回调

  • 如果想深度监听的话,后面加一个deep:true

  • 如果想监听完立马运行的话,后面加一个immediate:true

  • 如果想在生命周期中使用watch

    this.$watch('someObject', callback, {
       deep: true,
       immediate: true
    }
    

nextTick

  • nextTick:在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后立即使用这个方法,获取更新后的 DOM
  • 如果想要在Vue生命周期函数中的created()操作DOM可以使用Vue.nextTick()回调函数
  • 在数据改变后要执行的操作,而这个操作需要等数据改变后而改变DOM结构的时候才进行操作,需要用到nextTick

在下次 DOM 更新循环结束之后执行延迟回调,nextTick主要使用了宏任务和微任务,根据执行环境分别尝试采用

  • Promise
  • MutationObserver
  • setImmediate
  • 如果以上都不行则采用setTimeout

定义一个异步方法,多次调用nextTick会将方法存入队列中,通过这个异步方法清空当前队列

Vue是异步渲染 在data改变之后 DOM不会立刻渲染

$nextTick 会在DOM渲染之后被捕获 以获取最新的DOM节点

路由模式

Vue 路由有三种模式:hash、history 和 abstract

hash: 使用 URL hash 值来作路由,支持所有浏览器,hash不会调用接口

hash模式

hash其实就是指url后面的#号以及后面的字符,这里的#和css里的#是一个道理, hash也称作锚点,本身是用来做页面定位的,它是可以使对应的id元素显示在可视区域内的, 由于hash值变化不会导致浏览器向服务器发出请求,而且hash改变会触发hashchange事件, 同时浏览器的进后退也能对其进行控制,所以在html5的history出现之前,基本都是在使用hash来实现前端路由的

hash的特点在于:hash出现url中,但不会被包含在HTTP请求中,对后端完全没有任何影响,因此改变hash不会重新加载页面

window.addEventListener('hashchange',function(){
  //监听hash变化,点击浏览器的前进后退时会触发
})
history模式

HTML5 History 中新增的 pushState()replaceState() 方法(需要特定浏览器支持) 这两个方法应用于浏览器的历史记录栈,在当前已有的 backforwardgo 的基础之上,它们提供了对历史记录进行修改的功能, 只是当它们执行修改时,虽然改变了当前的 URL,但浏览器不会立即向后端发送请求, 因此可以说,hash 模式和 history 模式都属于浏览器自身的特性

window.addEventListener('popstate',function(){ 
//监听history变化,点击浏览器的前进后退会触发 
})
hash和history的区别

hash模式下,仅hash符号之前的内容会被包含在请求中,如 www.juejin.cn 因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回404错误

history模式下,前端的url必须和实际后端发起请求的url一致,如www.juejin.cn/editor/ 如果后端缺少对/editor/ 的路由处理,将返回404错误,此时需要在后端作出相应的调整

router.query和router.params的区别

类型于get(query) 和 post(params)

query方式传参和接收参数

  传参:

this.$router.push({
       path:"/xxx"
       query:{ id:id}
   })

接收参数:this.$router.query.id

params方法传参合接收参数

 传参:

    this.$router.push({
       path:"./xxx"
       params:{id:id}
    })

 接收参数:this.$router.params.id

  • params传参,push里面只能是 name:'xxxx',不能是path:'/xxx',因为params只能用name来引入路由,如果写成了path,接收参数页面会是undefined

  • 另外, 二者还有区别,通俗的来讲 query相当于get请求,页面跳转的时候,可以在地址栏看到请求参数,而params相当于post请求,参数不会在地址栏中显示

  • 若刷新当前页面params对象里面数据会消失,而query不会

  • 传参是this.$router,接收参数是this.$route

$route$router的区别

  • $route是路由信息对象,包括path,params,hash,query,fullPath,matched,name等路由信息参数。
  • 而$router是路由实例对象包括了路由的跳转方法,钩子函数等。

2022你该掌握的Vue知识点

虚拟DOM

2022你该掌握的Vue知识点 简洁强大的vdom库

Vue参考它实现的vdomdiff 推荐学习方式

Mixin

  • 数据对象内

mixin的数据对象和组件的数据发生冲突时以组件数据优先

  • 钩子函数 同名钩子函数将会混合为一个数组,都将被调用到,但是混入对象的钩子将在组件自身钩子之前调用

  • 值为对象的选项

值为对象的选项,例如 methods, componentsdirectives,将被混合为同一个对象,两个对象键名冲突时,取组件对象的键值对

vue中组件通信的方式

  • 父组件向子组件传递 :data="tranData",子组件通过props接收
  • $ref获取子组件实例
  • 子组件使用$emit对父组件进行传值
  • 父组件通过$chidren获取子组件实例 子组件通过$parent获取父组件实例
  • vuex状态管理
  • 路由传值
  • 通过eventBus兄弟组件传值
  • $attrs包含了父作用域中不被 prop 所识别 (且获取) 的特性绑定 (class 和 style 除外)/$listeners包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器,它可以通过 v-on="$listeners" 传入内部组件
  • provideinject
  • localStorage、sessionStorage

组件中data为什么必须是一个函数

复用组件的时候,都会返回一份新的data,相当于每个组件实例都有自己私有的数据空间,不会共享同一个data对象

Proxy与Object.defineProperty的优劣对比

Proxy的优势如下:

  • Proxy可以直接监听对象而非属性
  • Proxy可以直接监听数组的变化
  • Proxy有多达13种拦截方法,不限于apply、ownKeys、deleteProperty、has等等是Object.defineProperty不具备的
  • Proxy返回的是一个新对象,我们可以只操作新的对象达到目的,而Object.defineProperty只能遍历对象属性直接修改
  • Proxy作为新标准将受到浏览器厂商重点持续的性能优化,也就是传说中的新标准的性能红利

Object.defineProperty的优势如下:

  • 兼容性好,支持IE9

父组件监听子组件的生命周期

// Parent.vue 
<Child @hook:mounted="doSomething"></Child>

doSomething() { 
    console.log('父组件监听到 mounted 钩子函数 ...')
}


// Child.vue 
mounted() { 
   console.log('子组件触发 mounted 钩子函数 ...');
}

// 以上输出顺序为: 
// 子组件触发 mounted 钩子函数 ... 
// 父组件监听到 mounted 钩子函数 ...

当然 @hook 方法不仅仅是可以监听 mounted,其它的生命周期事件,例如:created, updated 等都可以监听

keep-alive

keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,避免重新渲染 ,其有以下特性:

  • 一般结合路由和动态组件一起使用,用于缓存组件;
  • 提供 includeexclude 属性,两者都支持字符串或正则表达式, include 表示只有名称匹配的组件会被缓存,exclude 表示任何名称匹配的组件都不会被缓存 ,其中 exclude 的优先级比 include 高
  • 对应两个钩子函数 activateddeactivated ,当组件被激活时,触发钩子函数 activated,当组件被移除时,触发钩子函数 deactivated

生命周期内调用异步请求

可以在钩子函数 createdbeforeMountmounted 中进行调用,因为在这三个钩子函数中,data 已经创建,可以将服务端返回的数据进行赋值,推荐在 created 钩子函数中调用异步请求,因为在 created 钩子函数中调用异步请求有以下优点:

  • 能更快获取到服务端数据,减少页面 loading 时间
  • ssr 不支持 beforeMountmounted 钩子函数,所以放在 created 中有助于一致性

监听数组变化

Object.defineProperty是不能监听数组变化的

重写定义原型, 重写pushpop等方法,实现监听

Proxy可以原生支持监听数组变化

vm.$set

解决vue视图不及时更新问题

this.$set( target, key, value )

target:要更改的数据源(可以是对象或者数组)

key:要更改的具体数据

value :重新赋的值

路由守卫

全局守卫:beforeEach(to,from,next)和afterEach(to,from)

路由独享守卫:beforeEnter

组件内的守卫:路由进入/更新/离开之前 beforeRouterEnter/update/leave vue的路由守卫钩子,vue的路由方式,vue的路由传参

路由守卫钩子:在路由进入或者离开的执行的方法

beforeEach(to,from,next) :路由的前置守卫,进入该路由执行的方法

参数中包含了路由的一些信息

to: 进入到哪个路由去

from:从哪个路由离开

next:函数,决定是否展示你要看到的路由页面

next(); 顺利进入

next(false); 阻止进入

next('/login'); 进入到其他路由

全局路由守卫的简单用法:

router.beforeEach((to,from,next)=>{
    if(to.path == '/login' || to.path == '/register'){
      next()
    }else{
      alert('您还没有登录,请先登录')
      next('/login')
    }
})

局部路由守卫:

beforeRouteEnter (to, from, next) {
    // 这里还无法访问到组件实例,this === undefined
    next( vm => {
    // 通过 `vm` 访问组件实例
    })
}

afterEach(to,from) : 路由的后置守卫,离开该路由执行的方法

vue路由的常用方式
  1. 动态路由:路由后面:跟不同的参数,跳转同一个组件

  2. 嵌套路由:一级路由后面跟children子路由

  3. 编程式路由:使用js在router中push新的path

  4. 路由传参

  5. 使用动态路由的特点:后跟参数的方式传递

定义:

{ path: '/user/:id', component: User }

使用:

this.$router.push({

 path: `/user/${id}`,

})

获取:this.$route.params.id

  1. 通过路由属性中的name来确定匹配的路由,通过params来传递参数。

定义:

{
    path: '/describe',
    name: 'Describe',
    component: Describe
}

使用:

this.$router.push({
    name: 'Describe',
    params: {
    id: id
    }
})

获取:this.$route.params.id

  1. 使用path来匹配路由,然后通过query来传递参数,推荐使用

定义:

{
    path: '/describe',
    name: 'Describe',
    component: Describe
}

使用:

this.$router.push({
    path: '/describe',
    query: {
    id: id
    }
})

获取:this.$route.query.id

  1. router-link 中声明params传递
<router-link :to="{name:'Reg',params:{num:888}}">显示注册页面</router-link>

如何在刷新的情况下结合vuex保存登录状态

cookie

localstorage

对用户登录的token记录在本地,在进入登录页面是像后端发送请求验证token的有效性,合法的token怎进入相关页面,否则进入登录页面

  1. 在vuex中记录userMessage, token

  2. 在登录时向storage中记录user, token, 登录标识符,同时向vuex派发action,改变vuex相关字段值

  3. 在刷新页面的时候vuex中的state会被初始化,所以需要判断本地storage中的数据,然后在通过vuex派发事件,改变相关状态 vue路由钩子是在路由跳转过程中拦截当前路由和要跳转的路由的信息

  第一种:全局路由钩子

beforeEach(to,from,next) {  
   //...
}

  第二种:路由独享的钩子

beforeEnter(to,from,next) {
    // ...
}

   第三种:组件内的钩子

beforeRouteEnter(to,from,next) {
   //...
}
beforeRouteUpdate(to,from,next) {
  //...
}
beforeRouteLeave(to,from,next) {
// ...
}

内部指令

  • v-model:用于在表单上创建双向数据绑定。
  • v-text:等同于JS的text属性
  • v-html:等同于JS的innerHtml属性
  • v-show:通过样式display改变显隐
  • v-if:根据表达式的值的真假条件来渲染元素
  • v-else:v-else是搭配v-if使用的,它必须紧跟在v-if或者v-else-if后面,否则不起作用
  • v-else-if:充当v-if的else-if块,可以链式的使用多次。可以更加方便的实现switch语句
  • v-slot:插槽
  • v-once:只会渲染一次
  • v-pre:用来跳过这个元素和它的子元素编译过程
  • v-cloak:用来保持在元素上直到关联实例结束时进行编译
  • v-for:用v-for指令根据遍历数组来进行渲染

注意:当v-for和v-if同处于一个节点时,v-for的优先级比v-if更高。这意味着v-if将运行在每个v-for循环中

  • v-on:绑定事件,缩写@
  • v-bind:用来动态的绑定一个或者多个特性绑定变量,缩写:

 <div :class="{'is-active':isActive, 'text-danger':hasError}"></div>
 <p :class="[{'is-active':activeClass},errorClass]">tg</p>

修饰符

.lazy

<input v-model.lazy="msg">

.number

<input v-model.number="msg">

.trim

<input v-model.trim="msg">

事件修饰符

  • .native:绑定事件在自定义组件上时,能执行
  • .stop 阻止事件继续传播
  • .prevent 事件不再重载页面
  • .capture 使用事件捕获模式,即元素自身触发的事件先在此处处理,然后才交由内部元素进行处理
  • .self 只当在 event.target 是当前元素自身时触发处理函数
  • .once 事件将只会触发一次
  • .passive 告诉浏览器你不想阻止事件的默认行为

使用修饰符时,序很重要;相应的代码会以同样的顺序产生 因此,用v-on:click.prevent.self阻止所有的点击,而 v-on:click.self.prevent 只会阻止对元素自身的点击

强制渲染

vue页面中通过v-for进行数据渲染,如果层级过多,有时候数据发生改变但是视图未发生更新,render函数没有自动更新,使用this.$forceUpdate()是重新渲染虚拟DOM,不是重新加载组件,因为this.$forceUpdate执行后,只会触发beforeUpdateupdated这两个钩子函数,并不会触发其他的钩子函数,它仅仅影响实例本身和插入插槽内容的子组件,并不是所有子组件,这个时候便可以通过this.$forceUpdate()进行手动刷新

this.$forceUpdate()

未完待更新...