vue面试题

2021-01-06  本文已影响0人  Grit_1024

(掌握)简单说下setTimeout(fn, 0)中的0代表的是什么?如果我想在vue实现此功能可以用什么方法代替

js运行是基于单线程的,意味着一段代码执行时,其他代码将进入队列等待,一旦线程有空闲就执行后续代码。如果代码中设定了一个setTimeout,那么浏览器便会在合适的时间,将代码插入任务队列,如果这个时间设为 0,就代表立即插入队列,但并不是立即执行,仍然要等待前面代码执行完毕。

所以setTimeout 并不能保证执行的时间,是否及时执行取决于 JavaScript 线程是拥挤还是空闲。

可以用Vue中的nextTick代替,nextTick是Vue的DOM更新队列的下一次更新完成时触发,也是能够确保DOM更新完毕,如果环境不支持的时候其实就是setTimeout(fn, 0)。

#(掌握)用Vue实现样式绑定,可以用class或者内联样式,最少写出2个?

<!-- 第一种绑定class -->
<div :class="['classA', 'classB']"></div>

<!-- 第二种绑定class -->
<div :class="{'classA': true, 'classB' : false}"></div>

<!-- 第一种绑定style -->
<div :style="{fontSize: '16px', color: 'red'}"></div>

<!-- 第二种绑定style -->
<div :style="[{fontSize: '16px', color: 'red'}]"></div>

#(掌握)refs 和el的用法

ref 有三种用法:

1、ref 加在普通的元素上,用this.$refs(ref值) 获取到的是dom元素。

2、ref 加在子组件上,用 this.refs 获取到的是组件实例,可以使用组件的所有方法。在使用方法的时候直接this.refs.XX。

vm.$el:

获取Vue实例关联的DOM元素;

比方说我这里想获取自定义组件tabControl,并获取它的OffsetTop,就需要先获取该组件。

在组件内设置 属性 ref='一个名称(tabControl2)', 然后 this.$refs.tabControl2,就拿到了该组件

切记:ref属性,而获取组件的时候要用$refs

获取 OffsetTop,组件不是DOM元素,是没有OffsetTop的,无法通过.OffsetTop来获取的。就需要通过$el来获取组件中的DOM元素:

this.tabOffsetTop=this.$refs.tabControl2.$el.offsetTop

#(掌握)一、简述Vue的生命周期

常用的有8个(生命周期不仅仅是8个),都是成对出现。分别是: beforeCreate阶段、created阶段; beforeMount阶段、mounted阶段; beforeUpdate阶段、updated阶段; beforeDestroy阶段、destroyed阶段; 分别为:创建前/后,载入前/后,更新前/后,销毁前/后。

#(掌握)二、第一次页面加载会触发哪几个钩子?

beforeCreate, created, beforeMount, mounted

#(掌握)三、Vue实现数据双向绑定的原理

vue实现数据双向绑定主要是:采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应监听回调。当把一个普通 Javascript 对象传给 Vue 实例来作为它的 data 选项时,Vue 将遍历它的属性,用 Object.defineProperty 将它们转为 getter/setter。用户看不到 getter/setter,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。

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

#(掌握)四、简单实现双向数据绑定

<body>
    <div id="app">
        <input type="text" id="txt">
        <p id="show"></p>
    </div>
</body>
<script type="text/javascript">
    var obj = {}
    Object.defineProperty(obj, 'txt', {
        get: function () {
            return obj
        },
        set: function (newValue) {
            document.getElementById('txt').value = newValue
            document.getElementById('show').innerHTML = newValue
        }
    })
    document.getElementById('txt').addEventListener('keyup', function (e) {
        obj.txt = e.target.value
    })
</script>

#(掌握)六、简单讲述vuex

vuex是专门为vue.js提供的一种状态管理模式,它采用的是集中式储存和管理所有组件的状态和数据,方便使用。

image

Vex有5种属性,分别是 state、getter、mutation、action、module:

1、state

