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:通过template和slot解决,使用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、state和localStorage中数据互传,是因为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
};
}
});

浙公网安备 33010602011771号