前端面试题之Vue

对SPA单页面的理解,它的优缺点分别是什么

SPA在Web页面初始化时加载相应的HTML、CSS、JavaScript。一旦页面加载完成,SPA不会因为用户的操作而进行页面的重新加载或跳转。取而代之的是利用路由机制实现HTML内容的变换,UI与用户的交互,避免页面的重新加载。

优点:

  1. 用户体验好且快,内容的改变不需要重新加载整个页面,避免了不必要的跳转和重复的渲染;
  2. SPA单页面对服务器的压力小;
  3. 前后端职责分离,架构清晰,前端进行交互逻辑,后端负责数据处理。

缺点:

  1. 初次加载比较耗时:为实现单页Web应用功能及显示效果,需要在加载页面的时候将CSS、JavaScript这些都统一加载,部分页面按需加载;
  2. 前进后退路由管理:由于单页应用在一个页面中显示所有的内容,所以不能使用浏览器的前进后退功能,所有的页面切换需要自己建立堆栈来管理;
  3. SEO难度较大:由于所有的内容都在一个页面中动态替换显示,所以在SEO上比较弱。

Vue的生命周期有哪些

  1. 创建:beforeCreate,created;
  2. 载入:beforeMount,mounted;
  3. 更新:beforeUpdate,updated;
  4. 销毁:beforeDestroy,destroyed。

生命周期示意图:


第一次页面加载会触发哪几个钩子

beforeCreate、created、beforeMount、mounted


每一个周期具体适合哪些场景

  1. beforeCreate:在 new 一个 Vue 实例后,只有一些默认的生命周期钩子和默认事件,其他的东西都还没创建。不能获取 DOM 节点。data 和 methods 中的数据都还没有初始化,不能在这个阶段使用 data 中的数据和 methods 中的方法。
  2. created:实例已经创建,仍不能获取 DOM 节点,data 和 methods 都已经被初始化好了,如果要调用 methods 中的方法,或者操作 data 中的数据,最早可以在这个阶段里操作。
  3. beforeMount:在内存中已经编译好模板了,但是还没有挂载到页面中,此时,页面还是旧的。
  4. mounted:Vue 实例已经初始化完成了,此时组件脱离了创建阶段,进入到运行阶段。如果我们想要通过插件操作页面上的 DOM 节点,最早可以在这个阶段中进行。
  5. beforeUpdate:当执行这个钩子时,页面中的显示的数据还是旧的,data 中的数据是更新后的,页面还没有和最新的数据保持同步。
  6. updated:页面显示的数据和 data 中的数据已经保持同步了,都是最新的。
  7. beforeDestroy:Vue 实例从运行阶段进入到了销毁阶段,这个时候所有的 data、methods、指令、过滤器等等都是处于可用状态,还没有真正被销毁。
  8. destroyed:组件已经被销毁,无法操作里面的任何东西了。

Vue获取数据一般在哪个周期函数

在 created、beforeMount、mounted 中都可以。

不要在 updated 里更新数据。


怎样让CSS只在当前组件中生效

在组件中的 style 标签上加上 scoped。

<style scoped>

</style>

如何获取DOM

  1. 原生 JS 获取;
  2. ref 获取;
// 1. 原生 JS 获取
<div class="getDom"></div>

mounted() {
  let getDom = document.querySelector(".getDom")
}
// 2. ref 获取
<div ref="getDom"></div>

mounted() {
  let getDom = this.$refs.getDom
}

Vue常用的指令有哪些

  • v-html:会将html代码解析出来并进行渲染
  • v-text:输出文本
  • v-if:条件判断指令
  • v-show:是否隐藏元素
  • v-for:循环指令
  • v-bind:属性绑定指令(数据的单向绑定)
  • v-model:实现数据的双向绑定
  • v-on:绑定事件指令
  • v-once:表示元素和组件只会渲染一次
  • v-pre、v-cloak

v-show与v-if的区别

  1. v-show的本质是改变display的值。
  2. v-if是动态向DOM树内添加或者删除DOM元素。

v-show就是控制CSS的display,而v-if是不停的销毁和创建,因此如果需要频繁切换使用v-show性能会更好一点。


v-if和v-for的优先级是什么