Vuex 使用单一状态树,即每个应用将仅仅包含一个store 实例,但单一状态树和模块化并不冲突。存放的数据状态,不可以直接修改里面的数据。

2、getters

类似vue的计算属性,主要用来过滤一些数据。

3、mutations

mutations定义的方法动态修改Vuex 的 store 中的状态或数据。

4、actions

actions可以理解为通过将mutations里面处里数据的方法变成可异步的处理数据的方法,简单的说就是异步操作数据。view 层通过 store.dispath 来分发 action。

const store = new Vuex.Store({ //store实例
  state: {
    count: 0
  },
  mutations: {                
    increment (state) {
      state.count++
    }
  },
  actions: { 
    increment (context) {
      context.commit('increment')
    }
  }
})

5、modules

项目特别复杂的时候,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
 }

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

#(掌握)七、vue如何自定义一个过滤器

1、局部过滤器

Html:

<div id="app">
     <input type="text" v-model="msg" />
     {{msg| 过滤器名称 }}
</div>

JS:

var vm=new Vue({
    el:"#app",
    data:{
        msg:''
    },
    filters: {
      过滤器名称: function (value) {
        if (!value) return ''
        ...
        return value
      }
    }
})

2、全局过滤器

Vue.filter('过滤器名称', function (value) {
  if (!value) return ''
  ...
  return value
})

#(掌握)八、对keep-alive 的了解?

keep-alive 包裹动态组件时,会缓存不活动的组件实例,主要用于保留组件状态或避免重新渲染。

使用方法:

<keep-alive>
  <component>
    <!-- 该组件将被缓存! -->
  </component>
</keep-alive>

#(掌握)十一、Vue 组件 data 为什么必须是函数

每个实例可以维护一份被返回对象的独立的拷贝。data是一个函数的话,这样每复用一次组件,就会返回一份新的data,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据。而单纯的写成对象形式,就使得所有组件实例共用了一份data,就会造成一个变了全都会变的结果。

#(掌握)十二、Vue 中怎么自定义指令

1、全局注册

// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
  // 当被绑定的元素插入到 DOM 中时……
  inserted: function (el) {
    // 聚焦元素
    el.focus()
  }
})

2、局部注册

directives: {
  focus: {
    // 指令的定义
    inserted: function (el) {
      el.focus()
    }
  }
}

#(掌握)十三、nextTick 是做什么的

$nextTick 是在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后使用 $nextTick,则可以在回调中获取更新后的DOM。

#(掌握)十四、$route$router 的区别

$routerVueRouter 实例,想要导航到不同 URL,则使用 $router.push 方法

$route 为当前 router 跳转对象里面可以获取 namepathqueryparams

#(掌握)十五、vue-cli生成的项目文件夹assets和public(static) 的区别

vue-cli2生成的项目目录是static

vue-cli3以上生成的项目目录是public

assets和public(static) 都是存放静态资源的文件。项目所需要的静态文件、图片、样式文件都可以放在这两个文件夹下

在assets中存放的静态资源,在项目打包时会将这些静态资源与代码、index.html文件一起一同进行打包压缩,上传到服务器

在public(static)中存放的静态资源,不会被打包压缩格式化等流程,而是直接进入打包好的目录,直接上传到服务器

#(掌握)十六、DOM渲染在哪个周期中就已经完成

DOM 渲染在 mounted 中就已经完成了。

#(掌握)十七、VNode是什么?虚拟DOM是什么?

Vue在页面上渲染的节点,及其子节点称为“虚拟节点 (Virtual Node)”,简写为“VNode”。“虚拟 DOM”是由 Vue 组件树建立起来的整个 VNode 树的称呼。

#(掌握)十八、什么是RESTful API?怎么使用?

是一个api的标准,无状态请求。请求的路由地址是固定的,如果是tp5则先路由配置中把资源路由配置好。标准有:.post .put .delete

#(掌握)二十、如何让CSS只在当前组件中起作用?

