【面试】前端面试之Vue篇
叮叮叮,下面是一些vue面试中经常会被问到的题目。一、v-show和v-if的区别v-show的值无论是true还是false,他的元素都是存在于html当中,只是设置了style中的display的值,为none 或者block而v-if只有为true的时候,元素才会显示在html当中二、如何让css只在当前组件中起作用?只需要在当前组件的tyle当中写入 scoped<sty...
文章目录
- 前端面试之Vue篇
- vue组件的核心选项
- vue组件的通信方式有哪几种?
- vue如何操作dom节点?
- vue当数据更新是如何更新dom节点的?
- computed内想传入一个参数,要怎么实现?
- Vue组件中的data为什么必须是函数?
- 封装自定义组件使用v-model的方法
- Vue等单页面应用及其优缺点
- 说一下 Vue 的双向绑定数据的原理?
- vue的底层用object.definedPropety( )来实现它有什么弊端或局限性?
- 解释单向数据流和双向数据绑定?
- Vue 如何去除 URL 中的#?
- 对 MVC、MVVM 的理解?
- Vue 生命周期的理解?
- 什么是虚拟的dom?
- 请解释下虚拟dom的原理?
- v-show和v-if的区别?
- 如何让css只在当前组件中起作用?
- $route 和 $router 的区别?路由跳转有哪些形式?
- 讲下vue-router 路由你的了解有多少?
- 讲下路由守卫是怎样的?
- vue-router响应路由参数的变化
- Vue中key的值
- 组件间的参数传递
- NextTick 是做什么的?NextTick的原理是什么?
- Vuex是什么?怎么使用?哪种功能场景使用它?
- 对keep-alive 的了解?
- v-for与v-if的优先级
- Vue 组件 data 为什么必须是函数?
- computed和watch的区别?
- vue-cli ⼯程常⽤的 npm 命令有哪些?
- .Vue常用的几种指令
- Vue的计算属性缓存和方法调用的区别
- Vue 中怎么自定义指令?
- Vue 中怎么自定义过滤器?
- 简述vue的风格指南?
- 说一下对vue里面slot的理解?
- vue常用的修饰符?
前端面试之Vue篇
前沿知识:
关于MVVM
,MVVM之间的通信都是双向的,主要是负责数据模型的操作,不用过多的操作dom,它是种架构模式的概念,按照这种模式设计的框架都叫MVVM框架,
它主要有三个部分,M:数据模型、V:视图模型、VM:视图模型而
vue
就是个mvvm架构模式的渐进式框架 最核心的有两个点:
1.数据驱动
,也叫双向数据绑定,主要是负责数据模型的操作,不用过多地操作dom,减少dom的操作也意味着更高的性能。
2.组件系统
提高开发效率、方便重复使用、简化调试步骤、提升整个项目的可维护性
vue组件的核心选项
1.模板(template)
:模板声明了数据和最终展现给用户的dom之间的映射关系。
2.初始数据(data
):一个组件的初始数据状态,对于可复用的组件来说,这通常是私有的状态
3.接受的外部参数(props)
:组件之间通过参数来进行数据的传递和共享
4.方法(methods)
:对数据的改动操作一般都在组件的方法进行
5.生命周期钩子函数(lifecycle hooks)
,一个组件会触发多个生命周期钩子函数
6.私有资源(assets)
,vue.js当中将用户自定义的指令、过滤器、组件等统称为资源。一个组件可以声明自己的私有资源,私有资源只有该组件和他的子组件可以调用。
对于vue是一套构建用户界面的渐进式框架的理解 渐进式代表的含义是:没有多做职责之外的事
vue.js只提供了vue-cli生态中最核心的组件系统和双向的数据绑定 像vuex、vuer-outer都属于围绕vue,js开发的库
vue组件的通信方式有哪几种?
1.父传子:props
父组件通过props向下传递数据给子组件
props: {
desc: {
type: String,
default: ""
}
},
2.子传父:$emit
子组件通过$emit发送消息,父组件通过v-on绑定函数,接收数据
this.$emit('getData',1)
<detail @getData='getDataList'></detail>
getDataList(ms){
console.log(ms)
}
3.vuex (状态管理器)
4.ref和$refs
5.event Bus
6.parent children
vue如何操作dom节点?
vue是鼓励开发人员按照“数据驱动”的思路去开发项目,但是有时候也不可避免会遇到操作dom的特殊情况,以下就是vue操作dom节点的方式
- ref和$refs
ref是用来给子组件和元素注册引用信息的,引用信息会注册到父对象的$refs身上。若在普通的dom元素上,指向的就是dom元素,如果是子组件,那指向的就是子组件的实例
$refs持有所有注册过ref所有子组件的对象
vue当数据更新是如何更新dom节点的?
真实dom的渲染会引起整个dom树的重排重绘,会造成非常大的开销,因此vue采用virtual dom(即虚拟dom)进行局部更新。
- 虚拟dom是将真实dom数据抽取出来,以对象的形式模拟树形的结构
- 在更新节点的过程中采用
diff算法
,diff的过程就是调用patch函数,比较新旧节点,一边对比一边给真实dom打补丁
how to进行diff比较?
- 采用diff算法比较新旧节点时,比较只会在同层级进行,不会跨层级比较
- diff算法在执行时有三个维度:Tree Diff 、Component Diff、Element Diff
详解vue的diff算法:https://juejin.cn/post/6844903607913938951
老哥的这篇文章写的很详细,推荐大家看
computed内想传入一个参数,要怎么实现?
在computed内return 出一个函数出来,在return出来的函数处进行传参
Vue组件中的data为什么必须是函数?
<script>
export default {
data() {
//返回一个唯一的对象,不要和其他的组件共有一个对象进行返回
return {
msg:'hello'
}}}
因为一个组件是可以共享的,一个改变,其他的也改变,假如我们data是一个对象的话,很容易会污染变量,造成数据的紊乱(因为是全局对象),但假如是函数的形式返回一个对象,那么我们每次使用该组件的时候,返回的对象地址的指向都是不一样的,(函数=块级作用域),这样就能让各个组件数据独立。
封装自定义组件使用v-model的方法
父组件
<modelTab v-model="activeValue" :tabList="tabList" ><modelTab>
而v-model是绑定参数和绑定事件的语法糖,一个组件上的 v-model 默认会利用名为 value 的 prop 和名为input 的事件,因此v-model一般情况下是:
:value=“someValue” @input=“val=>someValue=val”
此语句的缩写。
<modelTab :value="activeValue" @input=“val=>activeValue=val” :tabList="tabList" ><modelTab>
子组件
<!-- 选业务的tab栏 -->
<template>
<div class="tab">
<div class="item" v-for="(item, i) of tabList" :key="i" :class="{ active: currentIndex == i }" @click="selectedTab(i)"
>
{{ item.label }}
</div>
</div>
</template>
<script>
export default {
name: 'modelTab',
model: {
prop: 'value',
event: 'onTabChange'
},
props: {
value: {
type: [String, Number],
default: ''
},
tabList: {
type: Array,
default () {
return [
{ label: 'tab1', value: 1 },
{ label: 'tab2', value: 2 },
{ label: 'tab3', value: 3 }
]
}
}
},
data () {
return {
}
},
computed: {
currentIndex () {
return this.tabList.findIndex(item => item.value == this.value)
}
},
// 方法集合
methods: {
selectedTab (i) {
this.$emit('onTabChange', this.tabList[i].value)
}
}
}
</script>
总结:
1️⃣model定义prop和event
2️⃣prop写入相应数值value
3️⃣对应函数,通过$emit方法将数据进行响应式修改
Vue等单页面应用及其优缺点
优点:Vue 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件,核心是一个响应的数据绑定系统。MVVM、数据驱动、组件化、轻量、简洁、高效、快速、模块友好。
缺点:不支持低版本的浏览器,最低只支持到IE9;不利于SEO的优化(如果要支持SEO,建议通过服务端来进行渲染组件);第一次加载首页耗时相对长一些;不可以使用浏览器的导航按钮需要自行实现前进、后退。
优点
- 良好的交互体验
- 良好的前后端工作分离模式
- 减轻服务端的压力
缺点- seo难度较高
- 前进、后退管理
- 初次加载耗时多
说一下 Vue 的双向绑定数据的原理?
vue实现双向数据绑定的原理是:采用数据劫持“发布者-订阅者”的模式,这种模式是通过Object.defineProperty()来劫持各个属性的setter、getter,然后在数据变动的时候发布给订阅者,触发相应的监听回调。
简单地理解:当data有变化的时候它通过Object.defineProperty()方法中的set方法进行监控,并且调用在此之前已经定义好data和view的关系的回调函数,来通知view进行数据的改变,而view发生改变则是通过底层的input事件来进行data的响应更改。vue是通过Object.defineProperty()来实现数据劫持的。
实现方式(发布者-订阅者模式):Observer(Object.defineProperty中的set)监听data的变化,当data有变化的时候通知观察者列表Dep(里面有与data变化对应的update函数),watcher负责向观察者列表添加(订阅)对应的更新函数,Dep里面的更新函数执行完了之后再将最新的值更新到view上面。
具体步骤:
(1)需要observe的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter和getter。
这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化。
(2)compile解析模板指令
,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图。
(3)Watcher订阅者
是Observer和Compile之间通信的桥梁,主要做的事情是:
①在自身实例化时往属性订阅器(dep)里面添加自己
②自身必须有一个update()方法
③待属性变动dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调,则功成身退。
(4)MVVM作为数据绑定的入口
,整合Observer、Compile和Watcher三者,通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据model变更的双向绑定效果。
vue的底层用object.definedPropety( )来实现它有什么弊端或局限性?
弊端:
1.不能监听对象属性的新增和删除,只对获取和更改进行了处理
2.通过索引更改数组对象不能被监听,如arr[1]=9
3.Object.defineProperty不能再get或set中使用该对象,因为使用该对象,就会触发get方法,会进入死循环,需要对被订阅的对象进行拷贝,使用拷贝的对象
4.需要遍历对象当中的各个属性,对其使用Object.defineProperty进行set/get的改写目前,解决第一个和第二个问题的方式是通过
vue.set(target,key,value)
来实现
在使用proxy时,创建代理对象。使用target和key,传入需要实现响应式的对象和属性,通过代理实现了目标对象的响应式。
解释单向数据流和双向数据绑定?
单向数据流:顾名思义,数据流是单向的,数据的流动方向可以跟踪,流动单一,追查问题的时候可以更加快捷。
缺点就是写起来不太方便
。要使UI发生变更就必须创建各种action
来维护相对应的state
。
双向数据绑定:数据之间是相同的,将数据变更的操作隐藏在框架的内部。优点
是在表单交互较多的场景下,会简化大量与业务无关的代码,缺点
就是无法追踪局部状态的变化,增加了出错时debug的难度。
Vue 如何去除 URL 中的#?
vue-router默认使用
hash
模式,所以在路由加载的时候,项目中的url会自带“#”。如果不想使用“#”,可以使用vue-router的另一种模式 history:
newRouter({
mode:'history',
routes:[]
})
需要注意的是,当我们启用
history模式
的时候,由于我们的项目是一个单页面的应用,所以在路由跳转的时候,就会出现访问不到静态资源出现“404”的情况,这时候就需要服务端增加一个覆盖所有情况的候选资源:如果url匹配不到任何静态资源,则应该返回同一个“index.html”页面。(由后端处理)
对 MVC、MVVM 的理解?
MVC:
特点:
- View传送指令到Controller
- Controller完成业务逻辑后,要求Model改变状态
- Model将新的数据发送到View,用户得到反馈
所有的通信都是单向的
MVVM:
MVVM分为Model、View、ViewModel三者
Model:代表数据模型,数据和业务逻辑都要在Model中定义
View:代表UI视图,负责数据的展示
ViewModel:就是界面View对应的Model,因为数据库结构往往是不能直接跟界面控件一一对应上,所以,需要再定义一个数据对象专门对应view上的控件,而ViewModel的职责就是把model对象封装成可以显示和接受输入的界面数据对象
特点:
1.各部分之间的通信,都是双向的
2.采用双向绑定:View的变动,自然都反应在ViewModel,反之也一样
延伸问题:ul中有一个li列表,它是怎么和我们的数据一一对应上的呢?(此题考查ViewModel)
Model是通过ViewModel来联系的,Model和ViewModel之间是有着双向数据绑定的联系,View和ViewModel也是,因此当Model中的数据改变时会触发View层的数据更新,View中由于用户的交互操作而改变的数据也会在Model数据模型当中同步。
Vue 生命周期的理解?
共有八个,创建前,创建后,挂载前,挂载后,更新前,更新后,销毁前,销毁后。
beforeCreate()
:在实例创建之前执行,数据是未加载的状态
created()
:在实例创建,数据加载后,能初始化数据,在DOM渲染之前执行
beforeMounte()
:虚拟DOM已创建完成,在数据渲染前最后一次更新数据
mounted()
:页面、数据渲染完成,真实的DOM挂载完成
beforeUpdate()
:重新渲染之前触发
Updated()
:数据已经更改完成,DOM也重新render完成,更改数据会陷入一个死循环。
beforeDestory()
:销毁前执行(这时实例仍然可以使用)
destoryed()
:销毁后执行
什么是虚拟的dom?
Vue通过建立一个虚拟的dom数对真实的dom发生的变化保持追踪
一棵真实的dom树的渲染需要先解析css样式和dom树,然后将其整合成一棵渲染树,再通过布局算法去计算每个节点在浏览器中的位置,最终输出到显示器上面。
而我们所提及的虚拟的dom
则可以理解为保存了一棵dom树被渲染之前所包含的所有信息,而这些信息可以通过对象的形式一直保存在内存当中,并通过js的操作来进行维护
请解释下虚拟dom的原理?
背景:在网页浏览器资源开销最大的便是dom节点了,dom很慢而且也非常地庞大,
网页的性能问题也大多数是由于js修改dom所引起的
,我们使用js来操作dom,操作的效率往往是非常低的
由于dom被表示为树的结构
,每次dom中的某些内容都会发生变化,引起对dom的更改非常的快,但是由于更改后的元素,他的子项,必须经过reflow/layout阶段,然后浏览器必须重新绘制更改,这很慢的。
因此,回流/重绘的次数越多,应用程序就会越卡顿
。但是js运行的速度很快,
虚拟dom是放在js和html中间的一个层,他可以通过新旧dom的对比
,来获取对比后的差异对象,然后有针对性地把差异部分真正地渲染到页面上,从而减少实际dom的操作,最终达到了性能优化的目的。
虚拟的dom是根据dom树映射出来的,里面加了diff算法,通过对比新旧dom,可以计算dom的最少改变值,最后通过虚拟的dom来修改真实的dom
简单地概括有以下三点:
1、用js模拟dom树,并渲染这个dom树
2、比较新老的dom树,饿到比较的差异对象
3、把差异对象应用到渲染的dom树里面
v-show和v-if的区别?
v-show的值无论是true还是false,他的元素都是存在于html当中,只是设置了style中的display的值,为none
或者block 而v-if只有为true的时候,元素才会显示在html当中
如何让css只在当前组件中起作用?
只需要在当前组件的tyle当中写入 scoped
css <style scoped> </style>
$route 和 $router 的区别?路由跳转有哪些形式?
router是vueRouter的实例,相当于一个全局的路由对象,包括路由的跳转对象和钩子函数。
route是“路由的信息对象”,包括path,params,name,query等
路由跳转的形式有哪些?
1.router-link(声明式路由)
不带参数
:<router-link :to=’’{path:’/home’}’> //name path都行,建议用name
带参数
:<router-link :to=’{name:‘home’,params:{id:1}}’>
2.router.push(编程式路由)
字符串
:router.push(‘home’)
对象
:router.push({path:‘home’})
命名的路由
:router.push({name:"user’,params:{id:0}})
带查询参数 变成/register?paln=prive
router.push({path:‘register’,query:{plan:‘prive’}})
query和params区别?
比较直观的区别:
1.query类似于get
,跳转后页面url后面会拼接参数,类似?id=1,非重要的可以这样子传,密码之类的还是用params刷新页面id还在
2.params类似post
跳转之后页面url后面不会拼接参数,但是刷新页面id会消失
其他区别:
3.query传参配置的是path,而params传参配置的是name,在params配置path无效
4.query传递的参数会显示在地址栏
5.params传参刷新会无效,但是query会保存传递过来的值,刷新不变
讲下vue-router 路由你的了解有多少?
路由就是用来跟后端服务器进行交互的一种方式,通过不同的路径,来请求不同的资源,请求不同的页面是路由的其中一种功能。
前端路由的核心
就在于改变视图的同时不会向后端发出请求。
hash
和history
hash模式:
这里的hash就是指url尾巴后的#号以及后面的字符。这里的#和css里的#是一个意思。hash也称为锚点,本身是用来做页面定位的,她可以使对应的id的元素显示在可视区域内。
由于hash值变化不会导致浏览器向服务器发出请求
,而且hash改变会触发hashchange事件,浏览器的进后退也能对齐进行控制,所以人们在html5的history出现前,基本都是使用hash来实现前端路由的。
history模式
已经有hash模式了,而且hash能兼容到ie8,history只能兼容到IE10,为什么还要搞个history呢?
首先,hash本来是拿来做页面定位的,如果拿来做路由的话,原来的锚点功能就不能用了。其次,hash的传参是基于url,如果要传递复杂的数据,会有体积的限制
,而history模式不仅可以在url里面放参数,还可以将数据存放在特定的对象里面。
路由配置主要有四步:
1.引入路由插件
2.创建路由配置
3.使用路由配置创建路由对象实例
4.挂载到根实例
<script src='./js/vue.min.js'></script>
//需要在引入vue之后再去引入路由库
//1.引入库
<script src='./js/vue-router.min.js'></script>
<script>
//2.创建路由配置
//里面的应该是路由对象,每个对象都是一个路由
//路由最重要的是这个配置
var routes=[]
//3.使用上面的配置创建路由实例对象
var router=new VueRouter({routes})
//4.挂载到根实例
var app=new Vue({el:'#app',router})
</script>
//其他引入方式
import Vue from 'vue'
import VueRouter from 'vue-router'
不用路由也可以实现组件的切换
需求:点击按钮,切换页面
- 编写组件:
- data数据配合v-if判断数据决定组件是否显示
- 创建改变data的方法
- 使用按钮控制data数据
缺点:- 繁琐,每多一个组件就多一个v-if
- 不友好,没有状态保存,刷新后会被重置
讲下路由守卫是怎样的?
一、全局守卫
1.router.beforeEach((to,from,next)=>{})
回调函数里面的参数,to:进入到哪个路由去,from:从哪个路由离开,next:函数,决定是否展示你要看到的路由页面
业务场景:检验是否登录了,没登录就跳转到登录页面不然他在其他页面逗留,现在一般都是用请求的全局拦截来进行实现
router.beforeEach((to,from,next)=>{
if(to.path == '/login' || to.path == '/register'){
next();
}else{
alert('请先登录,憨憨儿');
next('/login');
}
})
2.router.afterEach((to,from)=>{})(少用) 这个钩子不会接受next函数,也不会改变导航本身
二、路由独享的守卫
1.beforeEnter、beforeLeave 用法和全局守卫是类似的,但是只能作用于单个路由里面
//登录模块
path:'login',
component:()=>import('/views/login'),
beforeEnter:(to,from,next)=>{
if(to.meta.needLogin $$ !$store.state.isLogin)
next({path:'/login'}
)}}
}
else{
next()
}
三、组件内的守卫
可以在路由组件内直接定义一下的路由导航守卫
1.beforeRouteEnter
- 在渲染该组件的对应路由被confirm前调用
- 不能!获取组件实例this,因为当守卫执行之前,组件实例还没被创建
- 可以通过next获取data中的数据
data(){
return {
name:"jack"}
}
beforeRouteEnter:(to,from,next)=>{
next(vm=>{
alert("hi"+vm.name)})
}
2.beforeRouteUpdate
在原先的版本中,如果一个在两个子路由之间跳转,是不触发beforeRouteLeave的,这回导致某些重置的操作,没地方触发,在这之前,我们都是用watch,但是通过这个钩子,我们有了更好的方式
beforeRouteUpdate(to,from,next){
//在当前路由改变,但是该组件被复用时被调用
//举例来说,对于一个带有动态参数的路径 /doo/:id,在/doo/1和/doo/4之间跳转的时候
//由于会渲染同样的doo组件,因此组件实例会被复用,而这个钩子就会在这个情况下被调用
//可以访问组件实例‘this’
}
3.beforeRouteLeave
这个离开的守卫通常用来禁止用户在还未保存修改前突然离开,该导航可以通过next(false)来取消
- 可以访问组件实例this
beforeRouteLeave: (to, from, next) => {
if (confirm("你确定要离开吗") == true) {
next();
} else {
next(false);
}
},
返回上一级路由
1.history.back()
2.this.$router.go(-1)
关于to,from,next,next(false)
vue-router响应路由参数的变化
问题:当使用路由参数时,例如从/page?id=1到/page?id=2,此时原来的组件实例会被复用,意味着组件的生命周期钩子不会再被调用,此时vue应该如何响应路由的参数变化?
答案:使用watch(监听变化)$route对象
Vue中key的值
key 的特殊 attribute 主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes。如果不使用
key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法。而使用 key 时,它会基于 key
的变化重新排列元素顺序,并且会移除 key 不存在的元素。有相同父元素的子元素必须有独特的 key。重复的 key 会造成渲染错误。
可参考官方文档:https://cn.vuejs.org/v2/api/#key
简单来讲:
vue中的key作用是高效地更新虚拟的dom
,就是管理可复用的元素
。当vue.js用v-for遍历已渲染过的元素列表时,它默认用“就地复用的策略”,会复用已有的元素而不是从头开始渲染,这样会使vue变得非常快
组件间的参数传递
父组件与子组件的传值
父组件传给子组件:子组件通过props方法进行接受数据 子组件传给父组件:子组件通过$emit的方式进行传递兄弟组件之间的传值
一般会创建一个中间站,就是兄弟子组件,都把数据传递给父组件,即先是子组件传递给父组件,再通过父组件传递给另一个子组件的方式- 非兄弟、非父子之间的组件传值如下:
/*新建一个Vue实例作为中央事件总嫌*/
let event = new Vue();
/*监听事件*/
event.$on('eventName', (val) => {
//......do something
});
/*触发事件*/
vent.$emit('eventName', 'this is a message.')
NextTick 是做什么的?NextTick的原理是什么?
$nextTick
是在下次dom更新循环结束之后执行延迟回调,在修改数据之后使用$nextTick
,则可以在回调当中获取更新后的DOM。运用此方法 可以拿到最新的dom数据。
为什么要这么做?
因为频繁更新dom是特别耗性能的,所以搞了一个批处理更新,update操作放到任务队列当中,当主线程中执行栈所有的同步任务自信完毕之后,系统才会读取任务队列,所以实时set完之后,get就不能立刻拿到set的值,因为此时主线程还存在同步任务。
举个栗子:
比如需要在一个dom上面挂载或者监听一个内容时候,往往会出错。比如使用v-if来进行dom渲染,由于dom还未渲染,会直接导致挂载失败。这也是Vue不建议直接操作dom的原因。
或者是通过data里的数据来重新刷新一些插件的值,由于数据是异步刷新的,可能会导致传输到插件的值还是原值,导致插件刷新失败。
这里Vue提供一个Vue.nextTick(callback)的方法,这样可以在dom都渲染完毕后再执行我们相关的业务代码。
什么时候需要用Vue.nextTick():
- 你在Vue生命周期的created()钩子函数进行的DOM操作一定要放在Vue.nextTick()的回调函数中。原因是什么呢,原因是在created()钩子函数执行的时候DOM 其实并未进行任何渲染,而此时进行DOM操作无异于徒劳,所以此处一定要将DOM操作的js代码放进Vue.nextTick()的回调函数中。与之对应的就是mounted钩子函数,因为该钩子函数执行时所有的DOM挂载和渲染都已完成,此时在该钩子函数中进行任何DOM操作都不会有问题 。
- 在数据变化后要执行的某个操作,当你设置 vm.someData = ‘new value’,DOM并不会马上更新,而是在异步队列被清除,也就是下一个事件循环开始时执行更新时才会进行必要的DOM更新。如果此时你想要根据更新的 DOM 状态去做某些事情,就会出现问题。。为了在数据变化之后等待 Vue 完成更新 DOM ,可以在数据变化之后立即使用Vue.nextTick(callback) 。这样回调函数在 DOM 更新完成后就会调用。
Vuex是什么?怎么使用?哪种功能场景使用它?
vuex是vue框架中的状态管理。 只用来读取的状态集中放在store中; 改变状态的方式是提交mutations,这是个同步的事物;
异步逻辑应该封装在action中。 在main.js引入store,注入。新建了一个目录store,…… export 。
场景有:单页应用中,组件之间的状态、音乐播放、登录状态、加入购物车
state Vuex 使用单一状态树,即每个应用将仅仅包含一个store 实例,但单一状态树和模块化并不冲突。存放的数据状态,不可以直接修改里面的数据。
mutations mutations定义的方法动态修改Vuex 的 store 中的状态或数据,view层通过store.commit来动态改变数据。
getters 类似vue的计算属性,主要用来过滤一些数据。
action actions可以理解为通过将mutations里面处里数据的方法变成可异步的处理数据的方法,简单的说就是异步操作数据。view 层通过
store.dispath 来分发 action。
对keep-alive 的了解?
keep-alive是vue内置的一个组件,主要用于
保留组件状态
或避免重新渲染
。
应用场景: 有一个列表页面和一个详情页面,那么用户就会经常执行这样的操作详情
=>返回列表
=>打开详情
这样的操作的话,列表和详情都是一个频率很高的页面,那么就可以对列表组件使用进行缓存,这样用户每次返回列表的时候,都能`从缓存中快速渲染,而不是重新渲染
<!-- 基本 -->
<keep-alive>
<component :is="view"></component>
</keep-alive>
<!-- 多个条件判断的子组件 -->
<keep-alive>
<comp-a v-if="a > 1"></comp-a>
<comp-b v-else></comp-b>
</keep-alive>
<!-- 和 `<transition>` 一起使用 -->
<transition>
<keep-alive>
<component :is="view"></component>
</keep-alive>
</transition>
具体参考官方文档API:https://cn.vuejs.org/v2/api/#keep-alive
v-for与v-if的优先级
当他们处于同一个节点时,v-for的优先级比v-if的更高,这意味着v-if将分别重复运行与每个v-for的循环当中。当你想仅为一些项渲染节点时,这种优先级的机制会十分地有用。
⽽如果你的⽬的是有条件地跳过循环的执⾏,那么可以将 v-if 置于外层元 素 (或 )上。
<div v-if='msg.length>0'>
<div v-for='msg'>
</div>
</div>
<div v-else></div>
Vue 组件 data 为什么必须是函数?
因为js本身的特性带来的,如果data是一个对象,那么由于对象本身属于引用类型,当我们修改其中的一个属性的时候,会影响到所有Vue实例的数据,如果将data作为一个函数返回一个对象,那么每一个实例的data属性都是独立的,不会相互影响了。
computed和watch的区别?
computed
1.支持缓存,只有依赖数据发生改变,才会重新进行计算
2.不支持异步,当computed里面有异步操作且无效时,无法监听数据的变化
3.computed属性值会默认走缓存,计算属性是基于他们的响应式依赖进行缓存的,也就是基于data中声明过的,或者父组件传递的props中的数据通过计算得到的值
4.如果一个属性是由其他的属性计算而来的,这个属性依赖于其他的属性,是一个多对一或者一对一的关系,一般就用computed
5.如果computed属性值是函数,那么默认会走get方法,函数的返回值就是属性的属性值,在computed中,属性都有一个get和一个set方法,当数据发生变化的时候,就调用set方法。
watch
(异步或者开销较大的时候使用,平时请勿滥用)
1.不支持缓存,数据一改变,就会触发相应的操作
2.watch支持异步
3.监听的函数接收两个参数时,第一个参数就是最新的值,第二个参数是输入之前的值
4.当一个属性发生变化的时候,需要执行对应的操作,一对多
5.监听数据必须是data中声明过的,或者父组件传递过来的props中的数据,当数据发生变化时,触发其他的操作,函数有两个参数,
immediate:组件加载立即触发回调函数会选哪个,
deep-深度监听,为了发现对象内部值的变化,复杂类型的数据时使用,例如数组中的对象内容的改变,注意监听数组的变动不需要那么做。
vue-cli ⼯程常⽤的 npm 命令有哪些?
下载 node_modules 资源包的命令: npm install 启动 vue-cli 开发环境的 npm命令:
npm run dev vue-cli ⽣成 ⽣产环境部署资源 的 npm命令: npm run build ⽤于查看
vue-cli ⽣产环境部署资源⽂件⼤⼩的 npm命令: npm run build --report
.Vue常用的几种指令
v-if:根据表达式的值的真假条件渲染元素。在切换时元素及它的数 据绑定 / 组件被销毁并重建
v-show:根据表达式之真假值,切换元素的 display CSS 属性。 •
v-for:循环指令,基于⼀个数组或者对象渲染⼀个列表,vue 2.0以 上必须需配合 key值 使⽤。
v-bind:动态地绑定⼀个或多个特性,或⼀个组件 prop 到表达式。
v-on:⽤于监听指定元素的DOM事件,⽐如点击事件。绑定事件监 听器。
v-model:实现表单输⼊和应⽤状态之间的双向绑定
Vue的计算属性缓存和方法调用的区别
- 计算属性必须返回结果
- 计算属性是基于他的依赖缓存的,一个计算属性所依赖的数据发生变化的时候,他才会重新开始取值
- 使用计算属性computed还是methods取决于是否需要缓存,当遍历大数组或者需要做大量计算的时候,应当使用计算属性,除非你不希望得到缓存。
- 计算属性是需要依赖自动执行的,而methods是需要事件的调用
Vue 中怎么自定义指令?
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function(el) {
// 聚焦元素
el.focus()
}
})
//下面是局部注册
directives: {
focus: {
// 指令的定义
inserted: function
(el) {
el.focus()
}
}
}
参考官方文档:自定义指令(https://cn.vuejs.org/v2/guide/custom-directive.html
)
Vue 中怎么自定义过滤器?
可以用全局方法 Vue.filter() 注册一个自定义过滤器,它接收两个参数:过滤器 ID 和过滤器函数。过滤器函数以值为参数,返回转换后的值。
Vue.filter('reverse',
function(value) {
return
value.split('').reverse().join('')
})
简述vue的风格指南?
vue的风格指南官网版本
分别有几个优先级,A/B/C 分别是必要的/强烈推荐/推荐三个
非常有必要
的有以下几点:
- 组件名为多个单词【为了防止了现有及未来的html元素相冲突】
- 组件中的data必须是个函数【因为组件需要复用,防止组件间数据的相互影响】
- prop的定义尽量要详细,至少要指定他的类型【若出错,帮助捕获潜在的错误】
- 为v-for设立键值,key要配合v-for
说一下对vue里面slot的理解?
https://www.cnblogs.com/maizilili/p/12449777.html
vue常用的修饰符?
.prevent:提交事件不再重载页面;.stop:阻止单击事件冒泡;.self:当事件发生在该元素本身时子元素的时候会触发;.capture:事件侦听,事件发生的时候会调用
更多推荐
所有评论(0)