前端常见面试-vue篇

        前面,咱们已经针对前端的基础知识和常见的一些进阶知识都作了总体的梳理,而且也对缓存进行了单独的具体讲解,有须要的朋友可自行查看相关的文章,文章以下:前端常见面试-css篇前端常见面试-js篇前端常见面试-进阶篇前端常见面试-存储/缓存篇
        对于前端来讲,尽管css、html、js是主要的基础知识,可是随着技术的不断发展,出现了不少优秀的mv*框架以及小程序框架。所以,对于前端开发者而言,须要对一些前端框架进行熟练掌握。这篇文章咱们一块儿来聊一聊VUE及全家桶的常见面试问题。javascript

一、请讲述下VUE的MVVM的理解?

        MVVM 是 Model-View-ViewModel的缩写,即将数据模型与数据表现层经过数据驱动进行分离,从而只须要关系数据模型的开发,而不须要考虑页面的表现,具体说来以下:
        Model表明数据模型:主要用于定义数据和操做的业务逻辑。
        View表明页面展现组件(即dom展示形式):负责将数据模型转化成UI 展示出来。
        ViewModel为model和view之间的桥梁:监听模型数据的改变和控制视图行为、处理用户交互。经过双向数据绑定把 View 层和 Model 层链接了起来,而View 和 Model 之间的同步工做彻底是自动的,无需人为干涉
        在MVVM架构下,View 和 Model 之间并无直接的联系,而是经过ViewModel进行交互,Model 和 ViewModel 之间的交互是双向的, 所以View 数据的变化会同步到Model中,而Model 数据的变化也会当即反应到View 上。php

二、VUE的生命周期及理解?

        答:总共分为8个阶段,具体为:建立前/后,载入前/后,更新前/后,销毁前/后
        建立前/后: 在beforeCreated阶段:ue实例的挂载元素\$el和数据对象data都为undefined,还未初始化;在created阶段,vue实例的数据对象data有了,$el尚未。
        载入前/后:在beforeMount阶段,vue实例的$el和data都初始化了,但仍是挂载以前为虚拟的dom节点,data.message还未替换;在mounted阶段,vue实例挂载完成,data.message成功渲染。
        更新前/后:当data变化时,会触发beforeUpdate和updated方法。
        销毁前/后:在执行destroy方法后,对data的改变不会再触发周期函数,说明此时vue实例已经解除了事件监听以及和dom的绑定,可是dom结构依然存在。css

具体讲解及应用

        beforeCreate:在new一个vue实例后,只有一些默认的生命周期钩子和默认事件,其余的东西都还没建立,data和methods中的数据都尚未初始化。不能在这个阶段使用data中的数据和methods中的方法
        create:data 和 methods都已经被初始化好了,若是要调用 methods 中的方法,或者操做 data 中的数据,最先能够在这个阶段中操做
        beforeMount:执行到这个钩子的时候,在内存中已经编译好了模板了,可是尚未挂载到页面中,此时,页面仍是旧的,不能直接操做页面的dom和获取dom对象
        mounted:执行到这个钩子的时候,就表示Vue实例已经初始化完成了。此时组件脱离了建立阶段,进入到了运行阶段。 若是咱们想要经过插件操做页面上的DOM节点,最先能够在和这个阶段中进行
        beforeUpdate: 当执行这个钩子时,页面中的显示的数据仍是旧的,data中的数据是更新后的,页面尚未和最新的数据保持同步
        updated:页面显示的数据和data中的数据已经保持同步了,都是最新的
        beforeDestory:Vue实例从运行阶段进入到了销毁阶段,这个时候上全部的data和 methods、指令、过滤器 ……都是处于可用状态。尚未真正被销毁
        destroyed: 这个时候上全部的data和methods、指令、过滤器 ……都是处于不可用状态。组件已经被销毁了。html

三、v-if和v-show的区别?

        共同点:都能控制元素的显示和隐藏;
        不一样点:实现本质方法不一样,v-show本质就是经过控制css中的display设置为none,控制隐藏,只会编译一次;v-if是动态的向DOM树内添加或者删除DOM元素,若初始值为false,就不会编译了。并且v-if不停的销毁和建立比较消耗性能。
        若是要频繁切换某节点,使用v-show(切换开销比较小,初始开销较大)。若是不须要频繁切换某节点使用v-if(初始渲染开销较小,切换开销比较大)前端

