# 四、前端框架阶段

# 1、请问 v-if 和 v-show 有什么区别?

答案:

①、编译过程: v-if 是 真正 的 条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。v-show 的元素始终会被渲染并保留在 DOM 中。v-show 只是简单地切换元素的 CSS 属性display。

②、编译条件: v-if 是惰性的:如果在初始渲染时条件为假,则什么也不做。直到条件第一次变为真时,才会开始渲染条件块。v-show不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。

③、性能消耗: v-if有更高的切换消耗。v-show有更高的初始渲染消耗。

④、应用场景: v-if适合运行时条件很少改变时使用。v-show适合频繁切换。

# 2、vue中 key 值的作用

答案:用于 管理可复用的元素。因为Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。

# 3、Vue 组件中 data 为什么必须是函数?

答案:因为一个组件是可以共享的,但他们的data是私有的,所以每个组件都要return一个新的data对象,返回一个唯一的对象,不要和其他组件共用一个对象。

# 4、computed 和 watch 区别?什么时候使用计算属性,什么时候使用watch属性呢?

答案:

  • computed 是计算属性,依赖其他属性计算值,并且 computed 的值有缓存,只有当计算值变化才会返回内容。
  • watch 监听到值的变化就会执行回调,在回调中可以进行一些逻辑操作。
  • 所以一般来说需要依赖别的属性来动态获得值的时候可以使用 computed,对于监听到值的变化需要做一些复杂业务逻辑的情况可以使用 watch
  • 能够使用computed属性实现的结果,就使用computed 属性,不要使用watch,因为watch是一直在侦听数据的变化,对内存性能开销比较大,而计算属性是基于它们的依赖进行缓存的,所以从性能上比watch开销要小很多。
  • 当需要执行异步操作的时候,就要使用watch属性,这个是computed 属性无法做到的。

# 5、组件中 data 什么时候可以使用对象?

答案:

  • 组件复用时所有组件实例都会共享 data,如果 data 是对象的话,就会造成一个组件修改 data 以后会影响到其他所有组件,所以需要将 data 写成函数,每次用到就调用一次函数获得新的数据。
  • 当我们使用 new Vue() 的方式的时候,无论我们将 data 设置为对象还是函数都是可以的,因为 new Vue() 的方式是生成一个根组件,该组件不会复用,也就不存在共享 data 的情况了

# 6、vuex 是什么? 有哪几种属性?

答案:

  • Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。
  • 有 5 种,分别是 stategettermutationactionmodule

vuex 的 store 是什么?

  • vuex 就是一个仓库,仓库里放了很多对象。其中 state 就是数据源存放地,对应于一般 vue 对象里面的 datastate 里面存放的数据是响应式的,vue 组件从 store 读取数据,若是 store 中的数据发生改变,依赖这相数据的组件也会发生更新它通过 mapState 把全局的 stategetters 映射到当前组件的 computed 计算属性

vuex 的 getter 是什么?

  • getter 可以对 state 进行计算操作,它就是 store 的计算属性虽然在组件内也可以做计算属性,但是 getters 可以在多给件之间复用如果一个状态只在一个组件内使用,是可以不用 getters

vuex 的 mutation 是什么?

  • 更改Vuexstore中的状态的唯一方法是提交mutation

vuex 的 action 是什么?

  • action 类似于 muation, 不同在于:action 提交的是 mutation,而不是直接变更状态action 可以包含任意异步操作
  • vueajax 请求代码应该写在组件的 methods 中还是 vuexaction

vuex的 module是什么?

面对复杂的应用程序,当管理的状态比较多时;我们需要将vuexstore对象分割成模块(modules)。

# 7、 Vue子组件调用父组件的方法

答案:

  • 第一种方法是直接在子组件中通过this.$parent.event来调用父组件的方法
  • 第二种方法是在子组件里用$emit向父组件触发一个事件,父组件监听这个事件就行了。

# 8、Webpack的四个核心概念有哪些?

答案:

  • Entry:入口,Webpack 执行构建的第一步将从 Entry 开始,可抽象成输入。
  • Loader:模块转换器,用于把模块原内容按照需求转换成新内容。
  • Plugin:扩展插件,在 Webpack 构建流程中的特定时机注入扩展逻辑来改变构建结果或做你想要的事情。
  • Output:输出结果,在 Webpack 经过一系列处理并得出最终想要的代码后输出结果。

# 9、组件通信一般分为几种情况?

答案:

  • 父子组件通信
  • 兄弟组件通信
  • 跨多层级组件通信

# 10、vue.js的两个核心是什么?

答案:

1、数据驱动,也叫双向数据绑定。

Vue.js数据观测原理在技术实现上,利用的是Object.defineProperty和存储器属性: getter和setter(所以只兼容IE9及以上版本),可称为基于依赖收集的观测机制。核心是VM,即ViewModel,保证数据和视图的一致性。

2、组件系统。

.vue组件的核心选项:

1、模板(template):模板声明了数据和最终展现给用户的DOM之间的映射关系。 2、初始数据(data):一个组件的初始数据状态。对于可复用的组件来说,这通常是私有的状态。 3、接受的外部参数(props):组件之间通过参数来进行数据的传递和共享。 4、方法(methods):对数据的改动操作一般都在组件的方法内进行。 5、生命周期钩子函数(lifecycle hooks):一个组件会触发多个生命周期钩子函数,最新2.0版本对于生命周期函数名称改动很大。 6、私有资源(assets):Vue.js当中将用户自定义的指令、过滤器、组件等统称为资源。一个组件可以声明自己的私有资源。私有资源只有该组件和它的子组件可以调用。 等等。

# 11、vue-router路由的两种模式?

答案:

vue-router路由提供了两种路由模式:hash模式和history模式。

hash模式:

vue-router 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。

