1、v-show和v-if的区别
v-show 操作的是元素的display属性
v-if 操作的是元素的创建和插入
v-if有更高的开销,而v-show有更高的初始渲染开销,如果需要非常频繁的切换,则使用v-show更好,如果在运行时条件很少改变,则使用v-if更好
使用场景:v-show----前台数据的展示 v-if----管理系统权限列表的展示
2、methods、computed、watch三者的区别
三者的共同点:
methods、computed、watch都是以函数为基础的
computed与watch都是以vue的依赖为基础,当所依赖的数据发生变化的时候会触发相关的函数去实现数据的变动
methods里是用来定义函数的,需要手动才能执行,不想computed和watch是“自动执行”函数
三者的不同点:
computed是计算属性,computed所依赖的属性发生变化是,计算属性才会重新计算,并进行缓存。当其他数据发生改变的时候computed属性不会重新计算,从而提升性能
watch:
a、watch类似于事件监听+事件机制
b、watch的方法默认是不会执行的,只有依赖的属性发生变化才会执行
c、watch默认第一次是不会执行的,通过声明immediate选项为true可以立即执行一次handler
d、watch用在监听数据变化,给后台发送数据请求
e、watch中的handler默认只能监听属性引用的变化,但内部属性是监听不到的,设置deep为true可以进行深度监听,但是性能开销也会变大
f、watch无法监听数据值的变化(特殊情况下)
computed和watch的使用场景:
computed一个数据受多个数据的影响 例如:商品购物车的结算,过滤某些商品数据
watch一个数据影响多个数据 例如:网络请求、浏览器自适应、监控路由对象
3、watch无法监听数组的情况,以及解决方案
无法监听数组的情况:
a、利用索引直接设置一个数组项时,例如:arr[indexOfItem]=newValue
b、修改数组的长度时,例如:arr.length=newLength
解决方案:
a、this.$set(arr,index,newVal)
b、使用数组splice方法
4、如何给一个响应式对象中添加一个属性?如何删除响应式对象中的属性?
import Vue from "vue" new Vue({ data:{ obj:{ } } }) Vue.set(obj,name,"孙艺珍") Vue.delete(obj,"name")
5、vue中自定义指令如何使用
Vue.directive()
参数一:指令名称
参数二:指令实现的函数,在回调函数中参数一是指令绑定的元素,参数二是一个对象,对象中有value属性代表的是表达式返回的结果,还有modifiers属性是指令的修饰符
6、vue中组件创建的方式有哪些
全局组件:Vue.component()
参数一:组件名称
参数二:组件的配置项
局部组件:new Vue({
components:{} key值为组件名称,val值为组件的配置项
})
7、vue中的过滤器如何使用
vue.filter()
参数一:过滤器名称
参数二:过滤器实现的方法,该方法中有两个参数,分别为需要过滤的数据、过滤器传递的参数
8、vue中组件通讯的方式有哪些
父传子:
通过绑定自定义属性,通过props接收
子传父:
a、通过绑定自定义事件
b、通过插槽作用域
非父子组件传值:
a、创建公共的vue实例对象
b、EventBus
c、手动封装事件订阅
d、vuex
9、vue的生命周期
beforeCreate() 组件刚刚被创建(el和data未初始化)
created() 组件创建已完成,属性已绑定,但DOM还未生成($el属性还不存在)
beforeMount() 模板挂载前(el和data初始化)
mounted() 挂载后
beforeUpdate() 组件更新前
updated() 组件更新后
beforeDestroy() 组件销毁前
destroyed() 组件销毁后
10、vue中的单向数据流
数据从父组件传递给子组件,只能单向绑定,子组件不能直接修改从父级传递过来的数据
数据只能从一个方向来修改状态,如果父组件给n个子组件进行了数据传递,那么某一个子组件中修改了这个数据,那么就会导致其他组件中的数据也会发生改变。这样会防止从子组件中意外改变父组件的状态,从而导致你的应用数据的流向难以理解,因此数据只能从一个方向来修改状态
11、什么是动态组件,如何使用,以及keep-alive的作用
动态组件:让多个组件使用同一个挂载点,并动态进行切换
实现动态组件:通过保留<component></component>元素,动态的绑定它的is属性,可以实现动态组件
<keep-alive></keep-alive>是一个抽象组件,它自身不会渲染成一个DOM元素
常用的一些属性:
include:类型:字符串或者正则表达式
解释:只有名称匹配的组件会被缓存
exclude:类型:字符串或者正则表达式
解释:任何名称匹配的组件都不会缓存
max:类型:数字
解释:最多可以缓存多少个组件实例
12、当使用keep-alive内置组件后会增加哪两个生命周期
activated:当组件为活跃状态时候触发(进入页面的时候)
deactivated:缓存状态的时候触发
13、vue中slot的使用方式,以及slot作用域插槽的用法
当组件当做标签使用的时候,如果需要在组件标签内部进行嵌套内容的时候,需要通过template组件包裹嵌套的内容,在组件内部通过<slot></slot>进行接收
14、为什么组件内部的data是一个函数而不是一个对象
因为每次调用组件的时候都会重新生成一个对象,如果是一个对象的情况下,data数据会进行复用,因为对象是引用类型数据,而当data是一个函数时,每次调用会返回一个新的对象
15、vue中动画如何实现
给需要动画的元素添加<transition></transition>标签,
进入时class类 <name>-enter <name>-enter-active <name>-enter-to
离开时class类 <name>-leave <name>-leave-active <name>-leave-to
16、浅谈对路由的理解
什么是路由:根据不同的url地址展示不同的页面或者数据
路由分为前端路由和后端路由
前端路由:
a、前端路由用于单页面开发,SPA
b、前端路由是不涉及到服务器的,是前端利用hash或者h5的historyAPI来实现的,一般用于不同的内容展示和切换
17、路由跳转的方式
①a标签进行跳转 <a href="#/home">首页</a>
②router-link进行跳转 <router-link to="/home">首页</router-link>
③编程式路由 this.$router.push()
18、路由传值的方式有哪几种
①动态路由传值 path="/home/:id/name" 通过this.$route.params接收
②query传值 在url中?后面的参数不会被解析,所以可以通过query传值 通过this.$route.query接收
③路由解耦 在配置路由的时候添加props属性为true,在需要接收参数的组件页面通过props接收
④编程式导航 this.$router.push({path:"/home",query:{}})
19、路由常用配置项及作用
path 跳转路径
component 路径相对于的组件
name 命名路由
meta 路由元信息
children 子路由的配置参数(路由嵌套)
props 路由解耦
redirect 路由重定向
20、编程式导航常用的方法
路由跳转 this.$router.push()
路由替换 this.$router.replace()
后退 this.$router.back()
请进 this.$router.forward()
21、如何重定向路由?如何实现路由解耦?
通过配置路由项中的redirect进行重定向
在路由的配置项中设置props:true,在需要接收的组件内部通过props接收
22、如何检测路由参数的变化
通过属性监听来实现或者beforeRouteUpdate()
watch: { "$route"(){ } } beforeRouteUpdate(to,from,next)
23、什么是路由守卫?路由的钩子函数有哪些?分别说出使用的场景及用法
什么是路由守卫:路由跳转前后的一些验证
路由常见的钩子函数:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave
使用场景:
beforeRouteEnter:当路由进入之前。登录验证、热力图的记录
beforeRouteUpdate:当路由更新的时。如果当前路由发生了变化,但是不需要组件的创建和销毁的过程的时候,就需要用到这个钩子函数
beforeRouteLeave:当路由离开时。支付、退出
24、什么是全局守卫
beforeEach 验证用户是否登录
25、axios和jQuery的ajax有什么不同
axios的优点:
①支持PromiseAPI
②自动转换json数据
③提供了一些并发请求的接口
④客户端支持防止csrf、xsrf
⑤从nodejs中创建http请求
ajax的优缺点:
①jQuery项目庞大,单纯的使用ajax引入整个jQuery不合理
②基于原生的XHR开发,但是XHR架构并不清晰
26、简述vuex的数据传递流程
当组件进行数据修改的时候,我们需要调用dispatch来触发actions中的方法
actions中的方法中有一个commit方法,通过调用commit来触发mutations中的方法进行数据修改
mutations中的方法中有一个state参数,当修改完毕后,因为数据是响应式的,会传导给页面。
27、双向数据绑定的原理
vue.js是采用数据劫持结合发布者-订阅者的方式,通过Object.defineProperty()来劫持各个属性的setter和getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
第一步:需要observer的数据对象进行递归遍历,包括子属性的对象的属性,都加上setter和getter,这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化
第二步:compile解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知更新视图
第三步:watcher订阅者是observer和compile之间通信的桥梁,这要做的事情是:
①在自身实例化时往属性订阅器(dep)里面添加自己
②自身必须有一个update方法
③待属性变动dep.notice()通知时,能调用自身的update方法,并触发compile中绑定的回调,则功成身退
28、使用vue的时候会一下子加载所有的东西使得初始化页面很卡,该如何解决
①路由懒加载
②服务端渲染
③骨架屏注入
像vue这种单页面应用,如果没有应用懒加载,运用webpack打包后的文件将会异常的大,造成进入首页时,需要加载的内容过多,时间过长,会出现长时间的白屏,即使做了loading也是不利于用户体验。而运用懒加载则可以将页面进行划分,需要的时间加载页面,可以有效的分担首页所承担的加载压力,减少首次加载用时。
29、如何在vue中实现css私有化
vue组件中在style标签上添加scoped属性,可以使css私有化。但是这种方法会造成样式不可修改,因为很多时候需要对公共组件的样式做微调,所以慎用。
30、常见的跨域方式
①服务器代理 http-proxy-middleware 原理:服务器之间的请求不存在跨域问题
②nginx proxy-pass后面跟一个跨域的地址
③cors 服务端的代理方式 设置响应头:header(Access-Control-Allow-Origin:*)
④jsonp 原理:表单中的action、script中的src、a标签和link标签中的href都会造成页面的跳转,所以这不存在跨域的问题。jsonP的原理是利用script的src进行跳转,前端将函数传到服务端,服务端将函数加工后再返回,所以jsonp和ajax不是一回事。 缺点:只支持get
31、vue中使用插件的流程
import Vue from "vue" import 插件 from "插件" Vue.use(插件)
32、列举3个vue中常用的生命周期钩子函数
created:实例已经创建完成之后调用,这里实例已经完成数据观测,属性和方法的运算,watch/event事件回调。挂载阶段还未开始,$el属性目前还不可见
mounted:el被创建的vm.$el替换,并挂载到实例上后调用该钩子。如果root实例挂载了一个文档内元素,当mounted调用时vm.$el也在文档内
activated:keep-alive组件激活时调用
33、第一次页面加载会触发哪几个钩子
beforeCreate
created
beforeMount
mounted
34、简单描述每个生命周期具体适合哪些场景
beforeCreate:可以在这里加loading事件,在加载实例时触发
created:初始化完成时的事件写在这里,例如在这里结束loading事件,异步请求也适宜在这里调用
mounted:挂载元素,获取DOM节点
updated:如果对数据统一处理,在这里写上相应函数
beforeDestroy:可以做一个确认停止事件的确认框
nextTick:更新数据后立即操作DOM
35、vue中router-link在电脑上有用,在安卓上没反应怎么办
vue路由在安卓上有问题,babel问题,安装babel polypill插件解决
36、vuex中常用的属性有哪些
state、getter、mutation、action、module
state:
①vuex就是一个仓库,仓库里面放了很多对象。其中state就是数据源存放地,对应于一般vue对象中的data
②state中存放的数据是响应式的,vue组件从state中读取数据,若是store中的数据发生改变,依赖这个数据的组件也会发生更新
③它通过mapState、mapGetters把全局的state和getters映射到当前组件的computed计算属性中
getter:
①getters可以对state进行计算操作,它就是store的计算属性
②虽然在组件内也可以做计算属性,但是getters可以在多组件之间复用
③如果一个状态只在一个组件中使用,是可以不用getters
mutation:
action类似于mutation,不同在于:action提交的是mutation,而不是直接变更状态;action可以包含任意异步操作。
37、是否封装过组件,说下封装组件的过程
首先,组件可以提升整个项目的开发效率,能够把页面抽象成多个相对独立的模块,解决了我们传统项目开发效率低、难维护、复用性等问题。
然后,使用Vue.extend方法创建一个组件,然后使用Vue.component方法注册组件
38、如果在vuex中保存了某些数据,刷新浏览器消失了,应该如何解决
保存在localStorage或者cookie中
39、swiper插件在后台获取数据没问题,css代码啥的也没问题,但是图片不能动应该怎么解决
这是因为生命周期的执行速度远远大于数据请求的速度,用watch&&nextTick解决,或者是update
40、什么是路由懒加载(当打开一个单页面应用的时候,会出现白屏,加载时间过长如何解决)
路由懒加载
nuxt服务端渲染
41、对vue-loader的理解
解析和转换.vue文件,提取出其中的逻辑代码script、样式代码style,以及html模板template,再分别把它们交给对应的loader去处理。
42、父组件如何访问子组件中的方法
this.$refs.属性.方法
43、对vue.extend的理解
使用vue构造器,创建一个子类,参数是一个组件对象,注意data必须是一个函数
Vue.extend()返回的是一个扩展实例构造器,简单来说就是一个预设了部分选项的vue实例,主要用来服务Vue.component,用来生成组件。
44、说下对Vue.use的理解
安装vue.js插件。如果插件是一个对象,必须提供install方法。如果插件是一个函数,它会被作为install方法。install方法调用时,会将vue作为参数传入。
该方法需要在调用new Vue()之前被调用
45、如何解决路由与跨域之间的冲突
统一规范为一个入口,在一定程度上会解决冲突或者在axios中配置baseUrl
46、vue响应式原理
工作原理是当我们把一个普通的JavaScript对象传给vue的实例data选项的时候,vue会遍历此对象的所有属性,并使用Object.defineProperty把这些属性全部转化为getter/setter。
(Object.defineProperty仅ES5支持,且没有垫片脚本的特性,因此vue不支持IE8及以下浏览器)。用户看不到getter/setter,但是在内部它们让vue追踪依赖,在属性被访问和修改时通知变化。
每个组件实例都有相应的watcher实例对象,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的setter被调用时,会通知watcher重新计算,从而使它关联的组件得以更新。
47、vue-router的实现原理
单页面应用(SPA)的核心之一是:更新视图而不更新请求页面
实现这一技术主要是两种方式:
hash:通过改变hash值
history:利用history对象新特性
48、对vue.js中templ编译的理解
先转化为AST树,再得到的render函数返回VNode
首先,通过compile编译器把template编译成AST(abstarct syntax tree 源代码的抽象语法结构的树状表现形式)语法树,compile是createCompiler的返回值,createCompiler是用来创建编译器的。另外compiler还负责合并option。
然后,AST会经过generate(将AST语法树转化成render function字符串的过程)得到render函数,render的返回值是VNode,Vnode是vue的虚拟DOM节点,里面有标签名、子节点、文本等。
49、前端路由和后端路由的区别
路由:根据不同的url展示不同的内容或页面
前端路由:很重要的一点就是页面不刷新,前端路由就是把不同路由对应不同的内容或页面的任务交给前端来做,每跳转到不同的url都是使用前端的锚点路由,随着SPA应用的不断普及,前后端开发分离,目前项目基本都使用前端路由,在项目使用期间路由不会重新加载。hash有一个特点:http请求中不会包含hash相关的内容,所以,单页面应用中的页面跳转主要用hash实现。
后端路由:通过用户请求的url导航到具体的html页面,每跳转到不同的url,都是重新访问服务端,然后服务端返回页面,页面也可以是服务端获取数据,然后和模板结合,返回html,也可以是直接返回模板html,然后由前端js再去请求数据,使用前端模板和数据进行结合,生成想要的html。
对比:
①从性能和用户体验的层面来比较的话,后端路由每次访问一个新页面的时候都要向服务器发送请求,然后服务器再响应请求,这个过程肯定会有延迟。而前端路由在访问一个页面的时候仅仅是变换了以下路径而已,没有了网络延迟,对于用户体验来说会有相当大的提升。
②在某些场合中,用ajax请求,可以让页面无刷新,页面变了但是url没有变化,用户就不能复制到想要的地址,用前端路由做单页面网页就很好的解决了这个问题。但是前端路由使用浏览器的前进后退键的时候会重新发送请求,没有合理的利用缓存。
50、前端渲染和后端渲染的优缺点
前端渲染:后端返回json数据,前端利用预先写的html模板,循环读取json数据,拼接字符串,并插入页面。
好处:
①前后端分离。前端专注于UI,后端专注于api开发,且前端有更多的选择性,而不需要遵循后端特定的模板。
②体验更好。比如我们将网站做成SPA或者部分内容做成SPA,这样尤其是移动端可以使体验更好更接近于原生app。
坏处:
①前端响应较慢。如果是客户端渲染,前端还要进行拼接字符串的过程,需要耗费额外的时间,不如服务器端渲染速度快。
②不利于SEO。目前如百度、谷歌的爬虫对于SPA都是不认识的,只是记录了一个页面,所以SEO很差。因为服务器端可能没有保存完整的html,而是前端通过js进行DOM的拼接,那么爬虫无法读取信息。除非搜索引擎的SEO可以增加对于JavaScript的爬取能力,这样才能保证SEO。
后端渲染:前端请求,后端用后台模板引擎直接生成html,前端接收到数据之后,直接插入页面。
好处:
①前端耗时少,减少了首屏时间
②有利于SEO。因为在后端有完整的html页面,所以爬虫更容易爬取到信息
③无需占用客户端资源。即解析模板的工作完全交由后端来做,客户端只要解析标准的html页面即可,这样对于客户端的资源占用更少,尤其是移动端,也可以更省电
④后端生成静态文件。即生成缓存片段,这样就可以减少数据库查询浪费的时间,且对于数据变化不大的页面非常高效
坏处:
①不利于前后端分离,开发效率低
②占用服务器端资源