将当前组件的<style> 修改为 <style scoped>

#(掌握)二十一、 修改第三方库的样式

/deep/ >>>

#(掌握)二十二 、那你能讲一讲MVVM吗?

MVVM是Model-View-ViewModel缩写,也就是把MVC中的Controller演变成ViewModel。Model层代表数据模型,View代表UI组件,ViewModel是View和Model层的桥梁,数据会绑定到viewModel层并自动将数据渲染到页面中,视图变化的时候会通知viewModel层更新数据。

#(掌握)单向数据流和双向数据流

单向数据流(Unidirectional data flow)方式使用一个上传数据流和一个下传数据流进行单向数据通信,两个数据流之间相互独立。单向数据流指只能从一个方向来修改状态。vuex(组件data -> action -> state->组件data)

与单向数据流对对应的是双向数据流(也叫双向绑定)。在双向数据流中,Model(可以理解为状态的集合) 中可以修改自己或其他Model的状态, 用户的操作(如在输入框中输入内容)也可以修改状态。这使改变一个状态有可能会触发一连串的状态的变化,最后很难预测最终的状态是什么样的。使得代码变得很难调试。

#(掌握)说一下MVC的理解?

mvc是模型(model)-视图(view)-控制器(controller)`的缩写,一种软件设计典范使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。`MVC对应Html,CSS,js。

#(掌握)二十三、那你知道Vue3.x响应式数据原理吗?

Vue3.x改用Proxy替代Object.defineProperty。因为Proxy可以直接监听对象和数组的变化,并且有多达13种拦截方法。并且作为新标准将受到浏览器厂商重点持续的性能优化

Proxy只会代理对象的第一层,那么Vue3又是怎样处理这个问题的呢?(拓展)

判断当前Reflect.get的返回值是否为Object,如果是则再通过reactive方法做代理, 这样就实现了深度观测。

监测数组的时候可能触发多次get/set,那么如何防止触发多次呢?(拓展)

我们可以判断key是否为当前被代理对象target自身属性,也可以判断旧值与新值是否相等,只有满足以上两个条件之一时,才有可能执行trigger。

#(掌握)二十四、再说一下vue2.x中如何监测数组变化

使用了函数劫持的方式,重写了数组的方法,Vue将data中的数组进行了原型链重写(push,pop,shift,unshift,splice...),指向了自己定义的数组原型方法。这样当调用数组api时,可以通知依赖更新。如果数组中包含着引用类型,会对数组中的引用类型再次递归遍历进行监控。这样就实现了监测数组变化。

#(掌握)二十五、Computed和Watch

Computed本质是一个具备缓存的watcher,依赖的属性发生变化就会更新视图。 适用于计算比较消耗性能的计算场景。当表达式过于复杂时,在模板中放入过多逻辑会让模板难以维护,可以将复杂的逻辑放入计算属性中处理。

Watch没有缓存性,更多的是观察的作用,可以监听某些数据执行回调。当我们需要深度监听对象中的属性时,可以打开deep:true选项,这样便会对对象中的每一项进行监听。这样会带来性能问题,优化的话可以使用字符串形式监听。

#(掌握)二十六.再说一下虚拟Dom以及key属性的作用

由于在浏览器中操作DOM是很昂贵的。频繁的操作DOM,会产生一定的性能问题。这就是虚拟Dom的产生原因

Vue2的Virtual DOM借鉴了开源库snabbdom的实现。

Virtual DOM本质就是用一个原生的JS对象去描述一个DOM节点。是对真实DOM的一层抽象。(也就是源码中的VNode类,它定义在src/core/vdom/vnode.js中。)

VirtualDOM映射到真实DOM要经历VNode的create、diff、patch等阶段。

「key的作用是尽可能的复用 DOM 元素。」

新旧 children 中的节点只有顺序是不同的时候,最佳的操作应该是通过移动元素的位置来达到更新的目的。

需要在新旧 children 的节点中保存映射关系,以便能够在旧 children 的节点中找到可复用的节点。key也就是children中节点的唯一标识。