history模式:

如果不想要很丑的 hash,我们可以用路由的 history 模式,这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。

//设置mode属性,设置路由模式
const router = new VueRouter({
  mode: 'history',
  routes: [...]
})

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

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

# 12、vue等单页面应用及其优缺点

答案:

优点:

无刷新体验,提升了用户体验; 前端开发不再以页面为单位,更多地采用组件化的思想,代码结构和组织方式更加规范化,便于修改和调整; API 共享,同一套后端程序代码不用修改就可以用于Web界面、手机、平板等多种客户端 用户体验好、快,内容的改变不需要重新加载整个页面。

缺点:

不支持低版本的浏览器,最低只支持到IE9; 不利于SEO的优化(如果要支持SEO,建议通过服务端来进行渲染组件); 第一次加载首页耗时相对长一些,出现白屏; 不可以使用浏览器的导航按钮需要自行实现前进、后退。

13、对于MVVM的理解?

答案:

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

  • Model: 代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑。我们可以把Model称为数据层,因为它仅仅关注数据本身,不关心任何行为
  • View: 用户操作界面。当ViewModel对Model进行更新的时候,会通过数据绑定更新到View
  • ViewModel: 业务逻辑层,View需要什么数据,ViewModel要提供这个数据;View有某些操作,ViewModel就要响应这些操作

MVVM主要解决了 MVC中大量的 DOM 操作使页面渲染性能降低,加载速度变慢,影响用户体验。和当 Model 频繁发生变化,开发者需要主动更新到 View 。

# 13、Vue中双向数据绑定是如何实现的?

答案:

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

# 14、vue中如何实现tab栏切换功能?

答案:

遇到此问题,一定要先回答前两种方式,再提使用第三方UI库实现

在 vue 中,实现 Tab 切换主要有三种方式:

1、使用 component 动态组件实现 Tab切换 [推荐移动端使用]

2、使用 vue-router 路由配合<router-view></router-view>标签实现

3、使用第三方插件

详解:


1、使用 component 动态组件实现 Tab切换:

动态组件 component: 渲染一个“元组件”为动态组件。依 isShow的属性值,来决定哪个组件被渲染。

示例:

<template>
	<div>
	  <tab>
	      <tab-item selected @on-item-click="onItemClick">Tab标签一</tab-item>
	      <tab-item @on-item-click="onItemClick">Tab标签二</tab-item>
	      <tab-item @on-item-click="onItemClick">Tab标签三</tab-item>
    </tab>
    <component :isShow="currentView"></component>
	</div>
</template>
<script type="text/javascript">
	import { Tab, TabItem } from 'vux'
    import initOne from '@/components/example/initOne.vue';
    import initTwo from '@/components/example/initTwo.vue';
    import initThree from '@/components/example/initThree.vue';
	export default{
		data () {
			return {
				currentView:"",
			}
		},
		components : {
			Tab,
			TabItem,
			initOne,
            initTwo,
            initThree
		},
		mounted(){
			 this.currentView = "initOne";
		},
		methods : {
			onItemClick (index) {
		        if(index==0){
		         //Tab切换一
		         this.currentView = "initOne";
		        }
		        if(index==1){
		         //Tab切换二
		         this.currentView = "initTwo";
		        }
		        if(index==2){
		         //Tab切换三
		         this.currentView = "initThree";
		        }
			}
		}
	}
</script>

2、通过 <router-view></router-view>标签 和 vue-router 子路由 配合实现Tab切换

示例:

适合vue做后台管理系统时,做侧边栏功能

account.vue文件:

<template> 
 <div id="account"> 
 <p class="tab"> 
  <!-- 使用 router-link 组件来导航. -->
  <!-- 通过传入 `to` 属性指定链接. -->
  <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
  <router-link to="/account/course">我的课程</router-link> 
  <!-- 注意这里的路径,course和order是account的子路由 -->
  <router-link to="/account/order">我的订单</router-link> 
 </p> 
 <!-- 路由出口 -->
 <!-- 路由匹配到的组件将渲染在这里 -->
 <router-view></router-view> 
 </div> 
</template>

在src/router/index.js:

import account from '../page/demo/account.vue'
import course from '../page/demo/course.vue'
import order from '../page/demo/order.vue'

export default new Router({
  //路由配置
  routes: [
  		{ 
    		path: '/account', 
    		name: 'account', 
   		 	component: Account, 
    		children: [ 
        		{name: 'course', path: 'course', component: course}, 
        		{name: 'order', path: 'order', component: order} 
      		] 
  		} 
	]
})

# 15、构建的 vue-cli 工程都到了哪些技术,它们的作用分别是什么?

答案:

  • vue.js:vue-cli工程的核心,主要特点是 双向数据绑定 和 组件系统。
  • vue-router:vue官方推荐使用的路由框架。
  • vuex:专为 Vue.js 应用项目开发的状态管理器,主要用于维护vue组件间共用的一些 变量 和 方法。
  • axios( 或者 fetch 、ajax ):用于发起 GET 、或 POST 等 http请求,基于 Promise 设计。
  • webpack:模块加载和vue-cli工程打包器。

# 16、路由的跳转方式?

答案:

声明式(标签跳转)

<router-link :to="index">

编程式( js跳转)

router.push('index')

# 17、$route$router的区别?

答案:

  • $route是“路由信息对象”,包括pathparamshashqueryfullPathmatchedname等路由信息参数。
  • $router是“路由实例”对象包括了路由的跳转方法,钩子函数等

# 18、vue首屏加载优化方案有哪些?

答案:

  • Vue-Router路由懒加载(利用Webpack的代码切割)
  • 使用CDN加速,将通用的库从vendor进行抽离
  • 服务端渲染SSR
  • 组件按需加载
  • Webpack开启gzip压缩