根据 官方文档 所描述的:不推荐同时使用 v-if 和 v-for。如果 v-if 与 v-for 一起使用时,v-for 具有比 v-if 更高的优先级。

这也就意味着 v-if 将分别重复运行于每个 v-for 循环中。因此是不推荐将这个两个指令同时使用。


vue-loader是什么及用途

vue-loader 是解析 .vue 文件的一个加载器,它可以将 template / js / style 转换成 JS 模块。

⽤途:JS 可以写 ES6、style 样式可以 scss / less、template 可以加 jade 等等。


什么是MVVM

MVVM是Model-View-ViewModel的缩写,它是一种设计思想。

  • Model层代表数据模式,也可以在Model中定义数据修改和操作的业务逻辑
  • View代表UI组件,它负责将数据模型转化为UI展现出来
  • ViewModel是一个同步View和Model的对象

阮一峰 - MVC,MVP和MVVM的图示

维基百科


Vue组件之间如何通信

props / $emit

父传子 - props

<div id="app">
  <cpn :cgame="games" :cmsg="msg"></cpn>
</div>
<template id="cpn">
  <div>
    <ul>
      <li v-for="item in cgame">{{item}}</li>
    </ul>
    <div>{{cmsg}}</div>
  </div>
</template>
var app = new Vue({
  el: '#app',
  data: {
    msg: '父传子',
    games: ['tlbb', 'yxlm', 'cyhx']
  },
  components: {
    cpn: {
      template: '#cpn',
      props: ['cgame', 'cmsg']
    }
  }
})

子传父 - $emit

子传父自定义事件:$emit("自定义事件名",自定义事件传递的参数)

<div id="app">
  <cpn @fclick="dclick"></cpn>
  {{msg}}
</div>
<template id="cpn">
  <div>
    <div v-for="item in main" @click="itemClick(item)">{{item}}</div>
  </div>
</template>
var app = new Vue({
  el: '#app',
  data: {
    msg: 'hehe'
  },
  methods: {
    dclick(item) {
      console.log(item);
      this.msg = item
    }
  },
  components: {
    cpn: {
      template: '#cpn',
      data() {
        return {
          main: [
            { id: 0, name: 'zww' },
            { id: 1, name: 'lq' }
          ]
        }
      },
      methods: {
        itemClick(item) {
          this.$emit('fclick', item)
        }
      },
    }
  }
})

ref 与 $parent / $children

访问子实例 - $children

<div id="app">
  <cpn></cpn>
  <button @click="btnClick">按钮</button>
</div>
<template id="cpn">
  <div>子组件</div>
</template>
var app = new Vue({
  el: '#app',
  methods: {
    btnClick() {
      this.$children[0].showSon()
    }
  },
  components: {
    cpn: {
      template: '#cpn',
      data() {
        return {
          msg: '子组件'
        }
      },
      methods: {
        showSon() {
          console.log("hh");
        }
      },
    }
  }
})

访问父实例 - $parent

<div id="app">
  <cpn></cpn>
</div>
<template id="cpn">
  <div>
    <span>子组件</span>
    <button @click="btnclick">按钮</button>
  </div>
</template>
var app = new Vue({
  el: '#app',
  data: {
    msg: '父组件内容'
  },
  components: {
    cpn: {
      template: '#cpn',
      methods: {
        btnclick() {
          console.log(this.$parent.msg);
        }
      },
    }
  }
})

访问子实例 - refs

ref:如果在普通的DOM元素上使用,引用指向的就是DOM元素;如果用在子组件上,引用就指向组件实例。

<div id="app">
  <cpn ref="a"></cpn>
  <button @click="btnClick">按钮</button>
</div>
<template id="cpn">
  <div>子组件</div>
</template>
var app = new Vue({
  el: '#app',
  methods: {
    btnClick() {
      this.$refs.a.showSon()
    }
  },
  components: {
    cpn: {
      template: '#cpn',
      data() {
        return {
          msg: '子组件'
        }
      },
      methods: {
        showSon() {
          console.log("hh");
        }
      },
    }
  }
})

$emit / $on

$attrs / $listeners

Vuex

Vuex官网


Vue中key值的作用是什么

使用 key 来给每个节点做一个唯一标识,Diff 算法就可以正确的识别此节点。

key 的作用主要是为了高效的更新虚拟 DOM。


