vue基础

谈谈你对MVVM开发模式的理解

  • 包括Model(数据模型)、View(ui层)、ViewModel(视图数据模型)

简述Vue的响应式原理

  • Vue实例创建时,vue会遍历data选项做的属性,用Object.defineProperty将它们转为getter/setter并且在内部追踪相关依赖,在属性被访问和修改时通知变化;
  • 每个组件实例都有相应的watcher程序实例,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的setter被调用时,会通知watcher重新计算,从而致使它关联的组件得以更新。

data中对象属性中添加一个新的属性会发生什么?怎么解决?

值已改变,但是视图没有更新。原因是在Vue实例创建时,新增属性并未声明,因此也就没有被Vue实例转换为响应式的属性,自然就不会触发视图的更新,这时就需要使用Vue的全局api $set
eg:this.$set(this.obj,'b','value')


delete和Vue.delete删除数组的区别?

delete只是使被删除的元素变成empty/undefined,其他元素的键值还是不变
Vue.delete同时删除了键与值


Vue实现数据双向绑定的原理

  • 采用数据劫持+发布-订阅者模式实现
  • Object.defineProperty来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应监听回调。

Vue.use全局注册组件方法

  • Vue.use主要针对有install方法的组件进行全局注册
  • 针对没有install方法的例如axios,无法使用Vue.use,采用添加原型属性的方法进行全局注册
main.js中注册
import axios from 'axios'
Vue.prototype.axios = axios

.vue文件中使用
this.axios.get('***')

虚拟DOM实现原理

  • 用JS模拟真实DOM树,对真实DOM进行抽象
  • diff 算法 — 比较两棵虚拟 DOM 树的差异
  • pach 算法 — 将两个虚拟 DOM 对象的差异应用到真正的 DOM 树

服务器端渲染优缺点

(1)服务端渲染的优点:

更好的 SEO: 因为 SPA 页面的内容是通过 Ajax 获取,而搜索引擎爬取工具并不会等待 Ajax 异步完成后再抓取页面内容,所以在 SPA 中是抓取不到页面通过 Ajax 获取到的内容;而 SSR 是直接由服务端返回已经渲染好的页面(数据已经包含在页面中),所以搜索引擎爬取工具可以抓取渲染好的页面;
更快的内容到达时间(首屏加载更快): SPA 会等待所有 Vue 编译后的 js 文件都下载完成后,才开始进行页面的渲染,文件下载等需要一定的时间等,所以首屏渲染需要一定的时间;SSR 直接由服务端渲染好页面直接返回显示,无需等待下载 js 文件及再去渲染等,所以 SSR 有更快的内容到达时间;

(2) 服务端渲染的缺点:

更多的开发条件限制: 例如服务端渲染只支持 beforCreate 和 created 两个钩子函数,这会导致一些外部扩展库需要特殊处理,才能在服务端渲染应用程序中运行;并且与可以部署在任何静态文件服务器上的完全静态单页面应用程序 SPA 不同,服务端渲染应用程序,需要处于 Node.js server 运行环境;
更多的服务器负载:在 Node.js 中渲染完整的应用程序,显然会比仅仅提供静态文件的 server 更加大量占用CPU 资源 (CPU-intensive - CPU 密集),因此如果你预料在高流量环境 ( high traffic ) 下使用,请准备相应的服务器负载,并明智地采用缓存策略。


Vue中$refs实现原理

原理:
  • 将元素或子组件注册引用信息到父组件或是vue实例上,
  • 注册后的引用信息就会呈现在父组件或vue实例的$.refs上
  • 通过$.refs获取DOM对象或子组件对象
作用一:获取页面DOM元素
  • 必须在mounted之后的生命周期钩子函数中使用。因为beforeMount只是将模板编译完成,尚未挂载在真实DOM上,还只是挂载在虚拟DOM上,因此ref是在渲染完成后才创建的。
<input type="text" ref="msgText" v-model="msg" />
mounted(){
    console.log($.refs.msgText.value)
}
作用二:获取子组件对象
  • 获取子组件对象之后,就可以获取到子组件的data,methods等属性了
<div id="app">
    <input type="text" ref="msgText" v-model="msg" />
    <button @click="getElement">获取元素值</button>

    <hr>

    <child ref="childComponent"></child>
</div>

<template id="child">
    <div>
        <input type="datetime" name="datetime" v-model="local">
        <button @click="getLocalData">获取当前时间</button>
    </div>
</template>

methods:{
    getElement() {
        console.log('input 输入框的值为:' + this.$refs.msgText.value)
        this.$refs.childComponent.getLocalData()
        console.log('子组件 input 输入框的值为:' + this.$refs.childComponent.local)
    }

Vue中key的作用与原理

作用一:增添选项时,防止勾选项发生偏移
<li v-for="(item, i) in list">
    <input type="checkbox"> {{item.name}}
</li>
// 没有key的场景
勾选选项二,之后再再头部新增选项x
跟新后,原选项二排列至第三位,去勾选。原选项一排列至第二位,并变为勾选项
作用二:优化diff算法,提升虚拟DOM更新效率
  • 两个假设:1.两个相同的组件产生类似的DOM结构,不同的组件产生不同的DOM结构;2.同一层级的DOM节点可以通过唯一的id来区分
  • 节点类型不同,则直接删除并创建新的节点,不在比较之后的节点
  • 节点类型相同,则更新属性值
// b-c之间插入e
a-->b-->c-->d
a-->b-->e-->c-->d
// 没有key的情况
a-a
b-b
c-e
d-c
结尾再插入d
// 有key的情况
直接在b-c之间插入e

Vue中$nextKick的作用及原理

场景一:created钩子函数中操作DOM时,一定使用Vue.nextTick()
  • 在created()钩子函数执行的时候DOM 其实并未进行任何渲染,而此时进行DOM操作无异于徒劳,所以此处一定要将DOM操作的js代码放进Vue.nextTick()的回调函数中。
  • 与之对应的就是mounted()钩子函数,因为该钩子函数执行时所有的DOM挂载和渲染都已完成,此时在该钩子函数中进行任何DOM操作都不会有问题。
场景二:DOM结构随着数据的变化而改变时,整个操作放在Vue.nextTick()中,v-for
原理:
  • 官方解释:Vue 异步执行 DOM 更新。只要观察到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据改变。如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作上非常重要。然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。Vue 在内部尝试对异步队列使用原生的 Promise.then 和MessageChannel,如果执行环境不支持,会采用 setTimeout(fn, 0)代替。
posted @ 2019-11-03 10:56  南华秋水  阅读(155)  评论(0编辑  收藏  举报