四、v-if和v-for同时使用在同一个标签上的表现?

        当v-if与v-for一块儿使用时,v-for具备比v-if更高的优先级,这意味着v-if将分别重复运行于每一个v-for循环中。
        因此,不推荐v-if和v-for同时使用。若是v-if和v-for一块儿用的话,vue中的的会自动提示v-if应该放到外层去vue

五、v-for中的key的理解?

        须要使用key来给每一个节点作一个惟一标识,Diff算法就能够正确的识别此节点。主要是为了高效的更新虚拟DOM。java

六、vue中transition的理解?

        1)定义transition时须要设置对应的name,具体语法为:<transition name=“fade”>须要动画的内容或者组件或者页面</transition>
         2)过渡动画主要包含6个class,分别为:
                v-enter:定义元素进入过渡的初始状态,在元素插入前生效,插入后一帧删除,
                v-enter-active:在元素插入前生效,在动画完成后删除,
                v-enter-to:在元素插入后一帧生效,在动画完成后删除,
                v-leave:离开过渡的初始状态,在元素离开时生效,下一帧删除
                v-leave-active:在离开过渡时生效,在动画完成后删除
                v-leave-to:离开过渡结束状态,在离开过渡下一帧生效,在动画完成后删除
        ⚠️:v会转化为对应的transition的name值
        3)固然咱们也能够自定义这六个class 能够直接在transition中设置对应的属性为对应的class名称,属性有:enter-class,enter-active-class,enter-to-class,leave-class,leave-active-class,leave-to-class
        4)在同时使用过渡和css动画的时候 能够设置type属性来制定vue内部机制监听transitioned或者animationed事件来完成过渡仍是动画的监听
        5)若是须要设置对应的过渡时间,能够直接设置属性duration,能够直接接收一个数字(单位为毫秒),也能够接收一个对象{enter:1000,leave:300}
        6)也能够设置过渡的钩子函数,具体有:before-enter,enter,after-enter,enter-cancelled,before-leave,leave,after-leave,leave-cancellednode

七、vue的自定义指令?

        自定义指令分为全局指令和组件指令,其中全局指令须要使用directive来进行定义,组件指令须要使用directives来进行定义,具体定义方法同过滤器filter或者其余生命周期,具体使用方法以下:
        全局自定义指令 directive(name,{}),其中name表示定义的指令名称(定义指令的时候不须要带v-,可是在调用的时候须要哦带v-),第二个参数是一个对象,对象中包括五个自定义组件的钩子函数,具体包括:react

  1. bind函数:只调用一次,指令第一次绑定在元素上调用,即初始化调用一次,
  2. inserted函数:并绑定元素插入父级元素(即new vue中el绑定的元素)时调用(此时父级元素不必定转化为了dom)
  3. update函数:在元素发生更新时就会调用,能够经过比较新旧的值来进行逻辑处理
  4. componentUpdated函数:元素更新完成后触发一次
  5. unbind函数:在元素所在的模板删除的时候就触发一次

        钩子函数对应的参数el,binding,vnode,oldnode,具体参数讲解以下:
        a、el指令所绑定的元素 能够直接操组dom元素
        b、binding一个对象,具体包括如下属性:
                1)name:定义的指令名称 不包括v-
                2)value:指令的绑定值,若是绑定的是一个计算式,value为对应计算结果
                3)oldvalue:指令绑定元素的前一个值,只对update和componentUpdated钩子函数有值
                4)expression:指令绑定的原始值 不对值进行任何加工
                5)arg:传递给指令的参数
                6)modifiers:指令修饰符,如:v-focus.show.async 则接收的modifiers为{show:true,async:true}
        c、vnode:vue编译生成的虚拟dom
        d、oldVnode:上一个vnode,只在update和componentUpdated钩子函数中有效webpack

        ⚠️:若是不须要其余钩子函数,能够直接简写为:directive(“focus”,function(el,binding){})

八、vue的实现原理?

        vue.js 是采用数据劫持结合发布者-订阅者模式的方式,经过Object.defineProperty()来劫持各个属性的setter,getter,在数据变更时发布消息给订阅者,触发相应的监听回调。

具体步骤:

        第一步:须要observe的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter和getter
这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化
        第二步:compile解析模板指令,将模板中的变量替换成数据,而后初始化渲染页面视图,并将每一个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变更,收到通知,更新视图
        第三步:Watcher订阅者是ObserverCompile之间通讯的桥梁,主要作的事情是:
