vue面试题

一、概念类
  1. vue.js是什么?
    vue.js是一个构建用户界面的渐进式框架。
  2. 怎么理解渐进式?
    主张少,没有那么多硬性规定。例如:angular必须使用它的模块机制,依赖注入、react的函数式编程理念。
  3. 什么是MVVM?
    MVVM是Model View ViewModel的缩写,Model是数据模型,View是视图,它们之间没有联系,是通过ViewModel来交互的。ViewModel层不需要我们去维护,由Vue统一管理。Model 和 ViewModel 之间的交互是双向的, 因此View 数据的变化会同步到Model中,而Model 数据的变化也会立即反应到View 上。
    image.png

    什么是MVC?
    View 传送指令到 Controller ---> Controller 完成业务逻辑后,要求 Model 改变状态 ----> Model 将新的数据发送到 View,用户得到反馈
    image
二、vue生命周期
  1. 什么是Vue的生命周期
    从vue开始创建实例到销毁的这个过程就是叫vue的生命周期。包括开始创建、初始化数据、渲染页面、销毁都是vue的生命周期。

  2. vue生命周期的作用
    在这个生命周期的过程中会有很多生命周期函数,可以通过操作这些生命周期函数来控制逻辑。

  3. 生命周期函数
    创建前/后, 载入前/后,更新前/后,销毁前/销毁后。
    beforeCreate("new Vue之前")、created("new Vue之后")、beforeMounted("el之前")、mounted("有了el之后")、beforedUpdate("更新数据之前")、updated("更新数据之后")、beforeDestroy("销毁之前")、destoryed("销毁之后")

  4. 第一次页面加载会触发哪几个钩子?
    会触发beforeCreate("new Vue之前")、created("new Vue之后")、beforeMounted("el之前")、mounted("有了el之后")

  5. DOM在哪个钩子函数中完成?
    在mounted中已经完成。

  6. 什么是vue的双向数据绑定?
    当我更新视图的数据也跟着改变,当我更新数据视图也跟着改变,例如当我文本框中输入了内容,则数据也发生了改变,当我改变数据,文本框内容也随之改变。

  7. vue的双向数据绑定原理是什么?
    vue的双向数据绑定是用数据劫持和发布者-订阅者模式结合来实现的。通过用Object.defineProprety对data中的每个属性的set和get进行劫持。当数据发生变化,发消息给订阅者,订阅者执行回调函数来更新视图


    image.png

a、实现一个数据监听器Observer,能够对vue中data里的所有属性进行监听,如有变动可拿到最新值并通知订阅者;因为属性可能是多个,所以会有多个订阅者,故我们需要一个消息订阅器Dep来专门收集这些订阅者。

b、实现一个订阅者Watcher,作为连接Observer和Compile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图;

c、实现一个指令解析器Compile,对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,初始化视图;

vue的数据双向绑定 将MVVM作为数据绑定的入口,整合Observer,Compile和Watcher三者,通过Observer来监听自己的model的数据变化,通过Compile来解析编译模板指令(vue中是用来解析 {{}}),最终利用watcher搭起observer和Compile之间的通信桥梁,达到数据变化 —>视图更新;视图交互变化(input)—>数据model变更双向绑定效果

三、vue组件间传值
  1. 父组件给子组件怎么传?
    在父组件中给子组件身上绑定属性,然后在子组件中用props接受数据;
  2. 子组件给父组件怎么传?
    在子组件中通过$emit方法传递参数,在父组件中通过执行子组件抛出的方法获取数据
  3. 非父子组件传值?
    可以通过总线的方式,通过在子组件1中this.bus.$emit('send',msg),触发事件,在子组件2中通过this.bus.$on('send',val=>{this.msg = val})
  4. 可以利用vuex来进行组件之间的传值
三、单页面vs多页面

SPA(单页面应用):指的就是只有一个主页面的应用,浏览器在一开始就必须加载所有的html,js,css,所有的页面内容都包含在这个主页面中,但是在写的时候还是会分开写(页面片段,例如.vue文件),在交互的时候通过路由(vue-router)动态加载,单页面的页面跳转,仅局部刷新页面。多应用于pc端,利于前后端分离
MPA(多页面应用):指的就是一个应用中有多个页面,页面跳转是整个页面刷新


image.png

SPA优缺点:
优点:页面切换快
缺点:首屏时间稍慢,SEO慢(首屏展示除了请求一次html还需要发js请求,都请求好了才会展示出来了,搜索引擎只认HTML,不认识js的内容,但是单页应用的内容都是靠js渲染出来的,不会给网页一个好的排名,在谷歌,但是可以通过vue提供的一些服务器渲染的内容改变单页的缺点)
页面跳转—>JS渲染
Js会感知到URL的变换,可以用js动态的把当前页面的内容清除掉,然后把另一个页面的内容挂到页面上,路由是由前端来控制,而不是后台来控制,所以每次切换的不会每次都请求http 请求了。

MPA优缺点:
优点:首屏时间快,SEO效果好(搜索引擎)
缺点:页面切换慢(因为每次切换的时候都会发一个http 请求)
页面跳转—>返回HTML

五、Vue-router

为了构建SPA(单页面应用),需要引入前端路由系统,这也就是Vue-router存在的意义,它的原理是通过改变网址,来实现页面的局部刷新。

两种模式:hash模式(默认)、history模式

  1. hash模式 —— 地址栏有#

比如:http://localhost:8080/#/Home,hash 的值为#/Home。它的特点在于:hash 虽然出现URL中,但不会被包含在HTTP请求中,对后端完全没有影响,因此改变hash不会重新加载页面。