v-model的原理

v-model就是一个语法糖,它背后本质是包含了两个操作:

  • v-bind绑定一个value属性
  • v-on给当前元素绑定input事件
<input type="text" v-model="message">
<!-- 等价于 -->
<input type="text" :value="message" @input="message = $event.target.value">

Class与Style如何动态绑定

Class

对象语法

绑定class对象语法:对象的键是类名,值是布尔值。

<div v-bind:class="{ active: isActive, size: isSize }">对象绑定Class</div>

data: {
  isActive: true,
  isSize: false
}

数组语法

绑定class数组语法:数组中的成员直接对应类名。

<div v-bind:class="[isActive,isSize]">数组绑定class</div>

data: {
  isActive: 'active',
  isSize: 'size'
}

Style

对象语法

<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }">对象绑定Style</div>

data: {
  activeColor: 'red',
  fontSize: 60
}

数组语法

<div v-bind:style="[styleColor, styleSize]">数组绑定Style</div>

data: {
  styleColor: {
    color: 'red'
  },
  styleSize: {
    fontSize: '23px'
  }
}

computed和watch的区别

computed

computed 是计算属性,它会根据你所依赖的数据动态显示新的计算结果。计算结果会被缓存,computed 的值在 getter 执行后是会被缓存的,只有在它依赖的属性值改变之后,下一次获取 computed 的值时才会重新调用对应的 getter 来计算。

应用场景:购物车商品结算,当我们需要进行数值计算,并且依赖于其它数据时,应该使用 computed,可以利用 computed 的缓存特性,避免每次获取值时,都要重新计算。

watch

watch 是去监听一个值的变化,然后执行相对应的函数。它可以接受 2 个参数(newValue, oldValue),即变化的最新值和上一次变化的旧值。它是没有缓存的。

应用场景:搜索数据,如果你需要在某个数据变化时做一些事情,使用 watch 来观察这个数据变化。


Vue的修饰符有哪些

表单修饰符

.lazy:让数据在失去焦点或者回车时才会更新同步;
.number:自动将用户的输入值转为数值类型;
.trim:自动过滤用户输入的首尾空白字符;

事件修饰符

.stop:阻止冒泡;
.prevent:阻止默认行为;
.self:只会触发自己范围内的事件,不包含子元素;
.once:事件将只会触发一次;
.capture:与事件冒泡的方向相反,事件捕获由外到内;
.passive:Vue还对应addEventListener中的passive选项提供了.passive修饰符,能够提升移动端的性能。

不要把.passive和.prevent一起使用,因为.prevent将会被忽略,同时浏览器可能会向你展示一个警告。请记住,.passive会告诉浏览器你不想阻止事件的默认行为。

按键修饰符

.enter:回车键;
.tab:制表键;
.delete:含删除和退格键;
.esc:返回键;
.space: 空格键;
.up:向上键;
.down:向下键;
.left:向左键;
.right:向右键;

系统修饰键

可以用如下修饰符来实现仅在按下相应按键时才触发鼠标或键盘事件的监听器。
.ctrl
.alt
.shift
.meta

鼠标按钮修饰符

.left:左键点击;
.right:右键点击;
.middle:中键点击;

.exact修饰符

.exact:修饰符允许你控制由精确的系统修饰符组合触发的事件。

<!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
<button v-on:click.ctrl="onClick">A</button>

<!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button v-on:click.ctrl.exact="onCtrlClick">A</button>

<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button v-on:click.exact="onClick">A</button>

keep-alive的作用是什么

keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。

官方文档 - keep-alive


Vue是如何实现数据的双向绑定的

Vue 双向数据绑定是通过数据劫持结合发布订阅模式的方式来实现的,也就是说数据和视图同步,如果数据发生变化,那么视图也跟着变化,视图变化,数据也随之发生改变;其核心是 Object.defineProperty() 方法。

掘金 - 0到1掌握:Vue核心之数据双向绑定


vue-router路由模式有几种

有两种模式,分别为hash模式和history模式

hash模式

地址栏URL中的#符号。比如此URL:https://www.cnblogs.com/LqZww/p/13544020.html#4261640972,hash的值为#/42616409711

  1. url路径会出现#字符;
  2. hash值不包括在Http请求中,它是交由前端路由处理,所以改变hash值时不会刷新页面,也不会向服务器发送请求;
  3. hash值的改变会触发hashchange事件;