#(掌握)二十七.Vue中组件生命周期调用顺序说一下

组件的调用顺序都是先父后子,渲染完成的顺序是先子后父

组件的销毁操作是先父后子,销毁完成的顺序是先子后父

加载渲染过程

父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount- >子mounted->父mounted

子组件更新过程

父beforeUpdate->子beforeUpdate->子updated->父updated

父组件更新过程

父 beforeUpdate -> 父 updated

销毁过程

父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

#(了解)二十八.SSR了解吗?

SSR也就是服务端渲染,也就是将Vue在客户端把标签渲染成HTML的工作放在服务端完成,然后再把html直接返回给客户端

SSR有着更好的SEO、并且首屏加载速度更快等优点。不过它也有一些缺点,比如我们的开发条件会受到限制,服务器端渲染只支持beforeCreatecreated两个钩子,当我们需要一些外部扩展库时需要特殊处理,服务端渲染应用程序也需要处于Node.js的运行环境。还有就是服务器会有更大的负载需求。

#(了解)在vuejs中实现防止模板渲染时闪烁的方法

[v-cloak] {
display: none;
} 
<div v-cloak>
{{ message }}
</div> 

#(了解)十九、聊聊你对Vue.js的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节点,里面有(标签名、子节点、文本等等)

#(了解)谈谈Vue.extend和Vue.component

Vue.extend返回的是一个扩展实例构造器,也就是预设了部分选项的Vue实例构造器。其主要用来服务于Vue.component

Vue.component()`会注册一个全局的组件,其会自动判断第二个传进来的是Vue继续对象(`Vue.extend`)还是普通对象(`{...}`),如果传进来的是普能对象的话会自动调用`Vue.extend

#(了解)九、vue常用的修饰符?

.prevent: 提交事件不再重载页面;

.stop: 阻止单击事件冒泡;

.self: 当事件发生在该元素本身而不是子元素的时候会触发;

.capture: 事件侦听,事件发生的时候会调用;

#(了解)十、什么是vue的计算属性?

在模板中放入太多的逻辑会让模板过重且难以维护,在需要对数据进行复杂处理,且可能多次使用的情况下,尽量采取计算属性的方式。好处:

① 使得数据处理结构清晰;

② 依赖于数据,数据更新,处理结果自动更新;

③ 计算属性内部this指向vm实例;

④ 在template调用时,直接写计算属性名即可;

⑤ 常用的是getter方法,获取数据,也可以使用set方法改变数据;

⑥ 相较于methods,不管依赖的数据变不变,methods都会重新计算,但是依赖数据不变的时候computed从缓存中获取,不会重新计算。

#(了解)五、Vue的路由实现

1、hash模式

在浏览器中符号“#”,#以及#后面的字符称之为hash,用window.location.hash读取; 特点:hash虽然在URL中,但不被包括在HTTP请求中;用来指导浏览器动作,对服务端安全无用,hash不会重加载页面。 hash 模式下,仅 hash 符号之前的内容会被包含在请求中,如 http://www.xxx.com (opens new window),因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回 404 错误。

2、history模式

history采用HTML5的新特性;且提供了两个新方法:pushState(),replaceState()可以对浏览器历史记录栈进行修改,以及popState事件的监听到状态变更。 history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致,如 http://www.xxx.com/items/id。后端如果缺少对 /items/id 的路由处理,将返回 404 错误。Vue-Router 官网里如此描述:“不过这种模式要玩好,还需要后台配置支持……所以呢,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。”

#(了解)vue-router 有几种导航钩子?

1、全局守卫: router.beforeEach

2、全局解析守卫: router.beforeResolve

3、全局后置钩子: router.afterEach

4、路由独享的守卫: beforeEnter

5、组件内的守卫: beforeRouteEnter、beforeRouteUpdate (2.2 新增)、beforeRouteLeave

上一篇下一篇

猜你喜欢

热点阅读