一、在自身实例化时往属性订阅器(dep)里面添加本身
二、自身必须有一个update()方法
三、待属性变更dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调,则功成身退。
        第四步:MVVM做为数据绑定的入口,整合ObserverCompileWatcher三者,经过Observer来监听本身的model数据变化,经过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通讯桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据model变动的双向绑定效果。

九、vue的diff算法理解?

        1)diff算法的做用:用来修改dom的一小段,不会引发dom树的重绘
        2)diff算法的实现原理:diff算法将virtual dom的某个节点数据改变后生成的新的vnode与旧节点进行比较,并替换为新的节点,具体过程就是调用patch方法,比较新旧节点,一边比较一边给真实的dom打补丁进行替换
        3)具体过程详解:

        a、在采用diff算法进行新旧节点进行比较的时候,比较是按照在同级进行比较的,不会进行跨级比较:
image.png
        b、当数据发生改变的时候,set方法会调用dep.notify通知全部的订阅者watcher,订阅者会调用patch函数给响应的dom进行打补丁,从而更新真实的视图
        c、patch函数接受两个参数,第一个是旧节点,第二个是新节点,首先判断两个节点是否值得比较,值得比较则执行patchVnode函数,不值得比较则直接将旧节点替换为新节点。若是两个节点同样就直接检查对应的子节点,若是子节点不同就说明整个子节点所有改变再也不往下对比直接进行新旧节点的总体替换
        d、patchVnode函数:找到真实的dom元素;判断新旧节点是否指向同一个对象,若是是就直接返回;若是新旧节点都有文本节点,那么直接将新的文本节点赋值给dom元素而且更新旧的节点为新的节点;若是旧节点有子节点而新节点没有,则直接删除dom元素中的子节点;若是旧节点没有子节点,新节点有子节点,那么直接将新节点中的子节点更新到dom中;若是二者都有子节点,那么继续调用函数updateChildren
        e、updateChildren函数:抽离出新旧节点的全部子节点,而且设置新旧节点的开始指针和结束指针,而后进行两辆比较,从而更新dom(调整顺序或者插入新的内容 结束后删掉多余的内容)

十、vue组件的通讯(父子组件和非父子组件)?
父子组件通讯

        传递参数可使用props,传递函数能够直接在调用子组件的时候传递自定义事件,并使用$emit来调用,例如:

//父组件
<div classs="parent">
   <child @getinfo="myname" :userinfo="usermessage"></child>
 <div>
 export default {
     data(){
         return {
             usermessage:'我是父亲'
         }
     },
     methods:{
         myname(name){
             console.log('个人名字叫'+name)
         }
     }
 }
 
//子组件
<div classs="child">
   来源:{{userinfo}}
   <button @click="getname">显示个人名字</button>
 <div>
 export default {
     props:['userinfo'],
     methods:{
         getname(){
           this.$emit('getinfo','bilibili')
         }
     }
 }
兄弟组件通讯

        首先创建一个vue实例空白页(js文件)

import Vue from 'vue'
      export default new Vue()

        组件a(数据发送方)经过使用 $emit 自定义事件把数据带过去

<template>
    <div>
        <span>A组件->{{msg}}</span>
        <input type="button" value="把a组件数据传给b" @click ="send">
    </div>
</template>
<script>
import vmson from "../../../util/emptyVue"
export default {
    data(){
        return {
            msg:{
                a:'111',
                b:'222'
            }
        }
    },
    methods:{
        send:function(){
            vmson.$emit("aevent",this.msg)
        }
    }
}
</script>

        组件b(数据接收方)使用而经过 $on监听自定义事件的callback接收数据

<template>
 <div>
    <span>b组件,a传的的数据为->{{msg}}</span>
 </div>
</template>
<script>
      import vmson from "../../../util/emptyVue"
      export default {
         data(){
                return {
                    msg:""
                }
            },
         mounted(){
                vmson.$on("aevent",(val)=>{//监听事件aevent,回调函数要使用箭头函数;
                    console.log(val);//打印结果:我是a组件的数据
                    this.msg = val;
                })
          }
    }
</script>
十一、vue的路由模式及区别?
hash模式在浏览器中符号“#”,#以及#后面的字符称之为hash,用window.location.hash读取;

        特色:hash虽然在URL中,但不被包括在HTTP请求中;用来指导浏览器动做,对服务端安全无用,hash不会重加载页面。

