目录
一、Vue
1.1 为什么要把data变成函数并return属性呢?
组件是一个可复用的实例,当你引用一个组件的时候,组件里的data是一个普通的对象,所有用到这个组件的都引用的同一个data,就会造成数据污染。
data以函数形式返回,在实例化组件的时候,我们只是调用了data函数生成的数据副本,避免了数据污染。
1.2 computed定义数据后如何赋值
computed:{
reMsg:{
get:function(){
return this.msg.split('').reverse().join('')
},
set:function(value){
this.msg = value; //最后修改了msg
}
}
}
1.3 Vue的数据为什么频繁变化但只会更新一次
1 检测到数据变化
2 开启一个队列
3 在同一事件循环中缓冲所有数据改变
4 如果同一个 watcher (watcherId相同)被多次触发,只会被推入到队列中一次
1.4 循环嵌套层级太深,视图不更新
比如给数组添加了一个新的参数,但是也页面始终没有重新渲染(原因数组嵌套太深导致页面无法重新渲染rander)。
解决方案如下:添加this.$forceUpdate();进行强制渲染(不建议使用,当前实例重新渲染)
1.5 路由参数变化时,页面不更新(数据不更新)
原因:路由视图组件引用了相同组件时,当路由参会变化时,会导致该组件无法更新,也就是我们常说中的页面无法更新的问题。
解决方案:
通过 watch 监听 r o u t e 的变化。强制更新数据 t h i s . route 的变化。 强制更新数据 this. route的变化。强制更新数据this.forceUpdate()
1.6 Vue中给对象添加新属性时,界面不刷新怎么办
该内容参考地址
原因:
vue2使用Object.defineProperty实现数据响应式
组件初始化时,对data中的obj进行递归遍历,对obj的每一个属性进行劫持,添加set,get方法。我们后来新加的newProperty属性,并没有通过Object.defineProperty设置成响应式数据,所以修改后不会视图更新
有如下三种解决方案:
Vue.set()
Object.assign()
lodash库的_assign() 和 _merge()
$forcecUpdated()
如下实例:在浏览器中输出的是最新结果,但是页面视图并没有更新
<template>
<div>
{{obj}}<br>
<button @click="addProperty">动态添加新属性</button>
</div>
</template>
<script>
export default {
data(){
return {
obj:{
oldProperty:"旧值"
}
}
},
methods:{
addProperty(){
this.obj.newProperty = "新值"
console.log(this.obj)
}
}
};
</script>
methods:{
addProperty(){
this.$set(this.obj, "newProperty", "新值");
console.log(this.obj)
}
}
methods:{
addProperty(){
// this.obj = Object.assign(this.obj,{newProperty:'新值'})
// 以上写法不会更新,要生成一个新对象
this.obj = Object.assign({},this.obj,{newProperty:'新值'})
console.log(this.obj)
}
}
也可以使用lodash库的_assign() 和 _merge()为对象添加响应式属性,触发视图更新
this.obj = _assign({},this.obj,{newProperty:'新值'})
this.obj = _merge({},this.obj,{newProperty:'新值'})
methods:{
addProperty(){
this.obj.newProperty = "新值"
this.$forceUpdate();
console.log(this.obj)
}
}
二、JS
2.1 预编译,执行过程理解
1:创建AO对象
2:找形参和变量的声明 作为ao对象的属性名 值为undefined
3:实参形参统一
4:找函数声明 会覆盖变量的声明
var a = 3
function fn () {
console.log(a)
var a = 4
}
fn() // 分析代码,程序会打印什么
// 预编译阶段 ao {a: undefined}
// 执行阶段: a = undefined。
// 需要注意的是var a=4(函数fn内,var a提升在作用域顶部,相当于function fn(){var a;console.log(a);a = 4;})
再分析如下代码会是怎样的一个结果
<script>
var a = 1;
function test () {
console.log(a)
this.a = 2
console.log(this.a)
this.a = 3
}
test()
</script>
// 按照上面4步规则来我们分析a的变化
// 特别说明:函数内的this.a 此时相当于window.a
// 所以第一句console.log(a) 在执行阶段直接输出 1;
// 第二句console.log(this.a) 因为前一句赋值为了2, 所以此时a的值为 2
如果上面两个分析你看清楚了,下面这段代码应该就很清晰了(如果还不清楚,那就是还没理解)
var a = 3
function fn () {
var a = 4
console.log(this.a) // 此时this.a 输出多少???
}
fn()
以上代码是否都搞清楚了,如果搞清楚了再看看如下代码看看依次分别会打印出什么结果
特别说明:此加入了构造函数
<script>
var a = 1;
function test () {
console.log(a)
this.a = 2
console.log(this.a)
this.a = 3
}
test()
new test()
</script>
// 依次分析:
// test() 执行完此时console.log(a) 输出的是 1;console.log(this.a) 输出的是 2。
// 这里需要注意的是:test()执行完后 此时this.a被赋值为了3(很重要,而且this.a 相当于 window.a)
// 然后执行构造函数 new test() , 此时你需要知道的是函数test内的this指向的是当前构造函数的这个实例
// 如果上面分析看懂了 你会很清楚的知道会分别打印出 1 2 3 2
以上代码只是讲到了变量的提升,接下来看看函数提升是怎样的?
变量声明与函数声明都会提升;函数声明会覆盖变量声明,但不会覆盖变量赋值
function fn(a,c) {
console.log(a)
var a = 123
console.log(a)
console.log(c)
function a() {}
if(false) {
var d = 678
}
console.log(d)
console.log(b)
var b = function() {}
console.log(b)
function c() {}
console.log(c)
}
fn(1,2)
// 第一步创建ao对象 AO: {}
// 第二步找形参和变量声明
AO: {
a: undefined
c: undefined
d: undefined
b: undefined
}
// 第三步实参和形参统一
AO: {
a: 1
c: 2
d: undefined
b: undefined
}
// 第四步找函数声明
AO: {
a: function a() {}
c: function c() {}
d: undefined
b: undefined
}
// 此时预编译阶段执行结束,接下来是js的解释执行(逐行执行)
// function a() {} 123 function c() {} undefined undefined function() {} function c() {}
2.2 数组相关及其他
先看我的另一篇博客: 博客地址
1)求一个数组中的最大值
let arr = [6,1,9,2,10,4,8];
// 思考:max函数是不能传数组的,如果参数传递的是数组,这时候就可以考虑apply方法
console.log(Math.max.apply(null,arr)); // es5
console.log(Math.max(...arr)); // es6拓展运算符
console.log(Math.max.call(null,...arr)) // 同理这么写也是可以的
2)将两个数组合并的方法
let arr1 = [6,1,9,2];
let arr2 = [10,4,8];
console.log(arr1.concat(arr2)) // 这是我第一想到的
console.log([...arr1, ...arr2])
// 注意:这两个操作都不会影响到原数组 然后我们再分析一下如下代码,看看有啥不同
let arr1 = [1, 2, 3], arr2 = [4, 5, 6];
// Array.prototype.push.apply(arr1, arr2); // ES5
arr1.push(...arr2); // ES6
// 通过数组我们发现arr2还是原来的arr2,但是arr1已经变成了[1,2,3,4,5,6]
// 这也是为了说明concat()方法用于连接两个或多个数组,返回一个新的数组,不会改变原数组。push则不然。