2、history模式 —— 这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。比如:http://yoursite.com/user/id

不过这种模式还需要后台配置支持。因为我们的应用是个单页客户端应用,如果后台没有正确的配置,当用户在浏览器直接访问 http://oursite.com/user/id 就会返回 404,这就不好看了。

所以呢,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。

六、Vue-router钩子函数

主要分为三类:全局钩子(全局守卫)、单个路由独享的、或者组件内的。
1.全局钩子函数一般用来判断权限,以及页面丢失时候需要执行的操作;

const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
  // ...
})

router.afterEach((to, from) => {
  // ...
})
  • to: Route: 即将要进入的目标 路由对象

  • from: Route: 当前导航正要离开的路由

  • next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。

2.单个路由共享的主要用于写某个指定路由跳转时需要执行的逻辑

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        // ...
      },
      beforeLeave: (to, from, next) => {
        // ...
      },
    }
  ]
})

3.组件内的钩子

beforeRouteEnter(to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不能获取组件实例 `this`
// 因为当钩子执行前,组件实例还没被创建
},
beforeRouteUpdate(to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
},
beforeRouteLeave(to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
},

beforeRouteEnter 钩子 不能 访问 this,因为钩子在导航确认前被调用,因此组件还没被创建。

不过,你可以通过传一个回调给 next来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数。

beforeRouteEnter (to, from, next) {
  next(vm => {
    // 通过 `vm` 访问组件实例
  })
}

你可以 在 beforeRouteLeave 中直接访问 this。这个 leave 钩子通常用来禁止用户在还未保存修改前突然离开。可以通过 next(false) 来取消导航。同时注意必须有这个next()。

七、vuex是什么?怎么使用?

Vuex通俗来讲就是用来管理所有组件之间的通信。相当于一个中间仓库。

首先新建store-->index.js,然后在main.js中引入index.js,挂载到Vue实例中。

index.js

import Vue from "vue"
import Vuex from "vuex"
Vue.use(Vuex)
const state = {
    count: 1
}
const mutations = {   //管理同步
    add(state) {
        state.count += 1;
    },
    reduce(state,n) {
        state.count -= n
    }
}
const actions = {   //异步操作
    add({ commit }) {
        commit("add")
    },
    reduce(context, n) {
        context.commit("reduce", n)
    },
    odd({ commit }) {
        if (state.count % 2 == 0) {
            commit('add')
        }
    },
    sync({ commit }) {
        setTimeout(function(){
            commit('add')
        },1000)
    }
}
const getters = {   //计算属性
    count(state) {
        return state.count += 10;
    }
}
export default new Vuex.Store({
    state,
    mutations,
    // getters,
    actions
})

state,唯一的数据源,不可以直接修改,唯一方法是提交 mutation
mutations,必须是同步函数
actions,异步操作
getters,相当于计算属性,每次都会执行

在其他页面中可以用计算属性来获取state得值和getters的值,可以通过
this.$store.commit("add",参数)来提交同步方法,可以通过this.$store.dispatch("add",参数)来提交异步方法

八、vue中如何自定义指令
九、keep-alive

keep-alive是 Vue 内置的一个组件,可以缓存组件,使被包含的组件保留状态,或避免重新渲染。
在vue 2.1.0 版本之后,keep-alive新加入了两个属性: include(包含的组件缓存) 与 exclude(排除的组件不缓存,优先级大于include) 。

  1. 利用include、exclude属性
<keep-alive include="bookLists">
      <router-view></router-view>
</keep-alive>
<keep-alive exclude="indexLists">
      <router-view></router-view>
</keep-alive>

include属性表示只有bookLists的组件会被缓存,(注意是组件的名字,不是路由的名字)其它组件不会被缓存;exclude属性表示indexLists的组件不会被缓存,其它组件都会被缓存

2.利用meta属性

export default[
 {
  path:'/',
  name:'home',
  components:Home,
  meta:{
    keepAlive:true //需要被缓存的组件
 },
 {
  path:'/book',
  name:'book',
  components:Book,
  meta:{
     keepAlive:false //不需要被缓存的组件
 } 
]
<keep-alive>
    <router-view v-if="this.$route.meta.keepAlive">
        <!-- 这里是会被缓存的视图组件,比如 Home! -->
    </router-view>
</keep-alive>

<router-view v-if="!this.$route.meta.keepAlive">
    <!-- 这里是不被缓存的视图组件,比如 Book! -->
</router-view>

应用场景:当我们在列表页的时候滑动到中间部分,退出去在返回来还希望保持在刚才查看的中间部分而不是顶部。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • vue是什么? vue是构建数据驱动的web界面的渐进式框架。Vue.js 的目标是通过尽可能简单的 API 实现...
    九四年的风阅读 8,746评论 2 131
  • active-class是哪个组件的属性?嵌套路由怎么定义? vue-router模块的router-link组件...
    慢慢慢热型阅读 605评论 0 2
  • 1、active-class是哪个组件的属性?嵌套路由怎么定义? 答:vue-router模块的router-li...
    黄海佳阅读 1,925评论 1 38
  • 1、active-class是哪个组件的属性?嵌套路由怎么定义? 答:vue-router模块的router-li...
    强哥科技兴阅读 6,558评论 0 6
  • 休了两天,嗖嗖的就过来了,今天宫铭帅同学正常去上学,也没有特别的事情,我还是老样子,带着两个小朋友玩:一...
    指挥官阅读 214评论 0 4