history模式:history采用HTML5的新特性;

        提供了两个新方法:pushState(),replaceState()能够对浏览器历史记录栈进行修改,以及popState事件的监听到状态变动。history 模式下,前端的 URL必须和实际向后端发起请求的URL一致,不然会报404错误

十二、vue与react、angular的比较?
vue

轻量级框架:只关注视图层,是一个构建数据的视图集合,大小只有几十kb;
简单易学:国人开发,中文文档,不存在语言障碍 ,易于理解和学习;
双向数据绑定:保留了angular的特色,在数据操做方面更为简单;
组件化:保留了react的优势,实现了html的封装和重用,在构建单页面应用方面有着独特的优点;
视图,数据,结构分离:使数据的更改更为简单,不须要进行逻辑代码的修改,只须要操做数据就能完成相关操做;
虚拟DOM:dom操做是很是耗费性能的, 再也不使用原生的dom操做节点,极大解放dom操做,但具体操做的仍是dom不过是换了另外一种方式;
运行速度更快:相比较与react而言,一样是操做虚拟dom,就性能而言,vue存在很大的优点。

react

相同点:
        React采用特殊的JSX语法,Vue.js在组件开发中也推崇编写.vue特殊文件格式,对文件内容都有一些约定,二者都须要编译后使用;中心思想相同:一切都是组件,组件实例之间能够嵌套;都提供合理的钩子函数,可让开发者定制化地去处理需求;都不内置列数AJAX,Route等功能到核心包,而是以插件的方式加载;在组件开发中都支持mixins的特性。
不一样点:
        React采用的Virtual DOM会对渲染出来的结果作脏检查;Vue.js在模板中提供了指令,过滤器等,能够很是方便,快捷地操做Virtual DOM。

angular

相同点:
        都支持指令:内置指令和自定义指令;都支持过滤器:内置过滤器和自定义过滤器;都支持双向数据绑定;都不支持低端浏览器。
不一样点:
        AngularJS的学习成本高,好比增长了Dependency Injection特性,而Vue.js自己提供的API都比较简单、直观;在性能上,AngularJS依赖对数据作脏检查,因此Watcher越多越慢;Vue.js使用基于依赖追踪的观察而且使用异步队列更新,全部的数据都是独立触发的。

1三、vue-roter的钩子函数?

vue路由钩子大体能够分为三类:

全局钩子

        主要包括beforeEach和aftrEach,beforeEach函数有三个参数:
        to:router即将进入的路由对象
        from:当前导航即将离开的路由
        next:Function,进行管道中的一个钩子,若是执行完了,则导航的状态就是 confirmed (确认的);不然为false,终止导航。
        afterEach函数不用传next()函数这类钩子主要做用于全局,通常用来判断权限,以及以及页面丢失时候须要执行的操做,例如:

//使用钩子函数对路由进行权限跳转
router.beforeEach((to, from, next) => {
    const role = localStorage.getItem('ms_username');
    if(!role && to.path !== '/login'){
        next('/login');
    }else if(to.meta.permission){
        // 若是是管理员权限则可进入,这里只是简单的模拟管理员权限而已
        role === 'admin' ? next() : next('/403');
    }else{
        // 简单的判断IE10及如下不进入富文本编辑器,该组件不兼容
        if(navigator.userAgent.indexOf('MSIE') > -1 && to.path === '/editor'){
            Vue.prototype.$alert('vue-quill-editor组件不兼容IE10及如下浏览器,请使用更高版本的浏
            览器查看', '浏览器不兼容通知', {
                confirmButtonText: '肯定'
            });
        }else{
            next();
        }
    }
})
2)单个路由里面的钩子

        主要用于写某个指定路由跳转时须要执行的逻辑

3)组件路由

        主要包括 beforeRouteEnter和beforeRouteUpdate ,beforeRouteLeave,这几个钩子都是写在组件里面也能够传三个参数(to,from,next),做用与前面相似.

beforeRouteEnter(to, from, next) {
    next(vm => {
      if (
        vm.$route.meta.hasOwnProperty('auth_key') &&
        vm.$route.meta.auth_key != ''
      ) {
        if (!vm.hasPermission(vm.$route.meta.auth_key)) {
          vm.$router.replace('/admin/noPermission')
        }
      }
    })
  }
