Vue相关零散知识点

  •  记:Vue 运行时的核心主要包括数据初始化、数据更新、异步队列、DOM渲染这几个部分。
  •  记:Vue双向数据绑定的核心和基础api是Object.defineProperty。其内部真正参与数据双向绑定流程的主要有Obderver、Dep和Watcher,基于defineProperty和发布者订阅者模式,最终实现数据的双向绑定。
  • 记:当数据发生变化时,会调用 dep.notity() 进而通知订阅的 watcher 进行更新。
  • 记:MVVM中的ViewModel不受开发者操作

  • 记:依赖收集:界面用到了就收集,没有用到就不收集。
  • 记:el: 'body'  直接选中body标签,不通过类或id也可以实现挂载

  • 记:dep对象就是一个闭包
  • 记:computed计算属性是一个函数,就和react/JS函数一样,可以使用三目运算符等js方法
  • 记:<p v-if="isShow"></p> 有哪些来源:
  • 1⃣️data(){ return { isShow: false} }    2⃣️computed:{ isShow: function(){return false};  }
  • 记:模板v指令的代码都会生成在render函数中,通过app.$options.render就能得到渲染函数
  • 记:v-for: item in items形式遍历数组或对象、建议设置key值
  • 记:new Vue()实例中可以有:【el、data、templete, methods、computed、全声明周期、definePorperty(){set,get}、watcher,Dep】
  • 记:能改变data初始数据的方式有哪些:【definePorperty(set), methods、computed ,声明周期】,操作改变时都需要加上this
  • 记:想使用Object.defineProperty()时,需要先在外层套一个函数➕函数调用👇🌟
  • 记:以后,不管是原生JS, React,Vue,凡是跟遍历沾边的方法:最好都设置上key:
<li v-for="item in items" :key="item.id">
  {{ item.label }}
</li>
  • 记:数据监听器 Observer:能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者
  • 记:指令解析器 Compile:对每个元素节点的V指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数

          ---------new Vue实例的生命周期-----------

  • 记:beforeCreate在执行的时候,data还没有被初始化,DOM也没有初始化,所以不能在这里发起异步请求并且不能给数据模型的属性赋值。
  • 记:created:可发起异步请求进行数据模型的赋值操作,此时还拿不到DOM
  • 记:beforeMount与created之间只有一个是否是浏览器的判断,所以这时候在钩子函数中的里数据模型里、页面的状态,与created是一样的。
  • 记:mounted被执行到的时候,数据模型和页面的DOM都初始化完成,在这里我们可以给数据模型赋值也可以进行DOM操作了。
  • 记:beforeUpdate: 由于beforeUpdate不会自动触发,是数据发生改变时触发,所以在mounted中更改了data数据,beforeUpdate再执行更新时,值已经是最新的了
  • 记:Update:与beforeUpdate的数据与页面保持一致。
  • 记:beforeDestroy:在mounted手动进行了destory销毁组件,触发了beforeDestroy钩子函数执行,在此生命周期中,依旧能看到数据模型与DOM是未被注销的。
  • 记:destroyed:可以看到DOM已经被清除了
  • Ajax请求应该放在created钩子函数是最好的 --- 待求证
  • 了解:生命周期拓展:activated与deactivated,被keep-alive标签包裹的子组件才会得到触发。不常用,易被遗忘
  • 同步渲染🆚异步渲染:当数据变化时,页面订阅的响应操作与数据变化完全对应;当数据变化都操作完成时,页面才会得到响应/渲染。
  • Vue 不能检测通过数组索引直接修改一个数组项---待查资料验证,如下代码👇➕

  • var vm = new Vue({
      data: {
        items: ['a', 'b', 'c']
      }
    })
    vm.items[1] = 'x' // 不是响应性的
  • 在vue的data中,一开始并不存在变量edit, 我后期通过方法进行的赋值。这样可能会导致vue页面渲染的响应慢一拍。最好一开始就在data中初始化变量(订阅值)

--------------------------------------------------start👇----------------------------------------------------------------​​​​​​​

