目录
1.自我介绍
2.vue面试题
1.v-show和v-if区别的区别:
2.为何v-for要用key
3.描述vue组件声明周期mm
单组件声明周期图
父子组件生命周期图
4.vue组件如何通信
5.描述组件渲染和更新的过程
1、vue 组件初次渲染过程
2、vue 组件更新过程
6.双向数据绑定v-model的实现原理
7.对mvvm的理解
8.computed有何特性
9.VUE 中如何封装组件?什么组件,为什么要封装组件?组件中 data 为什么是一个函数?
为什么要封装组件?
什么是组件?
10.ajax请求应该放在哪个生命周期?
11.如何将组件所有props传递给子组件?
12.如何自定实现v-model?
13.多个组件有相同逻辑,如何抽离?
14.何时要使用异步组件?
15.何时使用keep-alive?
16.何时使用beforeDestroy?
17.什么是作用域插槽?
18.vuex中action和mutation有何区别?
19.vue-router常用路由模式
20.如何配置vue-router异步加载
21.请用vnode描述一个dom结构
22.监听data变化的核心api是什么?
23.vue如何监听数据变化?
24.请描述响应式原理?
25.简述diff算法过程(了解)
26.vue为何是异步渲染,$nextTick何用?
27.vue常见性能优化方式?
1.合理使用v-if和v-show,
2.合理使用computed,
3.v-for加key,
4.自定义事件,dom事件及时销毁,
5.合理使用异步组件,
6.合理使用keepalive,
7.data层级不要太深,
8.使用vue-loader在开发环境做模板编译,
9.前端通用性能优化(如图片懒加载/减少 HTTP请求数/合理设置 HTTP缓存/资源合并与压缩/合并 CSS图片/将 CSS放在 head中/避免重复的资源请求/切分到多个域名),
10.使用ssr
28、VUEX 是什么?怎么使用?那种场合能用?
29、vue 的指令用法
30、vue.js的两个核心是什么?
31.vue中子组件调用父组件的方法?
32.vue中父组件调用子组件的方法?
33.vue页面级组件之间传值?
34.说说vue的动态组件。
35.$route和 $router的区别是什么?
36.为什么使用vue开发?
37.vue和react 有什么区别?
38.Vuex和Redux的区别
mvvm和mvc理解 与区别?
39.说一下vue的生命周期/钩子函数都有哪些?
40.双向数据绑定的理解?
41.vue组件中data为什么函数返回一个对象
42.vue中哪些数组方法可以直接对数组修改实现视图更新
43.有哪些指令?v-if和v-show区别,v-if、v-for优先级
44.v-for中key 的作用
45.使用过keep-alive吗
46.computed、watch(自动监听、深度监听)、methods区别
47.vue中对象更改检测的注意事项
48.什么是$nextTick?
49.ref 的作用?
50.什么是vuex?vuex核心包括?怎么修改state中数据?在项目中哪里使用?
51.路由模式有哪些?路由传参有哪些方式?路由守卫有哪些,有没有在项目中使用过?
52.vue过滤器
1. 全局过滤器
2.局部过滤器
53.有没有封装过组件,封装过什么,怎么封装?注意点或有哪些原则?
55.有没有使用过axios、axios拦截器,跨域如何解决?
56.vue项目做过哪些优化
57.为什么做首屏优化?
58.如何做首屏优化?
60.v-on可以监听多个方法吗?
61.vue中编写可复用的组件(深度好题,掌握思路,不用背诵)
62.vue如何监听键盘事件中的按键?(大声朗读2遍)
64.v-for产生的列表,实现active的切换 tab切换
65.v-model语法糖使用
66.十个常用的自定义过滤器
67.vue等单页面应用及其优缺点
68.vue的计算属性,特性,应用
70.vue-cli生产环境使用全局常量(了解)
71.vue弹窗后如何禁止滚动条滚动?(了解)
72.vue-cli中自定义指令的使用
73.父组件异步获取动态数据传递给子组件(好题)
74.父组件给子组件props传参,子组件接收的6种方法
75.Vuex页面刷新数据丢失咋解决这个bug
解决思路1:
解决方法2:
76.按钮权限怎么做?
77.完整的说下从url解析到显示页面过程,结合项目中说
78.vue声明周期都在哪些场景中使用?
1.自我介绍
2分钟,200-300个字,主旨自己基本情况,工作经历,优点,兴趣爱好,职业规划,邀约
2.vue面试题
1.v-show和v-if区别的区别:
v-show通过css display控制显示和隐藏,v-if组件真正的渲染和销毁,而不是显示和隐藏,频繁切换状态使用v-show 否则v-if
2.为何v-for要用key
快速查找到节点,减少渲染次数,提升渲染性能
3.描述vue组件声明周期mm
单组件声明周期图
挂载: beforeCreate => created => beforeMount => mounted
更新: beforeUpdate => updated
销毁: beforeDestroy => destroyed
父子组件生命周期图
挂载: parent beforeCreate => parent created => parent beforeMount => child beforeCreate => child created => child beforeMount => child mounted => parent mounted
更新: parent beforeUpdate => child beforeUpdate => child updated => parent updated
销毁: parent beforeDestroy => child beforeDestroy => child destroyed => parent destroyed
从以上能够看出:
挂载时,子组件是在父组件before mount后开始挂载,并且子组件先mounted,父组件随后
更新时,子组件是在父组件before update后开始更新,子组件先于父组件更新
销毁时,子组件是在父组件before destroy后开始销毁,并且是子组件先销毁,父组件随后。
4.vue组件如何通信
1.父子组件props和this.$emit
2.ref 链:父组件要给子组件传值,在子组件上定义一个 ref 属性,这样通过父组件的 $refs 属性就可以获取子组件的值了,也可以进行父子,兄弟之间的传值($parent / $children与 ref类似)
3.事件总线bus:使用一个 空的 VUE 实例作为事件总线,自定义事件event.$on event.$off event.$emit
4 provide inject组件通信
5.vuex
6.$attrs和$listeners 仅仅是传递数据,而不做中间处理,$attrs 里存放的是父组件中绑定的非 Props 属性,$listeners里存放的是父组件中绑定的非原生事件。
常见使用场景可以分为三类:
父子通信:
父向子传递数据是通过 props,子向父是通过 events($emit);
通过父链 / 子链也可以通信($parent / $children);
ref 也可以访问组件实例;
provide / inject API;
$attrs/$listeners
vuex
兄弟通信:
事件总线Bus;
Vuex
跨级通信:
事件总线Bus;
Vuex;
provide / inject API
$attrs/$listeners
5.描述组件渲染和更新的过程
1、vue 组件初次渲染过程
解析模板为 render 函数
触发响应式,监听 data 属性的 getter 和 setter
执行 render 函数, 生成 vnode,patch(elem,vnode)
2、vue 组件更新过程
修改 data, 触发 setter (此前在getter中已被监听)
重新执行 render 函数,生成 newVnode,patch(vnode, newVnode)
6.双向数据绑定v-model的实现原理
双向数据绑定最核心的方法便是通过Object.defineProperty()来实现对属性的劫持,达到监听数据变动的目的.
先是从data里面的数据msg通过绑定到input控件和p标签上。然后input上通过v-on:input监听控件,触发change()。
调用方法都可以默认获取e事件,e.target.value是获取调用该方法的DOM对象的value值。把value值在赋给data里的msg,就是实现了双向数据绑定的原理了。
7.对mvvm的理解
m->model,v->view,vm->viewModel。dom通过监听事件操作vue里的data,反之vue中的data通过指令操作dom,这就是所说数据驱动视图,这就是mvvm的理解。
8.computed有何特性
缓存,data不变不会重新计算,提高性能
9.VUE 中如何封装组件?什么组件,为什么要封装组件?组件中 data 为什么是一个函数?
为什么要封装组件?
主要就是为了解耦,提高代码复用率。
什么是组件?
页面上可以复用的都称之为组件 它是 HTML、CSS、JS 的聚合体。
组件就相当于库,把一些能在项目里或者不同项目里可以复用的代码进行需求性的封装。
组件中的 data 为什么是一个函数?
让每个返回的实例都可以维护一份被返回对象的独立的拷贝。
10.ajax请求应该放在哪个生命周期?
mounted,因为js是单线程,ajax异步获取数据
11.如何将组件所有props传递给子组件?
父组件绑定一个自定义属性变量,然后子组件通过props使用这个变量即可。
12.如何自定实现v-model?
我们定义了model对象。model对象包含两个属性,一个是prop,一个是event。prop值text1,event的值change1,我们这里写model是为了改变默认的东西,使用我们自己定义的变量。
<input type="text" :value="text1" @input="$emit('change1', $event.target.value)" >
13.多个组件有相同逻辑,如何抽离?
使用mixin 对公共部分的逻辑进行抽离
14.何时要使用异步组件?
加载大组件,路由异步加载
15.何时使用keep-alive?
缓存组件不需要重复渲染,多个静态tab页切换,优化性能
16.何时使用beforeDestroy?
1.解绑自定义事件event.$off
2.清除定时器
3.解绑自定义dom事件,如windom.scroll等
17.什么是作用域插槽?
在solt组件中有自己的data,把它传给使用的地方
18.vuex中action和mutation有何区别?
action中处理异步,mutation不可以
mutation做原子操作,action2可以整合多个mutation
19.vue-router常用路由模式
hash默认,h5 histroy需要服务端支持
20.如何配置vue-router异步加载
component:() => import('./component')
21.请用vnode描述一个dom结构
<ul id='test'>
<p class='hehe'>这里是p标签</p>
<li>{{1+1}}</li>
</ul>
let vdom={
tag:'ul',
props:{
id:'test'
},
children:[
{
tag:'p',
props:{
class:'hehe'
},
children:'这里是p标签'
},
{
tag:'li',
children:1
}
]
}
22.监听data变化的核心api是什么?
vue2.0核心api是Object.defineProperty,vue3.0是启用provy实现响应式
23.vue如何监听数据变化?
vue中的watch监听数据变化
24.请描述响应式原理?
1.描述监听data变化
监听对象变化:vue2.0核心api是Object.defineProperty,vue3.0是启用provy实现响应式
监听数组变化:重写数组的push.pop.shift.unshift.splice.sort.reverse方法
2.组件渲染和更新的过程(面试题5)
25.简述diff算法过程(了解)
在执行Diff算法的过程就是调用名为 patch 的函数,比较新旧节点。一边比较一边给真实的 DOM 打补丁。patch 函数接收两个参数 oldVnode 和 Vnode,它们分别代表新的节点和之前的旧节点。这个patch函数会比较 oldVnode 和 vnode 是否是相同的, 即函数 sameVnode(oldVnode, vnode), 根据这个函数的返回结果分如下两种情况:
true:则执行 patchVnode
false:则用 vnode 替换 oldVnode
//对比过程
找到对应的真实 dom,称为 el
判断 vnode 和 oldVnode 是否指向同一个对象。
如果是,那么直接 return。
如果他们都有文本节点并且不相等,那么将 el 的文本节点设置为 vnode 的文本节点。
如果 oldVnode 有子节点而 vnode 没有,则删除 el 的子节点。
如果 oldVnode 没有子节点而 vnode 有,则将 vnode 的子节点真实化之后添加到 el
如果两者都有子节点,则执行 updateChildren 函数比较子节点。
26.vue为何是异步渲染,$nextTick何用?
因为如果不采用异步更新,那么每次更新数据都会对当前组件进行重新渲染,所以考虑性能问题,Vue会在本轮数据更新之后,再去异步更新视图
$nextTick 是在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后使用 $nextTick,则可以在回调中获取更新后的 DOM
27.vue常见性能优化方式?
1.合理使用v-if和v-show,
2.合理使用computed,
3.v-for加key,
4.自定义事件,dom事件及时销毁,
5.合理使用异步组件,
6.合理使用keepalive,
7.data层级不要太深,
8.使用vue-loader在开发环境做模板编译,
9.前端通用性能优化(如图片懒加载/减少 HTTP请求数/合理设置 HTTP缓存/资源合并与压缩/合并 CSS图片/将 CSS放在 head中/避免重复的资源请求/切分到多个域名),
10.使用ssr
28、VUEX 是什么?怎么使用?那种场合能用?
vuex 是一个专门为 vue 构建的状态管理工具,主要是为了解决 多组间之间状态共享问题。强调的是集中式管理,(组件与组件之间的关系变成了组件与仓库之间的关系)
vuex 的核心包括:state(存放状态)、mutations(同步的更改状态)、actions(发送异步请求,拿到数据)、getters(根据之前的状态派发新的状态)、modules(模块划分)
state 发布一条新的数据,在 getters 里面根据状态派发新的状态,actions 发送异步请求获取数据,然后在 mutations 里面同步的更改数据
应用场合:购物车的数据共享、登入注册
29、vue 的指令用法
v-html //html
v-text //元素里要显示的内容
v-bind:data //绑定动态数据 :data
v-on:click //绑定事件 @click
v-for
v-if //条件渲染指令
v-model //双向绑定,用于表单
30、vue.js的两个核心是什么?
数据驱动和组件化
31.vue中子组件调用父组件的方法?
1.直接在子组件中通过this.$parent.event来调用父组件的方法。
2.在子组件里用$emit向父组件触发一个事件,父组件监听这个事件就行了。
3.父组件把方法传入子组件中,在子组件里直接调用这个方法。
32.vue中父组件调用子组件的方法?
父组件利用ref属性操作子组件方法。
父:
<child ref="childMethod"></child>
子:
method: {
test() {
alert(1)
}
}
在父组件里调用test即 this.$refs.childMethod.test()
33.vue页面级组件之间传值?
1.使用vue-router通过跳转链接带参数传参。
2.使用本地缓存localStorge。
3.使用vuex数据管理传值
34.说说vue的动态组件。
多个组件通过同一个挂载点进行组件的切换,is的值是哪个组件的名称,那么页面就会显示哪个组件。
35.$route和 $router的区别是什么?
$router为VueRouter的实例,是一个全局路由对象,包含了路由跳转的方法、钩子函数等。
$route 是路由信息对象||跳转的路由对象,每一个路由都会有一个route对象,是一个局部对象,包含path,params,hash,query,fullPath,matched,name等路由信息参数。
36.为什么使用vue开发?
组件化开发 单页面路由 丰富的Api方法 双向的数据绑定 单向数据流 易于结合其他第三库
37.vue和react 有什么区别?
1、监听数据变化的实现原理不同**
2、数据流的不同**
3、HoC和mixins**
4、组件通信的区别**
5、模板渲染方式的不同**
6、渲染过程不同**
7、框架本质不同**
38.Vuex和Redux的区别
mvvm和mvc理解 与区别?
View 将请求转交---> Controlle 处理 --->Model数据更新保存 ----->View视图显示
View 接受用户交互请求
View 将请求转交给Controller处理
Controller 操作Model进行数据更新保存
数据更新保存之后,Model会通知View更新
View 更新变化数据使用户得到反馈
MVVM即Model-View-ViewModel,将其中的 View 的状态和行为抽象化,让我们可以将UI和业务逻辑分开。MVVM的优点是低耦合、可重用性、独立开发。
View 接收用户交互请求
View 将请求转交给ViewModel
ViewModel 操作Model数据更新
Model 更新完数据,通知ViewModel数据发生变化
ViewModel 更新View数据
39.说一下vue的生命周期/钩子函数都有哪些?
单组件声明周期图
挂载: beforeCreate => created => beforeMount => mounted
更新: beforeUpdate => updated
销毁: beforeDestroy => destroyed
父子组件生命周期图
挂载: parent beforeCreate => parent created => parent beforeMount => child beforeCreate => child created => child beforeMount => child mounted => parent mounted
更新: parent beforeUpdate => child beforeUpdate => child updated => parent updated
销毁: parent beforeDestroy => child beforeDestroy => child destroyed => parent destroyed
从以上能够看出:
挂载时,子组件是在父组件before mount后开始挂载,并且子组件先mounted,父组件随后
更新时,子组件是在父组件before update后开始更新,子组件先于父组件更新
销毁时,子组件是在父组件before destroy后开始销毁,并且是子组件先销毁,父组件随后。
钩子函数有三种 ,也叫路由守卫
全局导航钩子(跳转前进行判断拦截) 全局路由守卫
router.beforeEach(to, from, next),全局前置守卫
router.beforeResolve(to, from, next),全局的解析守卫
router.afterEach(to, from ,next) 全局的后置守卫
组件内钩子 路由独享的守卫
beforeRouteEnter
beforeRouteUpdate
beforeRouteLeave
单独路由独享组件
beforeEnter 组件内的守卫
40.双向数据绑定的理解?
vue采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty劫持data属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
41.vue组件中data为什么函数返回一个对象
组件中的data写成一个函数,数据以函数返回值形式定义,这样每复用一次组件,就会返回一份新的data。如果单纯的写成对象形式,就使得所有组件实例共用了一份data,造成了数据污染。
42.vue中哪些数组方法可以直接对数组修改实现视图更新
push() pop() shift() unshift() splice() sort() reverse() vue数组对象修改触发视图更新
43.有哪些指令?v-if和v-show区别,v-if、v-for优先级
v-html //html
v-text //元素里要显示的内容
v-bind:data //绑定动态数据 :data
v-on:click //绑定事件 @click
v-for
v-if //条件渲染指令
v-model //双向绑定,用于表单
v-show通过css display控制显示和隐藏,v-if组件真正的渲染好饿销毁,而不是显示和隐藏,频繁切换状态使用v-show 否则v-if
v-for和v-if不应该一起使用,必要情况下应该替换成computed属性。原因:v-for比v-if优先,如果每一次都需要遍历整个数组,将会影响速度,尤其是当之需要渲染很小一部分的时候。
44.v-for中key 的作用
快速查找到节点,减少渲染次数,提升渲染性能
45.使用过keep-alive吗
keep-alive缓存vue实例,提高性能是 Vue 内置的一个组件,可以使被包含的组件保留状态,避免重新渲染 ,
提供 include 和 exclude 属性,两者都支持字符串或正则表达式, include 表示只有名称匹配的组件会被缓存,exclude 表示任何名称匹配的组件都不会被缓存 ,其中 exclude 的优先级比 include 高;
对应两个钩子函数 activated 和 deactivated ,当组件被激活时,触发钩子函数 activated,当组件被移除时,触发钩子函数 deactivated。
46.computed、watch(自动监听、深度监听)、methods区别
我们可以将同一函数定义为一个 method 或者一个计算属性。对于最终的结果,两种方式是相同的。
不同点:
computed:计算属性是基于它们的依赖进行缓存的,只有在它的相关依赖发生改变时才会重新求值。
methods:只要发生重新渲染, method 调用总会执行该函数。
watch监听对象需要深度监听,默认是浅监听
当页面中有某些数据依赖其他数据进行变动的时候,可以使用计算属性computed。
watch用于观察和监听页面上的vue实例,如果要在数据变化的同时进行异步操作或者是比较大的开销,那么watch为最佳选择。
47.vue中对象更改检测的注意事项
由于 JavaScript 的限制,Vue 不能检测对象属性的添加或删除:
对于已经创建的实例,Vue 不能动态添加根级别的响应式属性。但是,可以使用 `Vue.set(object, key, value)`方法向嵌套对象`添加响应式属性`。为已有对象赋予多个新属性,比如使用 `Object.assign()`或 `_.extend()`。在这种情况下,你应该用两个对象的属性创建一个新的对象。
48.什么是$nextTick?
场景:vue是异步渲染的框架,react也是,data改变之后,dom不会立刻渲染,$nextTick会在dom渲染之后被触发,以获取最新dom节点
49.ref 的作用?
获取dom元素 this.$refs.box
获取子组件中的data this.$refs.box.msg
调用子组件中的方法 this.$refs.box.open()
50.什么是vuex?vuex核心包括?怎么修改state中数据?在项目中哪里使用?
vuex 是一个专门为 vue 构建的状态管理工具,主要是为了解决 多组间之间状态共享问题。强调的是集中式管理,(组件与组件之间的关系变成了组件与仓库之间的关系)
vuex 的核心包括:state(存放状态)、mutations(同步的更改状态)、actions(发送异步请求,拿到数据)、getters(根据之前的状态派发新的状态)、modules(模块划分)
state 发布一条新的数据,在 getters 里面根据状态派发新的状态,actions 发送异步请求获取数据,然后在 mutations 里面同步的更改数据
应用场合:购物车的数据共享、登入注册
51.路由模式有哪些?路由传参有哪些方式?路由守卫有哪些,有没有在项目中使用过?
hash模式(默认) 例如:http://abc.com/#/user/10
h5 history模式 例如:http://abc.com/user/20 需要server端支持
注意:history有如下问题 404
路由传参方法?
query传参和params传参
1、声明式导航
不带参跳转 对应的地址为/foo
url字符串拼接传参 对应的地址为/foo?id=123
query方式对象形式传参 对应的地址为/foo?id=123
params方式对象形式传参 对应地址为 /path/123 , 注意params和query一起使用params会失效,params与name一起使用
2、编程式导航(路由实例对象router=new VueRouter())
字符串router.push('home')
对象router.push({ path: 'home' })
命名的路由 对应路径为/path/123
router.push({ name: 'user', params: { userId: '123' }})
带查询参数,变成 /register?plan=123
router.push({ path: 'register', query: { plan: '123' }})
接收参数
this.$route.params.id
this.$route.query.xxx
52.vue过滤器
过滤器是将后台返回的数据换一种形式输出,不改变原来的数据 应用场景:后台返回的状态码(性别,支付状态),商品价格
1. 全局过滤器
Vue.filter('过滤器',对应的过滤器函数)
2.局部过滤器
通过在Vue实例上挂载filers添加过滤器,只能在当前组件内部使用
53.有没有封装过组件,封装过什么,怎么封装?注意点或有哪些原则?
怎么封装:
● 首先,使用Vue.extend()创建一个组件
● 然后,使用Vue.component()方法注册组件
● 接着,如果子组件需要数据,可以在props中接受定义
● 最后,子组件修改好数据之后,想把数据传递给父组件,可以使用emit()方法
注意点或有哪些原则?
data数据结构设计,或者问有哪些原则
原则:
1.用数据描述所有的内容
2.数据要结构化,易于程序操作,遍历,查找
3.数据要可扩展,以便增加新的功能
组件如何设计,有什么原则
原则:
1.从功能上拆分层次
2.尽量让组件原子化,一个组件只做一件事情
3.容器组件(只管数据,一般是顶级组件)和展示组件(只管显示视图)
54.移动端项目如何适配(rem)?
css3规定:1rem的大小就是根元素<html>的font-size的值。
通过设置 根元素<html>的font-size的大小,来控制整个html文档内的字体大小、元素宽高、内外边距等,
根据移动设备的宽度大小来实现自适应,不同的设备都展示一致的页面效果。
rem布局简单分析 分三步:
第一步:前端开发者首先拿到UI设计原型稿的宽度,750宽度,如 320px 或者640px或者750px;
第二步:增加脚本(设置根元素<html>字体大小)
第三步:css中使用rem单位;关键点:字体大小,元素宽高,内外边距一定是根据设计稿测量得来的。
55.有没有使用过axios、axios拦截器,跨域如何解决?
axios拦截器:
// 添加请求拦截器
axios.interceptors.request.use
// 添加响应拦截器
axios.interceptors.response.use
跨域特别注意两点:
第一,如果是协议和端口造成的跨域问题“前台”是无能为力的,
第二:在跨域问题上,域仅仅是通过“URL的首部”来识别而不会去尝试判断相同的ip地址对应着两个域或两个域是否在同一个ip上。
vue如何解决跨域:
proxyTable 这里vue脚手架生成的标准项目为准。一般在项目config目录下面有个index文件
CORS CORS即跨源资源共享,它定义了一种浏览器和服务器交互的方式来确定是否允许跨域请求。
Nginx 当我们明白跨越的含义之后。只要解决了'源'的问题。那么跨越也就不存在了
56.vue项目做过哪些优化
(1)代码层面的优化
v-if 和 v-show 区分使用场景
computed 和 watch 区分使用场景
v-for 遍历必须为 item 添加 key,且避免同时使用 v-if
长列表性能优化
事件的销毁 addEventlisenter 事件监听
图片资源懒加载
路由懒加载
第三方插件的按需引入
优化无限列表性能
服务端渲染 SSR or 预渲染
(2)Webpack 层面的优化
Webpack 对图片进行压缩
减少 ES6 转为 ES5 的冗余代码
提取公共代码
模板预编译
提取组件的 CSS
优化 SourceMap
构建结果输出分析
Vue 项目的编译优化
(3)基础的 Web 技术的优化
开启 gzip 压缩
浏览器缓存
CDN 的使用
使用 Chrome Performance 查找性能瓶颈
57.为什么做首屏优化?
首屏时间的快与慢,直接影响到了用户对网站的认知度。所以首屏时间的长短对于用户的滞留时间的长短、用户转化率都尤为重要。
58.如何做首屏优化?
css模块化加载,对应模块下的css交给js或jsonp请求返回
js懒执行,有交互才执行
图片在其他屏(非首屏)都采用懒加载的模式,这样既能节省流量,也能减少请求数或延迟请求数。
服务器方面:
1. 少量静态文件的域名,图片与iconfont均是放在同一个域下,减少DNS的解析事件,最好做到域名收敛。
2. 模块化接口的支持。
3. 首屏内容最好做到静态缓存
4. 对于vue和react做ssr
59.vue常用的修饰符
.stop - 调用 event.stopPropagation(),禁止事件冒泡。
.prevent - 调用 event.preventDefault(),阻止事件默认行为。
.capture - 添加事件侦听器时使用 capture 模式。
.self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
.native - 监听组件根元素的原生事件。
.once - 只触发一次回调。
v-model 指令常用修饰符:
.number - 输入字符串转为数字
.trim - 输入首尾空格过滤
.lazy
60.v-on可以监听多个方法吗?
v-on可以监听多个方法,但是同一种事件类型的方法,vue-cli工程会报错
61.vue中编写可复用的组件(深度好题,掌握思路,不用背诵)
1.在 Vue 组件中,状态称为 props,事件称为 events,片段称为 slots。
Props 允许外部环境传递数据给组件
Events 允许组件触发外部环境的副作用 $emit
Slots 允许外部环境将额外的内容组合在组件中。
组件的构成部分也可以理解为组件对外的接口。良好的可复用组件应当定义一个清晰的公开接口。
2.组件间通信
在 Vue.js 中,父子组件的关系可以总结为 props down, events up 。父组件通过 props 向下传递数据给子组件,子组件通过 events 给父组件发送消息。
3.命名
组件的命名应该跟业务无关。应该依据组件的功能为组件命名。
4.业务数据无关
可复用组件只负责 UI 上的展示和一些交互以及动画,如何获取数据跟它无关,因此不要在组件内部去获取数据,以及任何与服务端打交道的操作。可复用组件只实现 UI 相关的功能。
5.组件职责
约束好组件的职责,能让组件更好地解耦,知道什么功能是组件实现的,什么功能不需要实现。
组件可以分为通用组件(可复用组件)和业务组件(一次性组件)。
可复用组件实现通用的功能(不会因组件使用的位置、场景而变化):
UI 的展示
与用户的交互(事件)
动画效果
业务组件实现偏业务化的功能:
获取数据
和 vuex 相关的操作
埋点
引用可复用组件
可复用组件应尽量减少对外部条件的依赖,所有与 vuex 相关的操作都不应在可复用组件中出现。
组件应当避免对其父组件的依赖,不要通过 this.$parent 来操作父组件的示例。父组件也不要通过 this.$children 来引用子组件的示例,而是通过子组件的接口与之交互。
6.命名空间
可复用组件除了定义一个清晰的公开接口外,还需要有命名空间。 modules
命名空间可以避免与浏览器保留标签和其他组件的冲突。特别是当项目引用外部 UI 组件或组件迁移到其他项目时,命名空间可以避免很多命名冲突的问题。
7.上下文无关
还是上面那句话,可复用组件应尽量减少对外部条件的依赖。没有特别需求且单个组件不至于过重的的前提下,不要把一个有独立功能的组件拆分成若干个小组件。
8.数据扁平化
每个 prop 应该是一个简单类型的数据。这样做有下列几点好处:
组件接口清晰
props 校验方便
当服务端返回的对象中的 key 名称与组件接口不一样时,不需要重新构造一个对象
9.使用自定义事件实现数据的双向绑定 v-model
有时候,对于一个状态,需要同时从组件内部和组件外部去改变它。
:value oninput
例如,模态框的显示和隐藏,父组件可以初始化模态框的显示,模态框组件内部的关闭按钮可以让其隐藏。一个好的办法是,使用自定义事件改变父组件中的值
10.使用自定义 watch 优化 DOM 操作
在开发中,有些逻辑无法使用数据绑定,无法避免需要对 DOM 的操作。例如,视频的播放需要同步 Video 对象的播放操作及组件内的播放状态。可以使用自定义 watch 来优化 DOM 的操作。
11.项目骨架
单组件不异过重,组件在功能独立的前提下应该尽量简单,越简单的组件可复用性越强。当你实现组件的代码,不包括CSS,有好几百行了(这个大小视业务而定),那么就要考虑拆分成更小的组件。
62.vue如何监听键盘事件中的按键?(大声朗读2遍)
在我们的项目经常需要监听一些键盘事件来触发程序的执行,而Vue中允许在监听的时候添加关键修饰符:
<input v-on:keyup.13="submit">
对于一些常用键,还提供了按键别名:
<input v-on:keyup.13="submit">
全部的按键别名:
.enter
.tab
.delete (捕获“删除”和“退格”键)
.esc
.space
.up
.down
.left
.right
修饰键:
.ctrl
.alt
.shift
.meta
与按键别名不同的是,修饰键和 keyup 事件一起用时,事件引发时必须按下正常的按键。换一种说法:如果要引发 keyup.ctrl,必须按下 ctrl 时释放其他的按键;单单释放 ctrl 不会引发事件
<!-- 按下Alt + 释放C触发 -->
<input @keyup.alt.67="clear">
<!-- 按下Alt + 释放任意键触发 -->
<input @keyup.alt="other">
<!-- 按下Ctrl + enter时触发 -->
<input @keydown.ctrl.13="submit">
对于elementUI的input,我们需要在后面加上.native, 因为elementUI对input进行了封装,原生的事件不起作用。
<input v-model="form.name" placeholder="昵称" @keyup.enter="submit">
<el-input v-model="form.name" placeholder="昵称" @keyup.enter.native="submit"></el-input>
63.解决非工程化项目初始化页面闪动问题(好题,理解)
vue页面在加载的时候闪烁花括号{},v-cloak指令和css规则如[v-cloak]{display:none}一起用时,这个指令可以隐藏未编译的Mustache标签直到实例准备完毕。{{name}} data: name:''
/*css样式*/
[v-cloak] {
display: none;
}
<!--html代码-->
<div id="app" v-cloak>
<ul>
<li v-for="item in tabs">{{item.text}}</li>
</ul>
</div>
64.v-for产生的列表,实现active的切换 tab切换
v-for生成序列
<ul>
<li v-for="(info,index) in list" :key="info.id" @click="select(index)" v-bind:class="{'active':info.active}">{{info.name}}</li>
</ul>
data数据
list:[
{
name:'a',
id:1,
active:false
},
{
name:'b',
id:2,
active:false
},
{
name:'c',
id:3,
active:false
},
{
name:'d',
id:4,
active:false
},
]
点击事件
select(d){
this.list.map(s=>s.active=false); //for forEach map filter some
this.list[d].active=true;
},
CSS样式
<style scoped>
li.active{
background-color: red;
}
65.v-model语法糖使用
v-model语法糖 v-model其实是一种简写方式,我们常见的有两种v-model,分别是input元素上的v-model 和非input元素上v-model
input元素上的:
<input v-model="price"><!-- 下行的语法糖 -->
<input :value="price" @input="price = $event.target.value">
data(){
return {
price: 20
}
}
非input元素上的:
Vue.component('base-checkbox', {
model: {
prop: 'checked',
event: 'change'
},
template: `
<input
type="checkbox"
v-bind:checked="checked"
v-on:change="$emit('change', $event.target.checked)"
>
`
})
父组件:<base-checkbox v-model="lovingVue"></base-checkbox>
66.十个常用的自定义过滤器
(1)去除空格
type:1-所有空格 2-前后空格 3-前空格 4-后空格。
(2)任意格式日期处理
(3)字母大小写切换
type:1:首字母大写 2:首页母小写 3:大小写转换 4:全部大写 5:全部小写
(4)字符串循环复制,count->次数.
(5)字符串替换
(6)字符替换*,隐藏手机号或者身份证号等
(7)格式化处理字符串
(8)现金额大写转换函数
(9)保留2位小数 0.3 + 0.9 != 1.2
(10)补零
67.vue等单页面应用及其优缺点
单页面应用(SPA),通俗一点说就是指只有一个主页面的应用
单页面的优点:
用户体验好,快,内容的改变不需要重新加载整个页面,基于这一点spa对服务器压力较小。
前后端分离。
效果会比较炫酷(比如切换页面内容时的专场动画)。
单页面缺点:
不利于seo。
导航不可用,如果一定要导航需要自行实现前进、后退。(由于是单页面不能用浏览器的前进后退功能,所以需要自己建立堆栈管理)。
初次加载时耗时多。
页面复杂度提高很多。
68.vue的计算属性,特性,应用
含义:computed 是计算属性,把模板中的一些稍微复杂的逻辑计算放回到js代码中,解决在模板中放入太多的逻辑会让模板过重且难以维护的问题。
computed特性:
(1)computed 是基于它们的依赖进行缓存的
(2)只有在它的相关依赖发生改变时才会重新求值
computed应用:就是简化tempalte里面{{}}计算和处理props或$emit的传值
69.vue父组件向子组件通过props传递数据
父组件传递:
<子组件调用 v-bind:自定义属性名="要传递的数据"></子组件调用>
子组件接收:
props:['自定义属性名']
props:{
type:String,
default{
return ''
}
}
70.vue-cli生产环境使用全局常量(了解)
第一步,在 static 下新建 config.js:
第二步,在 config.js 里面设置全局变量:
第三步,在 index.html 里面引入:
第四步,在其他 .js 文件中即可使用:
第五步,打包后修改:通过 `npm run build` 命令打包后,此 config.js 文件会被打包到 `dist/static`文件夹下,此时如果需要修改 `PUBLIC_IP`,打开`config.js`即可修改,无需重新打包!
71.vue弹窗后如何禁止滚动条滚动?(了解)
1.在有弹出框的页面中,加上以下方法,弹出框出现时调用禁止滚动方法stopScroll(),弹出框去掉是调取允许滚动方法canScroll()即可,代码如下
methods : {
//禁止滚动
stopScroll(){
var mo=function(e){e.preventDefault();};
document.body.style.overflow='hidden';
document.addEventListener("touchmove",mo,false);//禁止页面滑动
},
/***取消滑动限制***/
canScroll(){
var mo=function(e){e.preventDefault();};
document.body.style.overflow='';//出现滚动条
document.removeEventListener("touchmove",mo,false);
}
}
2.在全局js即main.js中,设置全局函数,在使用到的页面分别调用即可,代码如下:
//弹出框禁止滑动
Vue.prototype.stopScroll = function () {
var mo = function (e) { e.preventDefault() }
document.body.style.overflow = 'hidden'
document.addEventListener('touchmove', mo, false)// 禁止页面滑动
}
//弹出框可以滑动
Vue.prototype.canScroll = function () {
var mo = function (e) {
e.preventDefault()
}
document.body.style.overflow = ''// 出现滚动条
document.removeEventListener('touchmove', mo, false)
}
具体页面的调用方法如下:
//当需要禁止弹出框底部内容滑动时调用:
this.stopScroll()
//当需要页面恢复滑动功能时调用:
this.canScroll()
72.vue-cli中自定义指令的使用
1.全局注册
Vue.directive(‘name’, {})
2.局部注册
directives: {
name: {}
}
然后在模版中直接使用即可。
73.父组件异步获取动态数据传递给子组件(好题)
问题:由于父组件中的数据是异步获取的,而子组件在一开始便会渲染,所以会造成子组件渲染完成后,数据还未获取到的情况
解决方案:在子组件渲染前,判断父组件数据是否获取完成,数据获取完成后再渲染子组件.
//tab-weekly(v-if="userId", :userId="userId")
//tab-weekly是子组件,userId是在父组件中异步获取、需要传递给子组件tab-weekly的数据,在其中加一个判断,//当userId存在后,再渲染子组件
74.父组件给子组件props传参,子组件接收的6种方法
1. data中 变量 = this.props里面的数据
2. watch监听 赋值
3. mounted 渲染完成后调用一个函数 进行赋值
4. vuex
5. computed 计算属性,用法和watch类似,computed是同步,watch可以异步
6. 父组件v-if 触发渲染和销毁,子组件触发传参
75.Vuex页面刷新数据丢失咋解决这个bug
问题:F5页面刷新,页面销毁之前的资源,重新请求,因此写在生命周期里的vuex数据是重新初始化,无法获取的,这也就是为什么会打印出空的原因。
解决思路1:
使用Localstorage sessionStorage 或cookie
实际使用时当vuex值变化时,F5刷新页面,vuex数据重置为初始状态,所以还是要用到localStorage,
解决方法2:
插件vuex-persistedstate
vuex-persistedstate默认持久化所有state,可以指定需要持久化的state
76.按钮权限怎么做?
在点击左侧菜单,存储全部权限,每次点击单个时候,去计算获取当前页面的按钮权限,封装一个button组件,然后在需要的地方引用
77.完整的说下从url解析到显示页面过程,结合项目中说
1. 首先浏览器主进程接管,开了一个下载线程。
2. 然后进行HTTP请求(DNS查询、IP寻址等等),中间会有三次捂手,等待响应,开始下载响应报文。
3. 将下载完的内容转交给Renderer进程管理。
4. Renderer进程开始解析css rule tree和dom tree,这两个过程是并行的,所以一般我会把link标签放在页面顶部。
5. 解析绘制过程中,当浏览器遇到link标签或者script、img等标签,浏览器会去下载这些内容,遇到时候缓存的使用缓存,不适用缓存的重新下载资源。
6. css rule tree和dom tree生成完了之后,开始合成render tree,这个时候浏览器会进行layout,开始计算每一个节点的位置,然后进行绘制。
7. 绘制结束后,关闭TCP连接,过程有四次挥手
78.vue声明周期都在哪些场景中使用?
1.beforeCreate(){}
创建前,访问不到data当中的属性以及methods当中的属性和方法,可以在当前生命周期创建一个loading,在页面加载完成之后将loading移除
2.created(){}
创建后,当前生命周期执行的时候会遍历data中所有的属性,给每一个属性都添加一个getter、setter方法,将data中的属性变成一个响应式属性
3. beforeMount(){}
模板与数据进行结合,但是还没有挂载到页面上。因此我们可以在当前生命周期中进行数据最后的修改
4.mounted(){}
当前生命周期数据和模板进行相结合,并且已经挂载到页面上了,因此我们可以在当前生命周期中获取到真实的DOM元素
5. beforeUpdate(){}
当数据发生改变的时候当前生命周期就会执行,因此我们可以通过当前生命周期来检测数据的变化
当前生命周期执行的时候会将更新的数据与模板进行相结合,但是并没有挂载到页面上,因此我们可以在当前生命周期中做更新数据的最后修改
6.updated(){}
数据与模板进行相结合,并且将更新后的数据挂载到了页面上。因此我们可以在当前生命周期中获取到最新的DOM结构
7. beforeDestroy(){}
当前生命周期中我们需要做事件的解绑 监听的移除 定时器的清除等操作
8. destroyed(){}
当前生命周期执行完毕后会将vue与页面之间的关联进行断开
当<keep-alive>包裹动态组件的时候会触发两个新的生命周期
9. activated 当组件为活跃状态的时候触发(活跃状态:进入页面的时候)
10. deactivated 缓存状态的时候触发