1四、vuex的使用?

        Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的全部组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化,具体包括:
        1)state:Vuex 使用单一状态树,即每一个应用将仅仅包含一个store 实例,但单一状态树和模块化并不冲突。存放的数据状态,不能够直接修改里面的数据。
        2)getter:state的计算属性,相似vue的计算属性,主要用来过滤一些数据。
        3)action:actions能够理解为经过将mutations里面处里数据的方法变成可异步的处理数据的方法,简单的说就是异步操做数据。view 层经过 store.dispath 来分发 action。能够异步函数调用
        4)mutation:mutations定义的方法动态修改Vuex 的 store 中的状态或数据
        5)modules:项目特别复杂的时候,可让每个模块拥有本身的state、mutation、action、getters,使得结构很是清晰,方便管理。

1五、vue的filter的理解与用法?

        1)全局过滤器必须写在vue实例建立以前

Vue.filter('testfilter', function (value,text) { // 返回处理后的值
   return value+text
   })

        2)局部写法:在组件实例对象里挂载。

filters: {
        changemsg:(val,text)\=>{ return val + text
        }
    },

        3)使用方式:只能使用在{{}}和:v-bind中,定义时第一个参数固定为预处理的数,后面的数为调用时传入的参数,调用时参数第一个对应定义时第二个参数,依次日后类推

<h3 :title="test|changemsg(1234)">{{test|changemsg(4567)}}</h3>  
//多个过滤器也能够串行使用  
<h2>{{name|filter1|filter2|filter3}}</h2>

        4)vue-cli项目中注册多个全局过滤器写法:

//1.建立一个单独的文件定义并暴露函数对象
const filter1 = function (val) {
  return val + '--1'
}
const filter2 = function (val) {
  return val + '--2'
}
const filter3 = function (val) {
  return val + '--3'
}

export default {
  filter1,
  filter2,
  filter3
}

//2.导入main.js(在vue实例以前)
import filters from './filter/filter.js'

//3.循环注册过滤器
Object.keys(filters).forEach(key=>{
  Vue.filter(key,filters[key])
})
1六、vue的keep-alive的理解?

        keep-alive 是Vue内置的一个组件,可使被包含的组件保留状态,或避免从新渲染,页面第一次进入,钩子的触发顺序:created-> mounted-> activated,退出时触发 deactivated ,当再次进入(前进或者后退)时,只触发activated事件挂载的方法等,只执行一次的放在 mounted 中;组件每次进去执行的方法放在 activated 中;其有几个属性以下:
         1)include - 字符串或正则表达式,只有名称匹配的组件会被缓存
         2)exclude - 字符串或正则表达式,任何名称匹配的组件都不会被缓存
        3)include 和 exclude 的属性容许组件有条件地缓存。两者均可以用“,”分隔字符串、正则表达式、数组。当使用正则或者是数组时,要记得使用v-bind 。

<!-- 逗号分隔字符串,只有组件a与b被缓存。 -->
<keep-alive include="a,b">
  <component></component>
</keep-alive>

<!-- 正则表达式 (须要使用 v-bind,符合匹配规则的都会被缓存) -->
<keep-alive :include="/a|b/">
  <component></component>
</keep-alive>

<!-- Array (须要使用 v-bind,被包含的都会被缓存) -->
<keep-alive :include="['a', 'b']">
  <component></component>
</keep-alive>
1七、如何封装一个vue组件?

        根据业务需求,创建组件的模板,先把架子搭起来,写写样式,考虑好组件的基本逻辑。
        准备好组件的数据输入。即分析好逻辑,定好 props 里面的数据、类型。
        准备好组件的数据输出。即根据组件逻辑,作好要暴露出来的方法。
        封装完毕了,直接调用便可

1八、vue首屏白屏如何解决?

        1)路由懒加载
        2)vue-cli开启打包压缩 和后台配合 gzip访问
        3)进行cdn加速
        4)开启vue服务渲染模式
        5)用webpack的externals属性把不须要打包的库文件分离出去,减小打包后文件的大小
        6)在生产环境中删除掉没必要要的console.log

plugins: [
    new webpack.optimize.UglifyJsPlugin({ //添加-删除console.log
      compress: {
        warnings: false,
        drop_debugger: true,
        drop_console: true
      },
      sourceMap: true
    }),

        7)开启nginx的gzip ,在nginx.conf配置文件中配置

