1.说说你对SPA单页面的理解,它的优缺点分别是什么?
spa仅在Web页面初始化时加载相应的HTML、js、css,一旦页面加载完成,SPA不会因为用户的操作而进行页面的重新加载或跳转;取而代之的是利用路由机制实现HTML内容的变换,优化与用户的交互,避免页面的重新加载。
优点
1.用户体验好、快,内容的改变不需要重新加载整个页面,避免了不必要的跳转和重复渲染;
2.基于上面一点,SPA相对服务器压力小;
3.前后端职责分离,架构清晰,前端进行交互逻辑,后端负责数据处理;
缺点
1.初次加载耗时多:为实现单页Web应用功能及显示效果,需要在加载页面时,将js、css统一加载,部分页面按需加载;
2.前进后退路由管理:由于单页应用在一个页面中显示所有内容,所以不能使用浏览器的前进后退功能,所有的页面切换需要自己建立堆栈管理;
3.SEO难度较大:由于所有的内容都在一个页面中动态替换显示,所以在SEO上,其有着天然的弱势。
2.v-if和v-show的区别
1、当条件为真的时候 没有区别 当条件为假的时候 v-if通过创建或删除DOM节点来实现元素的显示隐藏,v-show通过css中的display属性来控制
2、v-if更适合数据的筛选和初始渲染 v-show更适合元素的切换
3.class与style如何动态绑定
class可以通过对象语法和数组语法进行动态绑定:
class
对象语法
<div :class="{active:isActive,'text-danger':hasError}"></div>
js;;
data(){
return {
isActive:true,
hasError:false
}
}
数组语法
<div :class="[isActive?active:'',errorClass]"></div>
style
对象语法
<div :style="{color:activeColor,fontSize:fontSize+'px'}"></div>
js;;
data(){
return {
activeColor:'red',
fontSize:20
}
}
数组语法
<div :style="[styleColor,styleSize]"></div>
js;;
data(){
return {
styleColor:{
color:"red
},
styleSize:{
fontSize:'20px'
}
}
}
4.怎样理解Vue的单向数据流?
所有的prop都使得其父子prop之间形成了一个单向下行绑定:父级prop的更新会向下流动到子组件中,但是反过来不行。这样会防止从子组件意外改变父组件的状态,从而导致你的应用的数据流难以理解。
额外的,每次父组件发生更新时,子组件中所有的prop都会刷新为最新的值。这意味着你不### 应该在一个子组件内部改变prop。如果你这样做了,vue会在浏览器的控制台中发出警告。### 子组件想修改时,可以通过$emit派发一个自定义事件,父组件接收后,由父组件修改
5.methods computed watch的区别
computed 具有缓存性,依赖于属性值,只有属性发生改变的时候才会重新调用
methods 是没有缓存的,只要调用,就会执行,一般结合事件来使用
watch 没有缓存性 监听data中的属性 属性值只要发生变化就会执行 可以利用他的特性做一些异步的操作
6.生命周期共有几个?分别在什么时候使用?
1.创建beforeCreate() 创建前的阶段,这个时候data中的数据,还未定义,所以不能使用 ### created() 最早开始使用 data和methods中数据的钩子函数
2.beforeMount() 指令已经解析完毕内存中已经生成dom树,还没有渲染到本地mounted() dom已经渲染完毕,最早可以操作DOM元素钩子函数
3. beforeUpdate() 当data的数据发生改变会执行这个钩子 内存更新,但是DOM节点还未更新 updated() 数据更新完成以后触发的方法,DOM节点已经更新
4. beforeDestroy()即将销毁 data和methods中的数据此时还是可以使用的,可以做一些释放内存的操作
destroyed()已经销毁完毕
keep-alive 方法
actived() 组件加上keep-alive,进入组件触发的方法
deactived 离开组件的时候触发的方法。
errorCaptured() 组件内发生错误的时候的触发的方法
7.vue的父组件和子组件生命周期钩子函数执行顺序?
vue的父组件和子组件生命周期钩子函数执行顺序可以归为以下4部分:
1.加载渲染过程
父beforeCreate -> 父created ->父beforeMount ->子beforeCreate ->子created ->子beforeMount ->子mounted ->父mounted
2.子组件更新过程
父beforeUpdate ->zibeforeUpdate ->子updated ->父updated
3.父组件更新过程
父beforeUpdate -> 父updated
4.销毁过程
父beforeDestory -> 子beforeDestory -> 子destoryed -> 父destoryed
8.created和mounted区别
created()是最早使用data中数据的钩子函数;
mounted()是最早可以操作dom元素的钩子函数.
9.父组件可以监听到子组件的生命周期嘛?
比如有父组件 Parent 和子组件 Child ,如果父组件监听到子组件挂在mounted就做一些逻辑处理,可以通过以下方法实现:
//Parent.vue
<Child @mounted = "doSomething" />
// Child.vue
mounted(){
this.$emit('mounted')
}
以上需要手动通过$emit触发父组件的事件,更简单的方式可以在父组件引用子组件时通过@hook来监听即可 ,如下所示:
// Parent.vue
<Child @hook:mounted = "doSomething" />
doSomething(){
console.log('父组件监听到mounted钩子函数')
}
// Child.vue
mounted(){
console.log('子组件触发mounted钩子函数')
}
以上输出顺序为 子组件触发mounted钩子函数 父组件监听到mounted钩子函数
10keep-alive是什么?
keep-alive是Vue提供给我们一个内置组件,他可以用来保存我们路由切换时组件的状态
组件使用keep-alive以后会新增两个生命周期 actived() deactived(),
我们在切换路由的时候,想保存组件的状态,比如列表页面进入详情,我们想保存列表滚动的位置,我们就可以##### 使用keep-alive保存列表页面的滚动位置。
怎么使用keep-alive,有两种方式,1. 路由配置 2. keep-alive参数
1. 全局保存在App.vue中 把包裹起来
2. 路由定义方式
1、router.js中设置要缓存的页面
```js
{
path: '/child1',
name: 'Child1',
component: Child1,
meta:{
keepAlive:true,//保存keep-alive状态
}
}
```
2、用v-if来显示router-view是否在keep-alive中出现
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
3. 使用keep-alive的标签属性, include() exclude()
<keep-alive inclue="list,detail" ></keep-alive>
include 包含标签名字被缓存 exclude 包含的标签不被缓存
##### 缓存名字组件中有个name属性进行定义即可
11.组件中的data为什么是一个函数
1.vue中组件是用来复用的,为了防止data复用,将其定义为函数。
2.vue组件中的data数据都应该是相互隔离,互不影响的,组件每复用一次,data数据就应该被复制一次,之后,当某一处复用的地方组件内data数据被改变时,其他复用地方组件的data数据不受影响,就需要通过data函数返回一个对象作为组件的状态。
3.当我们将组件中的data写成一个函数,数据以函数返回值形式定义,这样每复用一次组件,就会返回一份新的data,拥有自己的作用域,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据。
4.当我们组件的date单纯的写成对象形式,这些实例用的是同一个构造函数,由于JavaScript的特性所导致,所有的组件实例共用了一个data,就会造成一个变了全都会变的结果。
12.Vue中双向数据绑定是如何实现的
vue中的v-model可以实现双向绑定,其核心思想通过Object.definePropery来对Vue的数据进行数据劫持,
主要分为三部分
1.observer主要是负责对Vue数据进行数据劫持,使其数据拥有get和set方法
2.指令解析器负责绑定数据和指令,绑定试图更新方法
3.watcher负责数据监听,当数据发生改变通知订阅者,调用视图更新函数更新视图
13.父传递子如何传递
(1)在父组件的子组件标签上绑定一个属性,挂载要传输的变量
(2)在子组件中通过props来接受数据,props可以是数组也可以是对象,接受的数据可以直接使用 props:[“属性 名”] props:{属性名:数据类型}
14.子传递父如何传递
子传递父如何传递
(1)在父组件的子组件标签上自定义一个事件,然后调用需要的方法
(2)在子组件的方法中通过 this.$emit(“事件”)来触发在父组件中定义的事件,数据是以参数的形式进行传递的
15.兄弟组件如何通信
兄弟组件如何通信
(1)在src中新建一个Bus.js的文件,然后导出一个空的vue实例
(2)在传输数据的一方引入Bus.js 然后通过Bus. e m i t ( “ 事 件 名 ” , " 参 数 " ) 来 来 派 发 事 件 , 数 据 是 以 emit(“事件名”,"参数")来来派发事件,数据是以 emit(“事件名”,"参数")来来派发事件,数据是以emit()的参数形式来传递
(3)在接受的数据的一方 引入 Bus.js 然后通过 Bus.$on(“事件名”,(data)=>{data是接受的数据})
16.Vuex是什么?
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储和管理程序的所有组件的数据
在大型的程序中如果多个组件中用到的数据我们可以存储到vuex,如果小型项目我们可以适当的使用vuex
Vuex的核心概念及其作用
1、state 所有的数据都存储在state中 state是一个对象
2、mutations 可以直接操作state中的数据
3、actions 只能调用mutations的方法
4、getters 类似计算属性实现对state中的数据做一些逻辑性的操作
5、modules 将仓库分模块存储
17.简述MVVM和MVC
MVC:
Model(模型)
View(视图)
Controller(控制器)
简单的理解:视图请求数据,将请求发送至控制器,控制器再将请求发送给模型,模型去查找数据,找到之后传给控制器,控制器再传给视图进行渲染。
MVVM
Model 代表数据模型
View 代表UI视图
ViewModel 负责监听 Model 中数据的改变并且控制视图的更新(桥梁,可以理解成mvc中的控制器)
简单理解:视图请求数据,将请求发送至VModel,在Vmodel的两端具有监听机制,直接调用模型的数据,一端改变全部改变,利用数据劫持,结合订阅者和发布者模式,实现数据的双向绑定
18.proxy与Object.defineProperty优劣对比
Proxy的优势如下
1.Proxy可以直接监听对象 而非属性;
2.Proxy可以直接监听数组的变化
3.Proxy有多达13种拦截方法,不限于apply,ownKeys,deleteProperty,has等等,是Object.defineProperty不具备的
4.Proxy返回的是一个新对象,我们可以只操作新的对象达到目的,而Object.defineProperty只能遍历对象属性直接修改
19.你有对vue项目进行哪些优化?
1.代码层面的优化
- v-if和v-show区分场景使用
- computed和watch区分场景使用
- v-for遍历添加key,且避免同时使用v-if
- 长列表性能优化
- 事件的销毁
- 图片资源懒加载
- 路由懒加载
- 第三方插件按需引入
Webpack层面的优化
- Webpack对图片进行压缩
- 减少ES6转为ES5的冗余代码
- 提取公共代码
- 模板预编译
- 提取组件的css
- 优化SourceMap
- 构建结果输出分析
基础的Web技术的优化
- 开启gzip压缩
- 浏览器缓存
- CDN的使用
- 使用Chrome Performance查找性能瓶颈