history模式

利用了HTML5 History Interface中新增的pushState()和replaceState()方法。这两个方法应用于浏览器的历史记录栈,在当前已有的back、forward、go的基础之上,它们提供了对历史记录进行修改的功能。只是当它们执行修改时,虽然改变了当前的 URL,但浏览器不会立即向后端发送请求。

  1. 整个地址重新加载,可以保存历史记录,方便前进后退;
  2. 依赖H5 API和后台配置,没有后台配置的话,页面刷新时会出现404;

vue-router有哪几种导航钩子

vue-router提供的导航守卫主要用来通过跳转或取消的方式守卫导航。有多种机会植入路由导航过程中:全局的、单个路由独享的、组件级的。

参数或查询的改变并不会触发进入/离开的导航守卫。你可以通过观察$route对象来应对这些变化,或使用beforeRouteUpdate的组件内守卫。

  1. 全局守卫:router.beforeEach
  2. 全局解析守卫:router.beforeResolve
  3. 全局后置钩子:router.afterEach
  4. 路由独享的守卫:beforeEnter
  5. 组件内的守卫:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave

官方文档 - 导航守卫


vue-router导航解析的流程是什么

  1. 导航被触发。
  2. 在失活的组件里调用 beforeRouteLeave 守卫。
  3. 调用全局的 beforeEach 守卫。
  4. 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
  5. 在路由配置里调用 beforeEnter。
  6. 解析异步路由组件。
  7. 在被激活的组件里调用 beforeRouteEnter。
  8. 调用全局的 beforeResolve 守卫 (2.5+)。
  9. 导航被确认。
  10. 调用全局的 afterEach 钩子。
  11. 触发 DOM 更新。
  12. 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。

官方文档 - 完整的导航解析流程


route和router的区别

  1. $route 为当前 router 跳转对象,里面可以获取当前路由的 name、path、params、hash、query等等路由信息参数。
  2. $router是 VueRouter 的实例,是全局的路由对象,对象包括了路由的跳转方法,钩子函数等等。

vue-router实现路由懒加载

主要有以下三种方式:

  1. Vue异步组件技术:结合 Vue 的 异步组件 和 Webpack 的代码分割功能可以实现路由组件的懒加载。在这种情况下打包后,每一个组件生成一个 js 文件。
  2. 路由懒加载:使用动态 import 语法。
  3. require.ensure():使用 webpack 的 require.ensure 技术,也可以实现按需加载。这种情况下,多个路由指定相同的 chunkName,会合并打包成一个 js 文件。

Vuex是什么,怎么使用,哪种功能场景使用它

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。它实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间数据的共享。

使用Vuex统一管理状态有如下好处:

  1. 能够在vuex中集中管理共享的数据,易于开发和后期维护;
  2. 能够高效地实现组件之间的数据共享,提高开发效率;
  3. 存储在vuex中的数据都是响应式的,能够实时保持数据与页面的同步;

在 main.js 引入 store,注入。新建了一个 store 目录,然后...export。

场景:单页应用中,组件之间的共享状态和方法。

Vuex官网


Vuex有哪几种属性

  1. State:用于数据的存储,提供唯一的公共数据源,所有共享的数据都要统一放到Store的State中进行存储;
  2. Getter:用于对Store中的数据进行加工处理形成新的数据,类似Vue中的计算属性,Store中数据发生变化,Getter的数据也会跟着变化;
  3. Mutation:用于变更Store中的数据,且不能用于处理异步操作;
  4. Action:用于处理异步任务,如果通过异步操作变更数据,必须通过Action,而不能使用Mutation,但是在Action中还是要通过触发Mutation的方式间接变更数据;
  5. Module:类似于命名空间,用于项目中将各个模块的状态分开定义和操作;

待完善!

如何理解Vue的单向数据流
vue-router是什么
vue-router如何响应路由参数的变化
vue-router的几种实例方法以及参数传递
vue-router的动态路由匹配以及使用
vue-router如何定义嵌套路由
组件及其属性

posted @ 2020-09-02 17:41  LqZww  阅读(65)  评论(0编辑  收藏