http {  //在 http中配置以下代码,
   gzip on;
   gzip_disable "msie6"; 
   gzip_vary on; 
   gzip_proxied any;
   gzip_comp_level 8; #压缩级别
   gzip_buffers 16 8k;
   #gzip_http_version 1.1;
   gzip_min_length 100; #不压缩临界值
   gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
 }

        8)添加loading效果,给用户一种进度感觉

1九、vue中的v-cloak的理解?

        使用 v-cloak 指令设置样式,这些样式会在 Vue 实例编译结束时,从绑定的 HTML 元素上被移除。
        通常用于解决网页闪屏的问题,在对一个的标签中使用v-cloak,而后在样式中设置[v-cloak]样式, [v-cloak] 需写在 link 引入的css中,或者写一个内联css样式,写在import引入的css中不起做用。

20、vue中template编译的理解?

        答:就是先转化成AST树,再获得的render函数返回VNode(Vue的虚拟DOM节点),具体为:
        首先,经过compile编译器把template编译成AST语法树(abstract syntax tree 即 源代码的抽象语法结构的树状表现形式),compile是createCompiler的返回值,createCompiler是用以建立编译器的。另外compile还负责合并option。
        而后,AST会通过generate(将AST语法树转化成render funtion字符串的过程)获得render函数,render的返回值是VNode,VNode是Vue的虚拟DOM节点,里面有(标签名、子节点、文本等等)

2一、v-model的理解?

        答:v-model用于表单数据的双向绑定,其实它就是一个语法糖,这个背后就作了两个操做:
        1)v-bind绑定一个value属性;
        2)v-on指令给当前元素绑定input事件

2二、computed和watch的用法和区别?
computed

        1)变量不在 data中定义,而是定义在computed中,写法跟写方法同样,有返回值。函数名直接在页面模板中渲染,不加小括号 。
        2)根据传入的变量的变化 进行结果的更新。
        3)计算属性基于响应式依赖进行缓存。如其中的任意一个值未发生变化,它调用的就是上一次计算缓存的数据,所以提升了程序的性能。而methods中每调用一次就会从新计算一次,为了进行没必要要的资源消耗,选择用计算属性。

watch

        1)计算属性的时候 初始化的时候就能够被监听到而且计算 可是watch是发生改变的时候才会触发。
        2)当有一些数据须要随着其它数据变更而变更时,或者当须要在数据变化时执行异步或开销较大的操做时,使用 watch。

总结:

        1)计算属性变量在computed中定义,属性监听在data中定义。
        2)计算属性是声明式的描述一个值依赖了其余值,依赖的值改变后从新计算结果更新DOM。属性监听的是定义的变量,当定义的值发生变化时,执行相对应的函数。

2三、$nextTick的使用?

        答:在vue中理解修改数据后,对应的dom须要必定的时间进行更新,所以为了可以准确的后去更新后的dom,能够采用延迟回调的方法进行更新dom的获取,因此出现了$nextTick来进行延迟回调。即:在下次 DOM 更新循环结束以后执行延迟回调。在修改数据以后当即使用这个方法,获取更新后的 DOM。

2四、data为何是一个函数?

        答:这是有JavaScript的特性所致使,在component中,data必须以函数的形式存在,不能够是对象。
        组建中的data写成一个函数,数据以函数返回值的形式定义,这样每次复用组件的时候,都会返回一份新的data,至关于每一个组件实例都有本身私有的数据空间,它们只负责各自维护的数据,不会形成混乱。而单纯的写成对象形式,就是全部的组件实例共用了一个data,这样改一个全都改了。

2五、vue单页面和传统的多页面区别?
单页面应用(SPA)

        通俗一点说就是指只有一个主页面的应用,浏览器一开始要加载全部必须的 html, js, css。全部的页面内容都包含在这个所谓的主页面中。但在写的时候,仍是会分开写(页面片断),而后在交互的时候由路由程序动态载入,单页面的页面跳转,仅刷新局部资源。多应用于pc端。

多页面(MPA)

        指一个应用中有多个页面,页面跳转时是整页刷新

单页面的优势:

        用户体验好,快,内容的改变不须要从新加载整个页面,基于这一点spa对服务器压力较小;先后端分离;页面效果会比较炫酷(好比切换页面内容时的专场动画)。

单页面缺点:

        不利于seo;导航不可用,若是必定要导航须要自行实现前进、后退。(因为是单页面不能用浏览器的前进后退功能,因此须要本身创建堆栈管理);初次加载时耗时多;页面复杂度提升不少。

