web前端-这些问题你熟悉吗?

一、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则不然。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值