computed和 watch 的区别?

  • Watch
    1⃣️是什么?
        是监听数据更新变化后,每次都会将最新的值赋给dom订阅者。结构:{ 键名:键值} 键名:被观察的表达式;   键值:回调函数/方法名/对象

  • 2⃣️干什么的?
        用于观察和监听页面上的vue实例
    3⃣️啥时候用?
        适用于在数据变化的同时执行异步操作(并发)
        适用于比较大的开销
    4⃣️代码实现?​​​​​​​

  • computed 
    1⃣️是什么?
       计算属性
    2⃣️干什么的?
       页面上的数据有依赖性
    3⃣️啥时候用?
       大部分情况选择用它
       当页面中某些数据依赖其他数据时用它
    4⃣️代码实现?​​​​​​​

  • #两者有啥区别?
    1.看data中有没有数据:
           watch是看看data有没有数据,没有我就没活儿就歇着了
           computed 是如果没有data没有数据,我又需要,那我就自己造变量用于计算

    2.各自的图:

上图解析#:

Computed:一个数据受多个数据的影响
验证:total受abc三个数据的影响
Computed :.{
 Total:this.a*this.b*this.c
}

------------------------------------------------------------end👆-------------------------------------------------------------

  -----------​​​​​​​记 🌟🌟题:------------------start👇---------------------------------------------------------

// 初始化
const model = {
  name: 'vue',
};


// 创建监听器
function observe(obj) {
  let val = obj.name;
  Object.defineProperty(obj, 'name', {
    get() {
      return val;
    },
    set(newVal) {
      // 当有新值设置时,执行setter
      console.log(`name变化:从${val}到${newVal}`);
      // 解析到页面
      compile(newVal);
      val = newVal;
    }
  })
};


function compile(val) { 
  document.querySelector('#name').value = val;
};


observe(model); // 调用监听器,对model开始监听

 ------------------------------------------------------------🌟🌟end👆------------------------------------------------------------

  • 1. 如果在data中没有相应的属性的话,是不能watch的,这点和computed不一样。
  • 就算在data中没有直接声明出要计算的变量,也可以直接在computed中写入。
    计算属性默认只有getter,可以在需要的时候自己设定setter:
     

     记:测试v-for和v-if如果应用在同一个标签内,v-for优先级高。如果不在一个标签内,就该咋滴咋滴,按顺序执行。https://www.jb51.net/article/203971.htm​​​​​​​

  • 本例子🌰: 测试证明v-for和v-if如果应用在同一个标签内,v-for优先级高。
             看vue源码也证实了结论:同一个标签内,v-for优先级确实比v-if高
    
    判断依据是:模版对应的渲染函数代码👇👇👇
    
    // vue模版语法
    <div id="app">
    
      <p v-if="isShow" v-for="item in items">
    
        {{ item.title }}
    
      </p>
    
    </div>
    
    
    vue模版语法👆------>经app.$options.render方法 转换成------>对应的渲染函数👇:
    
    // 对应渲染函数
    ƒ anonymous() {
     with (this) { return
      _c('div', { attrs: { "id": "app" } }, 
      _l((items), function (item) 
      { return (isShow) ? _c('p', [_v("\n" + _s(item.title) + "\n")]) : _e() }), 0) }
    }
    
    
    
    知识点🌹: render渲染函数源码中_l意思是列表渲染
    
    注意事项⚠️*:
    永远不要把 v-if 和 v-for 同时用在同一个元素上,带来性能方面的浪费(因为每次渲染都会先循环再进行条件判断)
    
    
    解决办法💡:
    在外层嵌套template(页面渲染不生成dom节点),在这一层进行v-if判断,然后在内部进行v-for循环
    <templete v-if="isShow">
       <p v-for="item in items"></p>
    </templete>
    
    
    下边这句还不理解🤔️:➕
    如果条件出现在循环内部,可通过计算属性computed提前过滤掉那些不需要显示的项
    computed: {
      items: function() {
       return this.list.filter(function (item) {
        return item.isShow
       })
      }
    }

    先收集依赖流程:

observe -> 
walk -> 
defineReactive -> 
get -> 
dep.depend() -> 
watcher.addDep(new Dep()) -> 
watcher.newDeps.push(dep) -> 
dep.addSub(new Watcher()) -> 
dep.subs.push(watcher)
依赖收集会经过以上流程,最终watcher.newDeps数组中存放dep列表,dep.subs数组中存放watcher列表。

为什么v-for和v-if不能连用?

通过用app.$options.render方法得到模版(含v指令)对应的渲染函数。依据函数结果:

初步结论:v-for优先级是比v-if高

为什么要进行依赖收集?

new Vue({
    data(){
        return {
             name:'zane',
             sex:'男'
        }
    }
})