2六、vue经常使用的修饰符?

        .stop:等同于JavaScript中的event.stopPropagation(),防止事件冒泡;
        .prevent:等同于JavaScript中的event.preventDefault(),防止执行预设的行为(若是事件可取消,则取消该事件,而不中止事件的进一步传播);
        .capture:与事件冒泡的方向相反,事件捕获由外到内;
        .self:只会触发本身范围内的事件,不包含子元素;
        .once:只会触发一次。

2七、vue更新数组时触发视图更新的方法?

        答:push();pop();shift();unshift();splice(); sort();reverse()

2八、$route和$router的区别?
$router

        router是VueRouter的一个对象,经过Vue.use(VueRouter)和VueRouter构造函数获得一个router的实例对象,这个对象中是一个全局的对象,他包含了全部的路由包含了许多关键的对象和属性,常见的有:
        1)push:向 history 栈添加一个新的记录,当咱们点击浏览器的返回按钮时能够看到以前的页面

// 字符串
   this.$router.push('home')
// 对象
   this.$router.push({ path: 'home' })
// 命名的路由
   this.$router.push({ name: 'user', params: { userId: 123 }})
// 带查询参数,变成 /register?plan=123
   this.$router.push({ path: 'register', query: { plan: '123' }})

        2)go:页面路由跳转 前进或者后退

// 页面路由跳转 前进或者后退
this.$router.go(-1) // 后退

        3)replace:push方法会向 history 栈添加一个新的记录,而replace方法是替换当前的页面,不会向 history 栈添加一个新的记录

