参考https://www.jianshu.com/p/638e7454ec1a
1.单页面应用是什么?
单页应用(Single Page Application),是一种只需要将单个页面作为容器加载到浏览器之中的Web应用程序。
原理:主要由History和Hash两种形式实现
优点:
(1).避免了页面的重新加载,用户有良好流畅的交互体检
(2).得益于ajax,可以实现无跳转刷新,没有页面之间的切换
(3).减轻服务器压力,服务器只用出数据就可以了,不用管展示逻辑和页面合成
缺点:
(1).第一次加载首页耗时相对长一些
(2).不利于seo的优化
(3).不适合开发大型项目(设计大量DOM的操作)
2.什么是vuex?
vuex是vue的状态管理模式,它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化
常应用于多个组件共享状态时,如购物车、登录状态等
3.Vue.js的核心是什么
数据驱动、组件化
4.Vue的生命周期以及调用顺序
创建前/后:
beforeCreate,vue实例的$el和数据对象data此时都为undefined,还未初始化;
created,vue实例的数据对象data有了,但是$el还没有
载入前/后:
beforeMount,vue实例的$el和data都初始化了,data中的模板和数据生成了html,但还没有挂载在html上;
mounted,挂载完成,也就是模版中的html渲染到到html页面中
更新前/后:
beforeUpdate,数据更新之前被调用;
updated,更新完成之后调用,组件Dom已经更新,要避免在此期间更改数据,否则可能会导致无限循环
销毁前/后:
beforeDestory,在实例销毁之前调用,此时实例仍然完全可用,一般可以在这一步做一些重置的操作,比如清除定时器和监听的dom事件;
destoryed,在实例销毁之后调用,此时所有的事件监听器都会被移除,组件已被拆解,数据绑定被卸载,所有的子实例也会被销毁
组件的调用顺序都是先父后子,渲染完成的顺序是先子后父;
组件的销毁操作是先父后子,销毁完成的顺序是先子后父;
5.从template转换成真实DOM的实现机制
先将template中的html转换成函数,然后利用这个函数生成virtual dom对象,遍历这个对象,生成真实的dom
6.virtual DOM原理
Virtual DOM是一个简单的js对象,在页面进行更新的时候,借助虚拟DOM元素的改变可以在内存中进行比较,并将多次比较的结果合并以后一次性的更新到页面,从而减少页面渲染的次数,提高渲染效率。
具体实现步骤如下:
(1).用js对象结构表示DOM树的结构,然后用这个树构建一个真正的DOM树,插入到文档中
(2).当状态变更的时候,重新构造一颗新的对象树,然后用新的树和旧的树进行比较,记录两棵树的差异
(3).把记录到的差异应用到真正的DOM树上,视图就更新了
7.Vue的双向绑定原理
vue2
采用数据劫持结合发布者-订阅者模式的方法,通过Object.defineProperty()来劫持各个属性的getter、setter属性,在数据变动后,通知订阅者,触发更新回调函数,重新渲染视图。当把一个普通js对象传给Vue实例来作为它的data选项时,Vue将遍历它的属性,用Object.defineProperty()将它们转为getter/setter。用户看不到getter/setter,但是在内部它们让Vue追踪依赖,在属性被访问和修改时通知变化
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<input type="text" id="input">
<span id="span"></span>
</div>
</body>
<script>
let obj = {}; //定义一个空对象
let val = 'gwy'; //赋予初始值
Object.defineProperty(obj, 'val', {//定义要修改对象的属性
get: function () {
return val;
},
set: function (newVal) {
//定义val等于修改后的内容
val = newVal
//让文本框的内容等于val
document.getElementById('input').value = val
//让span的内容等于val
document.getElementById('span').innerHTML = val
}
})
document.addEventListener('keyup', function (e) {
//当在文本框输入内容时让对象里你定义的val等于文本框的值
obj.val = e.target.value;
})
</script>
</html>
vue3
原理:Vue 3.0与Vue 2.0的区别仅是数据劫持的方式由Object.defineProperty更改为Proxy代理,其他代码不变
为什么要用Proxy取代Object.defineProperty?
(1).Object.defineProperty存在一定的局限性,无法监控到数组下标的变化,导致直接通过数组的下标给数组设置值,不能实时响应。针对数组的某些方法进行了hack处理,只有以下八种方法可以检测到变化:
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
(2).Object.defineProperty只能劫持对象的属性,因此我们需要对每个对象的每个属性进行遍历。Vue里,是通过递归以及遍历data对象来实现对数据的监控的,如果属性值也是一个对象那么需要深层遍历,显然如果能劫持一个完整的对象,不管是对操作性还是性能都会有一个很大的提升。
要取代Object.defineProperty的Proxy有两个优点:
(1).可以劫持整个对象,并返回一个新对象
(2).有13种劫持操作
const obj = {};
const input = document.getElementById("input")
const title = document.getElementById("title")
const newObj = new Proxy(obj, {
get: function(target, key, receiver) {
console.log(`getting ${key}!`)
return Reflect.get(target, key, receiver)
},
set: function(target, key, value, receiver) {
console.log(target, key, value, receiver)
if (key === "text") {
input.value = value
title.innerHTML = value
}
return Reflect.set(target, key, value, receiver);
}
})
input.addEventListener("keyup", function(e) {
newObj.text = e.target.value;
})
什么是Reflect?
Reflect是ES6里的新的对象,非构造函数,不能用new操作符。可以把它跟Math类比,Math是处理JS中数学问题的方法函数集合,Reflect是JS中对象操作方法函数集合,它暴露出来的方法与Object构造函数所带的静态方法大部分重合,实际功能也类似,Reflect的出现一部分原因是想让开发者不直接使用Object这一类语言层面上的方法,还有一部分原因也是为了完善一些功能。Reflect提供的方法还有一个特点,完全与Proxy构造函数里Hander参数对象中的钩子属性一一对应。
8.v-model的作用
实现输入框的双向绑定,可作用于<input>和<textarea>等,其效果等同于:
<input v-bind:value="message" v-on:input="message = $event.target.value" /> //把input输入框的value属性值和vue实例的message属性进行绑定,同时监听输入事件。
实际使用:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--引入最新的vue稳定版本-->
<script type="text/javascript" src="https://unpkg.com/vue/dist/vue.min.js"></script>
<link rel="stylesheet" href="./css/style.css" type="text/css">
</head>
<body>
<!--input输入框-->
<div id="app">
<input type="text" v-model="message" placeholder="请输入">
<p>输入的内容是: {{message}}</p>
</div>
<script>
var vue=new Vue({
el:'#app',
data:{
message:''
}
});
</script>
</body>
</html>
9.v-if与v-show的区别与应用场景?
v-if是通过重建和销毁dom来达到显示和隐藏的效果
v-show是通过修改dom的display属性来显示和隐藏
当需要频繁切换的时候,用v-show
10.Vue跨组件通信方案
https://www.cnblogs.com/fundebug/p/10884896.html
父传子:属性传值,父组件给子组件标签上定义属性,子组件通过props接收
子传父:事件传值,子组件通过$emit,父组件通过在子组件上定义自定义事件来接收
兄弟组件:通过中央事件总线(Event Bus)
Vuex:全局状态管理
11.Vue 中 key 值的作用
Key的作用就是尽可能的复用dom元素,当有相同的标签名和元素切换时,需要通过key的特效设置唯一的值来标记,让vue区分它们,否则vue为了效率只会替换相同标签内部的内容
12.vue 常用的修饰符
v-model.number:将用户输入的值转为数值类型
v-model.trim:自动过滤用户输入的首尾空白字符
@click.stop:阻止事件冒泡
@click.once:事件只执行一次
v-on:keyup.enter:(键盘修饰符)按下键盘的时候
14.Vue组件中的data为什么是一个函数
一个组件被复用多次的话,也就会创建多个实例。本质上,这些实例用的都是同一个构造函数。如果data是对象的话,对象属于引用类型,会影响到所有的实例。所以为了保证组件不同的实例之间data不冲突,data必须是一个函数。
15.router-link和a标签的区别
router-link的to属性跳转比起a标签的href跳转的区别是,router-link进行跳转不会跳转到新页面,避免了重新渲染,它只更新变化的部分从而减少dom性能的消耗
16.Vue如何优化首屏加载速度
(1).路由懒加载,把不同路由对应的组件分隔成不同的代码块,按需加载
(2).减少入口文件体积
(3).静态资源本地缓存
(4).使用CDN资源,减小服务器带宽压力
(5).使用Nginx开启gzip压缩,减小网络传输的流量大小
(6).使用SSR(服务端渲染)
17.MVC和MVVM
https://www.jianshu.com/p/b0aab1ffad93
MVC的思想:一句话描述就是Controller负责将Model的数据用View显示出来,换句话说就是在Controller里面把Model的数据赋值给View,比如在controller中写document.getElementById("box").innerHTML = data[”title”],只是还没有刻意建一个Model类出来而已。
MVVM:
M:Model(服务器上的业务逻辑操作)
V:View(页面)
VM:ViewModel(Model与View之间核心枢纽,比如Vue.js)
-
Model与ViewModel之间的双向关系
Model通过Ajax通信,发送数据给ViewModel。
ViewModel也可以通过Ajax通信,发送请求给Model。 -
ViewModel与View之间的双向关系
ViewModel中的数据改变,可以同时改变View上的显示内容。
View上的内容改变(比如输入框中的内容),也可以同时改变ViewModel中对应的数据。
18.v-if和v-show的差异
-
v-if
是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。 -
v-if
也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。 -
相比之下,
v-show
就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。 -
注意,
v-show
不支持<template>
元素,也不支持v-else
。
一般来说,v-if
有更高的切换开销,而 v-show
有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show
较好;如果在运行时条件很少改变,则使用 v-if
较好。
此外,当 v-if
与 v-for
一起使用时,v-for
具有比 v-if
更高的优先级,这意味着 v-if
将分别重复运行于每个 v-for
循环中,所以不推荐同时使用v-if
和 v-for。
17.key是什么,有什么用
说到底,key的作用就是更新组件时判断两个节点是否相同。相同就复用,不相同就删除旧的创建新的。
由于渲染列表组件时会要求每个组件都有自己不同的状态,比如渲染一个新闻列表,点击其中一条希望其显示的颜色和未点击的颜色不同,为了保存这个状态,使用key可以唯一辨识。