上面的data中,实际上页面只使用到了name,并没有使用age,根据Object.defineProperty的转换,如果我们设置了this.sex='女',那么Vue也会去执行一遍虚拟DOM的比较,这样就无形的浪费了一些性能,因此才需要做依赖收集,界面用到了就收集,没有用到就不收集。------【Object.defineProperty的缺点: 不会变通,性能低】


Dep相关的用法的作用?
new Dep() //
dep.notity() // 
dep.depend() //
dep.addSub(new Watcher()) //
dep.subs.push(watcher)   //
Dep.target ===Watcher实例化对象: 通知订阅的watcher更新
Dep.prototype.notify = function notify () {}

更新触发的依赖:

set -> 
dep.notify() -> 
subs[i].update() -> 
watcher.run() || queueWatcher(this) -> 
watcher.get() || watcher.cb -> 
watcher.getter() -> 
vm._update() -> 
vm.__patch__()

1.当数据发生变化时,Obderver、Dep、Watcher都会第一时间知道吗?

2.Vue的异步队列的思路以及实现原理?👇

$nextTick、$nextTick 接口 是干嘛的?通过 nextTick 放入 callbacks 如何理解?Vue 中就是 flushSchedulerQueue?

1⃣️flushSchedulerQueue:

将队列中所有的 watcher 按照 id 进行排序、原因是?---要保证 watcher 按照正确的顺序执行(参照初始/原本的依赖关系), 之后再遍历队列依次执行其中的 watcher。

2⃣️nextTick:

xx->改成异步执行

目的:在一个事件循环(clickHandler)中让 flushSchedulerQueue 只执行一次,避免多次执行遍历、渲染,耗费性能

5. new Vue实例初始化data的2种写法?

// 第1种
new Vue({
  el: 'example1',
  data(){
    return(){
      a:1,
      b:2
    }

  }

});


// 第2种
new Vue({
  el: 'example2',
  data:{ 
      a:1,
      b:2
  }

});

6.  通过<div>{{ words }}</div>这个模版,猜测这个{{ words }}都可能来自于哪里?

       1⃣️new Vue实例中的data初始化变量

        2⃣️new Vue实例中的computed计算属性

<div id="example">
  <div>{{ words }}</div>
  <input type="button" @click="clickHanler" value="click"/>
</div>

  var vm = new Vue({
    el:"#example",
    data: {
      name: "Devin",
      greetings: "Hello"
    },
    computed: {
      words: function(){
        return this.greetings + ' ' + this.name + '!'
      }
    },
    methods: {
      clickHanler(){
        this.name = 'Devinn';
        this.name = 'Devinnzhang';
        this.greetings = 'Morning';
      }
    }
  });


#解析:
此时 Vue 中创建了两个 watcher:
一个是渲染 watcher,负责渲染模板,一个是 computed watcher 负责计算属性。


#场景➕问题:
操作场景:当点击 clickHandler 的时候数据发生变化会通知道两个 watcher要更新。

Q1、渲染watcher 和 computed watcher 同时订阅了变化的数据,哪一个先执行,执行顺序是怎么样的?

答:可见,在数据更新的阶段,需要一个管理多个 watcher 进行更新的角色。

此角色需要保证: watcher 能够按照正确的顺序执行&并尽可能的减少执行次数。

在Vue中,这个角色===>异步队列: 是在数据更新时开启的(肯定的哇)===> new Dep();

当数据发生变化时,会调用 dep.notity() 进而通知订阅的 watcher 进行 更新

Q2、在一个事件循环中 name 的变化触发了两次,greetings 触发了一次,对应两个 watcher 一共执行了几次?DOM渲染了几次? 
 

关于Vue数据响应式,常见的场景有下面这几个:

  • 数据变 → 使用数据的视图变
  • 数据变 → 使用数据的计算属性变 → 使用计算属性的视图变
  • 数据变 → 开发者主动注册的watch回调函数执行

三个场景,对应三种watcher:

  • 负责敦促视图更新的render-watcher
  • 执行敦促计算属性更新的computed-watcher
  • 用户注册的普通watcher(watch-api或watch属性)

4.Vue的渲染机制?--(见:onsite文档)

templete模版- compiler编译-->ats🌲-【loader/vue-templete-compilerwebpack工具编译】->render渲染函数--【源码调用render函数with方法】-->生成虚拟DOM--【vm._update(){} 2个执行时机】->都能将虚拟DOM转成真实DOM

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值