$route

        &dollar;route对象表示当前的路由信息,包含了当前URL解析获得的信息。包含当前的路径、参数、query对象等。
        1)&dollar;route.path:字符串,对应当前路由的路径,老是解析为绝对路径,如 "/foo/bar"。
        2)&dollar;route.params:一个 key/value 对象,包含了 动态片断 和 全匹配片断,若是没有路由参数,就是一个空对象。
        3)&dollar;route.query:一个 key/value 对象,表示 URL 查询参数。例如,对于路径 /foo?user=1,则有 $route.query.user == 1,若是没有查询参数,则是个空对象。
        4)&dollar;route.hash:当前路由的 hash 值 (不带#) ,若是没有 hash 值,则为空字符串。
        5.&dollar;route.fullPath:完成解析后的 URL,包含查询参数和 hash 的完整路径。
        6&dollar;route.matched:数组,包含当前匹配的路径中所包含的全部片断所对应的配置参数对象。
        7.&dollar;route.name:当前路径名字
        8.&dollar;route.meta:路由元信息

2九、vue-router实现懒加载的方式?
vue异步组件

        vue异步组件技术 ==== 异步加载
        vue-router配置路由 , 使用vue的异步组件技术 , 能够实现按需加载 。可是,这种状况下一个组件生成一个js文件

/* vue异步组件技术 */
{
  path: '/home',
  name: 'home',
  component: resolve => require(['@/components/home'],resolve)
},{
  path: '/index',
  name: 'Index',
  component: resolve => require(['@/components/index'],resolve)
},{
  path: '/about',
  name: 'about',
  component: resolve => require(['@/components/about'],resolve)
}
es提案的import()

        路由懒加载(使用import)

// 下面2行代码,没有指定webpackChunkName,每一个组件打包成一个js文件。
/* const Home = () => import('@/components/home')
const Index = () => import('@/components/index')
const About = () => import('@/components/about') */
// 下面2行代码,指定了相同的webpackChunkName,会合并打包成一个js文件。 把组件按组分块
const Home =  () => import(/* webpackChunkName: 'ImportFuncDemo' */ '@/components/home')
const Index = () => import(/* webpackChunkName: 'ImportFuncDemo' */ '@/components/index')
const About = () => import(/* webpackChunkName: 'ImportFuncDemo' */ '@/components/about')
{
  path: '/about',
  component: About
}, {
  path: '/index',
  component: Index
}, {
  path: '/home',
  component: Home
}
webpack的require,ensure()

        vue-router配置路由,使用webpack的require.ensure技术,也能够实现按需加载。这种状况下,多个路由指定相同的chunkName,会合并打包成一个js文件。

/* 组件懒加载方案三: webpack提供的require.ensure() */
{
  path: '/home',
  name: 'home',
  component: r => require.ensure([], () => r(require('@/components/home')), 'demo')
}, {
  path: '/index',
  name: 'Index',
  component: r => require.ensure([], () => r(require('@/components/index')), 'demo')
}, {
  path: '/about',
  name: 'about',
  component: r => require.ensure([], () => r(require('@/components/about')), 'demo-01')
}
30、delete和Vue.delete删除数组的区别?

        答:delete只是被删除的元素变成了 empty/undefined 其余的元素的键值仍是不变。Vue.delete 直接删除了数组 改变了数组的键值。

3一、路由跳转和location.href的区别?

        使用location.href='/url'来跳转,简单方便,可是刷新了页面;
        使用路由方式跳转,无刷新页面,静态跳转;

3二、vue的solt的用法?

        在子组件内使用特殊的<slot>元素就能够为这个子组件开启一个slot(插槽),在父组件模板里,插入在子组件标签内的全部内容将替代子组件的<slot> 标签及它的内容。
        简单说来就是:在子组件内部用 <slot></slot>标签占位,当在父组件中使用子组件的时候,咱们能够在子组件中插入内容,而这些插入的内容则会替换 <slot></slot>标签的位置
        固然:单个solt的时候能够不对solt进行命名,若是存在多个 则一个能够不命名,其余必须命名,在调用的时候指定名称的对应替换slot,没有指定的则直接默认无名称的solt

3三、\$emit 、\$on 、\$once 、\$off理解?
$emit

        触发当前实例上的自定义事件(并将附加参数都传给监听器回调)

$on

        监听实例上自定义事件并调用回调函数,监听emit触发的事件

$once

        监听一个自定义事件,可是只触发一次,在第一次触发以后移除监听器。

$off

        用来移除自定义事件监听器。若是没有提供参数,则移除全部的事件监听器;若是只提供了事件,则移除该事件全部的监听器;若是同时提供了事件与回调,则只移除这个回调的监听器。
        这四个方法的实现原理是:经过对vue实例挂载,而后分别使用对象存储数组对应的函数事件,其中emit经过循环查找存储的数组中对应的函数进行调用,once只匹配一次就就结束,on是将对应的函数存储到数组中,off是删除数组中指定的元素或者全部的元素事件。具体能够参考文章:VUE $on/$emit实现

3四、\$root、\$refs、\$parent的使用?
$root

        能够用来获取vue的根实例,好比在简单的项目中将公共数据放再vue根实例上(能够理解为一个全局 store ),所以能够代替vuex实现状态管理;

$refs

        在子组件上使用ref特性后,this.$refs属性能够直接访问该子组件。能够代替事件$emit 和$on 的做用。使用方式是经过ref特性为这个子组件赋予一个ID引用,再经过this.\$refs.testId获取指定元素。注意:\$refs只会在组件渲染完成以后生效,而且它们不是响应式的。这仅做为一个用于直接操做子组件的“逃生舱”——你应该避免在模板或计算属性中访问\$refs。

$parent

        $parent 属性能够用来从一个子组件访问父组件的实例,能够替代将数据以 prop 的方式传入子组件的方式;当变动父级组件的数据的时候,容易形成调试和理解难度增长;

3五、vue开发遇到的问题?
1)样式污染

        答:在编写样式中,若是须要防止样式的污染,可使用两种方式,一种是在组件的根元素上增长一个惟一的class或者id,而后在编写组件的样式时候在根元素对应的class或者id下进行编写;另外一种方式是在对应的style上添加scoped关键字,不过该关键字对引用的框架UI无效

2)router-link在安卓上不起做用

        答:不起做用的缘由是由于转码编译的问题,可使用babel来进行处理,安装babel polypill插件解决

3)初始化页面出现闪屏乱码的问题

        答:这是由于vue尚未解析的状况下会容易出现花屏现象,看到相似于{{data}}的字样,可使用两种方式来进行处理,一种为:在设置index.html的根元素的元素的样式为display:none,而后在mounted中的$nextTick函数中display:block展现;另外一种方式是使用vue的内置指令:v-cloak,而且在css中设置样式

[v-cloak] {  
    display: none;  
}
4)router-link上事件无效解决方法

        答:使用@click.native来进行调用原生的js事件。缘由:router-link会阻止click事件,.native指直接监听一个原生事件。

相关文章
相关标签/搜索