Vue知识点

1.Vue渲染页面之前数据还没获取到,可以重新渲染

场景:
某个数据报错undefined,但是数据渲染出来了。
原因:
页面渲染的时候数据还没获取到,所以控制台先报错了,等到数据获取到之后页面就会重新渲染出快来。特别是某个数据初始化是一个空对象,但是获取到数据之后有很多子属性的时候,子属性来不及获取就会先报错后渲染。
解决方案:
方式一:this.$forceUpdate();
方式二:v-if,数据加载完成之后再渲染

2.插槽Slot

具名插槽动态命名

<TagTemplateDetail>
<template v-slot: [dynamicSlotName] >
content
</template>
</TagTemplateDetail>

<slot :name=" dynamicSlotName "></slot>

传参

<TagTemplateDetail>
<template v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</template>
</TagTemplateDetail>
<slot name=" default " v-bind:user=”user”></slot>

只有default的情况下传参v-slot:default=”pamaName”可以写成v-slot=”pamaName”

传参的解构

<current-user v-slot="{ user }">
  {{ user.firstName }}
</current-user>

传参的重命名

<current-user v-slot="{ user: person }">
  {{ person.firstName }}
</current-user>

传参的默认内容

<current-user v-slot="{ user = { firstName: 'Guest' } }">
  {{ user.firstName }}
</current-user>

缩写,缩写必须具名,#代替v-slot

<current-user #default="{ user }">
  {{ user.firstName }}
</current-user>

3.等待Vuex数据获取完之后再渲染页面数据

场景:
应用进入时就会从Vuex中去取数据,但是如果此时Vuex还没接收到后端获取的数据,页面就会显示错误数据或者报错等信息
解决方案:
方案1:通过v-if判断数据是否获取完成,完成之后再显示出来
方案2:调用Vuex中的action返回Promise同步获取数据,然后通过then函数去获取显示数据

4.v-html中无法编译vue语言

场景:
v-html中嵌入了vue语言,比如@click或者{{插值法}}等没有用,因为v-html中插入html时,vue已经将页面编译成最基础的html语言了,不认识vue语言,且如果你使用onclick代替@click很可能违反CSP安全策略。
解决方案:
方案1:通过templateslot解决,使用vue语言的写法完成对页面动态html的插入
方案2:先对数据进行处理,然后直接将需要的html写在页面中,通过v-if去判断显示哪种样式的标签
方案3:直接通过render函数渲染需要的html,见下图:

5.Vuex刷新之后数据丢失

首先提出这个问题表示对Vuex不了解,Vuex本身就不是用来本地化永久存储数据的,它只是一个响应式的状态管理器。下面给出了一个解决方案,但是个人觉得完全没必要,如果真的要永久存储数据,可以直接使用localStorage、Session或者Cookie来存储,没必要传来传去,因为下面的方法本身就是一直在刷新localStorage
下面是两者的结合使用:
1、在vuex获取信息时,同时把这个信息存入localStorage
2、我们定义一个mutation方法,再次把数据从localStorage传给state
3、在computed属性获取数据时,只要判断数据为空就调用第2步的方法,然后我们把这个state return给那个响应属性就好了
4、statelocalStorage中数据互传,是因为state的值刷新后会没了,而localStorage的值不能响应式地变化(Vue 仅可以对其管理的数据做响应式处理,可以理解为 data 中的数据,localStorage 并不在 Vue 的管理下,自然不会有响应特性)

6.Vue使用防抖节流,闭包的经典应用

节流(throttle
所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数。
节流会稀释函数的执行频率。传2个参数,一个是回调函数,一个是间隔时间

export function throttle(func, wait) {
    let timerId;
    return function (...args) {
        if (!timerId) {
            timerId = setTimeout(() => {
                timerId = null;
                func.apply(this, args);
            }, wait);
        }
    }
}

防抖(debounce)
所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。

export function debounce(func, wait) {
    let timerId;
    return function (...args) {
        timerId && clearTimeout(timerId);
        timerId = setTimeout(() => {
            func.apply(this, args);
        }, wait);
    };
}

this指向问题
因为这个是一个单独的js文件,所以没有vue实例的this,而vue项目里单独js文件时是严格模式,所以外部函数里的this指向undefined。因为定义时函数已经执行了,返回了内部函数,相当于这个函数放在了vue实例内部,所以内部函数的this也就是vue实例,定时器用的箭头函数,this指向定义时的this,所以定时器里的this也就是vue实例。通过apply函数,就可以将func中的this指向vue实例,那我们自定义的func函数中使用的this就可以调用到当前vue的所有方法和变量。

闭包问题
因为定义时函数已经被执行了,执行过程就是返回内部函数给Vue中的search函数,内部函数引用了外部函数的timerId,所以形成闭包,timerId被保持在debounce函数返回的内部函数中,无法进行内存回收。如果再次执行search方法,timerId还会被引用;如果还有search3使用debounce方法,会有另外一个timerId被保持住。

如何使用

import {debounce,throttle} from '@/路径'
methods: {
    search: debounce(function(参数) {
        //回调函数,要执行的业务逻辑
    }, 300),
    search2: throttle(function(参数) {
        //回调函数,要执行的业务逻辑
    }, 300),
}

7.Vue为何使用函数返回data

Vue中的data首先不能使用对象返回,无法被访问到,原因在于Vue的内部逻辑导致其访问不到。如果使用函数返回,组件就可以正常工作了,但是如果data函数中的对象定义到外部为comdata,然后直接return comdata,会发生什么呢?当页面引用组件counter多次的时候,他们共享comdata,Vue调用该函数以检索该对象时,返回的都是同一个对象的引用,此时数据就会相互影响。为此Vue试图通过返回函数内的对象来防止数据的共享,这样Vue每次调用data时,返回的都是一个独立的新对象,每个组件实例都是自包含的,并且包含自己的部状态,在此形成闭包。因此要求data属性包含一个函数,实际上是一种防御措施。data属性应该是组件上下文的一个函数,总是返回一个新对象。

Vue.component('counter', {
    template: `
        <div>
            <button @click="counter++">{{ counter }}</button>
        </div>
    `,
    data: function() {
        return {
	    counter: 0
	};
    }
});
posted @ 2021-03-28 22:25  木-鱼  阅读(189)  评论(0)    收藏  举报