在这些题目中,我涵盖了各种不同的主题,包括vue2的基本概念、指令、组件、生命周期、状态管理等等。我也包括了一些常见的面试题目,例如vue2与其他框架的比较、vue2的优化等等。
区别
总结:v-if判断是否加载,可以减轻服务器的压力,在需要时加载,但有更高的切换开销;v-show调整DOM元素的CSS的dispaly属性,可以使客户端操作更加流畅,但有更高的初始渲染开销。如果需要非常频繁地切换,则使用v-show较好;如果在运行时条件很少改变,则使用v-if较好。
可以,利用对象设置的方式设置多个监听事件
key值在列表渲染的时候,能够提升列表渲染性能,为什么呢?首先得想想Vue的页面是如何渲染的,主要分为以下几步:
key值的作用就在第二步,当数据改变触发渲染层重新渲染的时候,会校正带有key的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率。key值如果不指明,默认会按数组的索引来处理,因而会导致一些类似input等输入框组件的值出现混乱的问题。
因而,在做list渲染时,如果list的顺序发生变化时,最好增加key,且不要简单的使用数组索引当做key,需要用唯一值当成key。
如果后台接口返回的循环数据没有唯一值,那么可以在客户端利用map循环对原数组内容进行遍历,然后返回经处理过带有唯一值的数组列表,那么在v-for循环的时候依旧设置的是唯一值数据。
methods,watch和computed都是以函数为基础的,但各自却都不同
总结:在computed、methods、watch方面,一个是计算,一个是调用、一个是观察,在语义上是有区别的。计算是通过变量计算来得出数据,调用是方法的重复执行,而观察是观察一个特定的值。
可以
{{compuntedFn(arg)}}computed:{compuntedFn:function(){returnfunction(arg){return"compuntedResult"};},},15.Vue实例中最为重要的三大部分是什么?不管是Vue也好或者其它的框架也罢,基本上面向对象以及组件化开发中实例对象都包含三个主要部分内容:
属性、事件是对象本身的操作,而方法一般交由第三方去操作对象本身内容,比如点击按钮去修改对象的属性操作。
块状内容在页面中将不会进行块状标签的输出
在进行组件化项目开发的时候都会存在一个组件的生命周期概念,像Vue、React、小程序等等,无一例外,而通常情况组件的生命周期主要分成三个阶段,包括:创建、更新以及销毁阶段。
Vue的生命周期钩子函数主要包括:
我们通常在created()/mounted()进行发送ajax请求,启动定时器等异步任务,而在beforeDestory()做收尾工作,如:清除定时器操作。
不过需要注意的是mounted生命周期钩子中并不代表界面已经渲染成功,因为mounted不会保证所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以在mounted内部使用vm.$nextTick。
Vue的生命周期钩子函数又分为了:单个组件生命周期、父子组件的生命周期、带缓存的路由组件生命周期等不同的状态,在不同的状态下所拥有的生命周期内容是不相同的。
更新:
销毁:
更新:
销毁:
路由离开
路由回来
不能。
组件间的关系主要分成:父与子、子与父、祖与孙以及非父子之间的关系,正是因为存在组件之间的不同关系也就意味着它们之间会存在一定的数据传递操作,而组件之间的数据传递方式主要可以归纳为如下10多种实现:
Vue的动画方式主要分成两大类,一类是CSS动画,一类是JS动画
in-out:新元素先进行过渡,完成之后当前元素过渡离开。
out-in:当前元素先进行过渡,完成之后新元素过渡进入。
组件、过滤器、自定义指令的注册方式都包含全局与局部注册两种
个指令定义对象可以提供如下几个钩子函数(均为可选):bind、inserted、update、componentUpdated、unbind
对应钩子函数的参数主要包括:el、binding(属性:name、value、oldValue、expression、arg、modifiers)、vnode、oldVnode
static和assets的区别,原理就在于webpack是如何处理静态资源的
总结:assets里面的资源会被webpack打包进代码,static里面的资源就直接引用了,一般在static里放一些类库的文件,assets放属于项目的资源文件。
插槽是一种组件间html传递的策略,实现父组件向子组件传递标签内容。插槽的类型主要包括:普通插槽、具名插槽以及作用域插槽
对于作用域插槽是在父组件需要向子组件传递标签结构内容,但决定父组件传递怎样标签结构的数据是在子组件中。在Vue2.6版本以后,新版本插槽的语法比起老版本区别略有区别,主要可以利用#slotName={property}的方式进行简化缩写。
slot="插槽的名字"+slot-scope="{要收集的数据-1,要收集的数据-2}"=v-slot:插槽名字="{要收集的数据-1,要收集的数据-2}"=#插槽名字="{要收集的数据-1,要收集的数据-2}"34.组件的类型及特点有哪些?如果想要对组件进行类型划分,从实现的功能以及所具备的特点来划分,大致可以归纳为:动态组件、缓存组件、异步组件、函数式组件+JSX、递归组件等
路由组件对象什么时候死亡
exportdefault{functional:true,//当前是函数组件render(createElement,context){return要显示界面的虚拟DOM}}35.简述一下对Vue-Router的理解?在以往的项目开发中,包括使用不同技术栈的项目内容,例如nodejs的express、Vue项目、React项目、小程序项目等都涉及到了路由的概念与操作。虽然这些项目归属于不同的技术体系,但路由的核心概念都是一致的,我也做了相应的归纳,总结出5个词进行了概括:静态路由表、分配地址、统一入口、寻址渲染,过滤判断。当然,对于不同的技术体系,路由的表现与配置方式会有所差异与不同。
路由的具体操作又表现在:操作模式、跳转方式、参数的传递、嵌套处理、守卫管理、懒加载及动态路由等方面。
导航守卫是什么
导航守卫分类主要包括:
当点击切换路由时:beforeRouterLeave-->beforeEach-->beforeEnter-->beforeRouteEnter-->beforeResolve-->afterEach-->beforeCreate-->created-->beforeMount-->mounted-->beforeRouteEnter的next的回调
当路由更新时:beforeRouteUpdate
最为常用的路由守卫应当是全局守卫中的beforeEach,因为在用户权限认证操作过程中都会需要该守卫操作的处理,而用户权限又是每个项目中不可缺少的一部分。
答:vue.js是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
具体步骤:
第一步:需要observe的数据对象进行递归遍历,包括子属性对象的属性,都加上setter和getter这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化
第二步:compile解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图
第三步:Watcher订阅者是Observer和Compile之间通信的桥梁,主要做的事情是:1、在自身实例化时往属性订阅器(dep)里面添加自己2、自身必须有一个update()方法3、待属性变动dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调,则功成身退。
第四步:MVVM作为数据绑定的入口,整合Observer、Compile和Watcher三者,通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化->视图更新;视图交互变化(input)->数据model变更的双向绑定效果。
keep-alive是Vue内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。它有两个属性:include(包含的组件缓存)与exclude(排除的组件不缓存,优先级大于include)。
使用方法
使用示例
scrollBehavior:function(to){if(to.hash){return{selector:to.hash}}},42.你如何理解vuex?vuex的5大属性:内容作用映射位置调用其它state设置状态mapStatecomputedgetters获取内容mapGetterscomputed计算数据后返回mutations修改数据mapMutationsmethodscommit可以异步但不建议,不利调试actions异步操作mapActionsmethodsdispatchmodules模块拆分namespaced43.vuex中的namespaces是什么?它的主要作用是什么?在Vuex模块中开启namespaced以后,确定该模块为带命名空间的模块。当模块被注册后,它的所有state、getter、action及mutation都会自动根据模块注册的路径调整命名。
刷新页面Vuex的state会丢失,可以利用vuex-persist、vuex-persistedstate状态持久化插件将state数据存储于本地存储对象当中,比如localStorage。
项目的发解、学习与掌握也是有一定的顺序与方法的,主要的流程包括如下几个步骤:
项目性能优化的方面包含很多,针对Vue项目的优化可以介绍几种类型的内容,主要包括:Vue代码层面的优化、webpack配置层面的优化、基础的Web技术层面的优化、用户体验优化等
代码层面的优化:
Webpack层面的优化
基础的Web技术层面的优化
不可以,只能用name和params配置的组合,query配置可以与path或name进行组合使用
path:'/search/:keyword',利用号设定
不指定params或者指定params参数值为undefined
可以:可以将query或params参数映射成props传递给路由组件对象
//在routes中配置props:route=>({keyword1:route.params.keyword,keyword2:route.query.keyword})55.编程式路由跳转到当前路由(参数不变),会抛出NavigationDuplicated的警告错误面试问题::在做项目时有没有遇到比较难的问题(可做回答)
回答步骤:
56.是否有对axios进行二次封装?主要的封装功能包括哪些?
场景:当我们需要覆盖element-ui等UI框架中组件的样式时可以通过深度作用选择器
.a>>>.b{...}style使用css的预处理器(less,sass,scss)的写法如下/deep/.a{...}/*/deep/在某些时候会报错,::v-deep更保险并且编译速度更快*/::v-deep.a{...}60.利用深拷贝解决修改不能取消的问题在对某数据进行修改时考虑还需要进行“确认”、“取消”操作,那么在取消时就需要返回保留的数据内容,那么如何将原有数据保留一份则是关键性问题。
mounted(){consttimer=setInterval(()=>{console.log(1)},1000)this.$once('hook:beforeDestroy',()=>{//监听beforeDestroy这个钩子函数clearInterval(timer)})}65.请说一下computed中的getter和settercomputed中可以分成getter(读取)和setter(设值),一般情况下是没有setter的,computed预设只有getter,也就是只能读取,不能改变设值。
可以利用监控或者组件的路由守卫功能实现
监控模式:
可以,利用vuex-router-sync可以将vuex与router对象进行同步,将当前的$route同步为vuex状态的一部分,我们甚至可以利用修改vuex的路由状态来进行路由地址的跳转与参数传递
commit('route/ROUTE_CHANGED',{to:{path:'/b'}})73.如何对lodash库实现按需引入import_from'lodash'//引入整体lodash==>打包了没用的工具函数,打包文件变大importthrottlefrom'lodash/throttle'//只引入我需要的工具函数打包文件减少1.4M74.如何实现跨域配置在vue.config.js中对devServer进行属性配置
所有的props都使得其父子组件形成一个单向下行绑定,父级props的更新会流动到子组件中,但反过来不行。这种设计办法是为了防止子组件意外改变父组件的状态,从而导致你的应用的数据流向难以理解。另外,如果该数据还被其他子组件使用,也将受影响,产生洪水式灾难。因此不应该在子组件中设计修改props数据的操作。
利用update:myPropName的方式进行数据防脏处理
/*动态加载vuex中所有的modules模块不再需要通过import手动一个一个引入*/constcontext=require.context('./modules',false,/\.js$/)constmodules=context.keys().reduce((modules,modulePath)=>{//'./app.js'=>'app'constmoduleName=modulePath.replace(/^\.\/(.*)\.\w+$/,'$1')modules[moduleName]=context(modulePath).defaultreturnmodules},{})85.addRoutes的作用与应用场景addRoutes可以实现动态路由的添加操作
应用场景:根据用户权限判断展示不同路由菜单项
router.addRoutes([...asyncRoutes,lastRoute]);86.不同路由同一组件的重用如果设置不同的路由,但指向的是同一组件,那么因为组件性能考虑及缓存策略,组件并不会刷新,那么如何实现组件的刷新重用呢?
alertType:{validator:value=>['signup','login','logout'].includes(value)}88.如何实现组件的刷新?一般情况组件的state状态或者是props发生改变时就会进行刷新渲染,但有时需要进行用户控制,那么有哪些方法呢:
注入reload方法
exportdefault{inject:['reload'],}在需要重载的地方直接调用
this.reload()90.表单提交时如何阻止页面刷新?表单提交时为了防止页面刷新需要进行默认事件的阻止处理,可以利用submit.prevent进行实现。
所谓的动态表单就是根据数据库动态获取的字段配置信息生成表单模块,这一操作在产品的SKU管理,还有OA,ERP系统中应用广泛。
比如有父组件Parent和子组件Child,如果父组件监听到子组件挂载mounted就做一些逻辑处理,可以通过以下写法实现:
修改vue.config.js配置,configureWebpack属性中加入externals,将对应的类库抽离,需要在index.html中加入对应的cdn文件。
module.exports={publicPath:'./',configureWebpack:{//此处可以配置cdn配置//需要在index.html中引入cdn文件externals:{vue:'Vue','vue-router':'VueRouter',vuex:'vue','element-ui':'ELEMENT'}}}95.首屏性能优化一般有哪些方案?96.什么是XSRF攻击,Vue中如何做好相应的安全策略?Cross-siterequestforgery跨站请求伪造,也被称为“OneClickAttack”或者SessionRiding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。CSRF定义的主语是”请求“,是一种跨站的伪造的请求,指的是跨站伪造用户的请求,模拟用户的操作。
SPU=StandardProductUnit(标准化产品单元)
SPU是商品信息聚合的最小单位,是一组可复用、易检索的标准化信息的集合,该集合描述了一个产品的特性。通俗点讲,属性值、特性相同的商品就可以称为一个SPU。
SKU=stockkeepingunit(库存量单位)
SKU即库存进出计量的单位,可以是以件、盒、托盘等为单位。
SKU是物理上不可分割的最小存货单元。在使用时要根据不同业态,不同管理模式来处理。在服装、鞋类商品中使用最多最普遍。