N+1道Vue面试题,快来康康

1.SPA单页应用

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

优点:

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

缺点:

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

2.v-show与v-if有什么区别?

  • v-if是真正的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当的被销毁和重建;也是惰性的:如果在初始渲染时条件为假,则什么也不做–直到条件第一次变为真时,才会开始渲染条件块。
  • v-show不管初始条件是什么,元素总是被渲染,并且只是简单的基于css的display属性进行切换。
  • 所以,v-if适用于在运行时很少改变条件,不需要频繁切换条件的场景;v-show则适用于需要频繁切换条件的场景。

3.Class与Style如何动态渲染?

Class可以通过对象语法和数组语法进行动态绑定:

  • 对象语法:
<div v-bind:class="{ active: isActive, 'text-danger': hasError }"></div>
data: {
  isActive: true,
  hasError: false
}
  • 数组语法:
<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
data: {
  activeClass: 'active',
  errorClass: 'text-danger'
}

Style可以通过对象语法和数组语法进行动态绑定:

  • 对象语法:
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
data: {
  activeColor: 'red',
  fontSize: 30
}
  • 数组语法:
<div v-bind:style="[styleColor, styleSize]"></div>
data: {
  styleColor: {
     color: 'red'
   },
  styleSize:{
     fontSize:'23px'
  }
}

4.怎么理解Vue的单向数据流?

所有的prop都使得其父子prop之间形成了一个单向下行绑定:父级prop的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流难以理解。

额外的,每次父组件发生更新时,子组件所有的prop都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变prop。如果你这样做了,Vue会在浏览器的控制台中发出警告。子组件想修改时,只能通过$emit派发一个自定义事件,父组件接收到后,由父组件修改。

有两种常见的试图改变一个prop的情形:

  • 这个prop用来传递一个初始值;这个子组件接下来希望将其作为一个本地的prop数据来使用。在这种情况下,最好定义一个本地的data属性并将这个prop用作其初始值:
props: ['initialCounter'],
data: function () {
  return {
    counter: this.initialCounter
  }
}
  • 这个prop以一种原始的值传入且需要进行转换。在这种情况下,最好使用这个prop的值来定义一个计算属性。
props: ['size'],
computed: {
  normalizedSize: function () {
    return this.size.trim().toLowerCase()
  }
}

5.computed和watch的区别和运用的场景?

computed:是计算属性,依赖其他属性值,并且computed的值有缓存,只有它依赖的属性值发生改变,下一次获取computed的值时才会重新计算computed的值;
watch:更多的是“观察”的作用,类似于某些数据的监听回调,每当监听的数据变化时都会执行回调进行后续操作。

运用场景:

  • 当我们需要进行数值计算,并且依赖于其他数据时,应该使用computed,因为可以利用computed的缓存特性,避免每次获取值时,都要重新计算;
  • 当我们需要在数据变化时执行异步或开销较大的操作时,应使用watch,使用watch选项允许我们执行异步操作(访问一个API),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。

6.直接给一个数组项赋值,Vue能检测到变化吗?

由于JavaScript的限制,Vue不能检测到以下数组的变动

  • 当你利用索引直接设置一个数组项时,例如:vm.items[indexOfitem]=newValue
  • 当你修改数组的长度时,例如:vm.items.length=newLength

为了解决第一个问题,Vue提供了以下操作方法:

	 //Vue.set
     Vue.set(vm.items,indexOfItem,newValue)
     //vm.$set,Vue.set的一个别名
     vm.$set(vm.items,indexOfItem,newValue)
     //Array.prototype.splice
     vm.items.splice(indexOfItem,1,newValue)

为了解决第二个问题,Vue提供了以下操作方法:

	 //Array.prototype.splice
     vm.items.splice(newLength)

7.谈谈你对Vue生命周期的理解?

  • 生命周期是什么?

Vue实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模板、挂载DOM、渲染更新、渲染卸载等一系列过程,我们称之为Vue的生命周期。

  • 各个生命周期的作用:
    生命周期的作用

8.vue的父组件和子组件生命周期钩子函数执行顺序?

  • 加载渲染过程

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

  • 子组件更新过程

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

  • 父组件更新过程

父beforeUpdate->父updated

  • 销毁过程

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

9.在哪个生命周期内调用异步请求?

可以在钩子函数created、beforeMount、mounted中进行调用,因为在这三个钩子函数中,data已经创建,可以将服务器返回的数据进行赋值,但是推荐在created钩子函数中调用异步请求,因为在created钩子函数中调用异步请求有以下优点:

  • 能更快获取到服务端数据,减少页面loading时间;
  • SSR不支持beforeMount、mounted钩子函数所以放在created中有助于一致性;

10.在什么阶段才能访问操作DOM?

在钩子函数mounted被调用前,Vue已经将编译好的模板挂载到页面上,所以在mounted中可以访问操作DOM。

11.父组件可以监听到子组件的生命周期?

比如有父组件Parent和子组件Child,如果父组件监听到子组件挂载mounted就做一些逻辑处理,可以通过以下写法实现:

// Parent.vue
<Child @mounted="doSomething"/>
    
// Child.vue
mounted() {
  this.$emit("mounted");
}

以上需要手动通过$emit触发父组件的事件,更简单的方式可以在父组件引用子组件时通过@hook来监听即可。

//  Parent.vue
<Child @hook:mounted="doSomething" ></Child>

doSomething() {
   console.log('父组件监听到 mounted 钩子函数 ...');
},
    
//  Child.vue
mounted(){
   console.log('子组件触发 mounted 钩子函数 ...');
},    
    
// 以上输出顺序为:
// 子组件触发 mounted 钩子函数 ...
// 父组件监听到 mounted 钩子函数 ...

当然 @hook 方法不仅仅是可以监听 mounted,其它的生命周期事件,例如:created,updated 等都可以监听。

12.谈谈你对keep-alive的了解?

keep-alive是Vue内置的一个组件,可以使被包含的组件保留状态,避免重新渲染,其有以下特性:

  • 一般结合路由和动态组件一起使用,用于缓存组件;
  • 提供include和exclude属性,两者都支持字符串或正则表达式,include表示只有名称匹配的组件会被缓存,exclude表示任何名称匹配的组件都不会被缓存,其中exclude的优先级比include高;
  • 对应两个钩子函数activated和deactivated,当组件被激活时,触发钩子函数activated,当组件被移除时,触发钩子函数deactivated。

13.组件中data为什么是一个函数?

为什么组件中的data必须是一个函数,然后return一个对象,而new vue实例里,data可以直接是一个对象?

// data
data() {
  return {
	message: "子组件",
	childName:this.name
  }
}

// new Vue
new Vue({
  el: '#app',
  router,
  template: '<App/>',
  components: {App}
})

因为组件是用来复用的,且JS里对象是引用关系,如果组件中data是一个对象,那么这样作用域没有隔离,子组件中的data属性值会相互影响,如果组件中data选项是一个函数,那么每个实例可以维护一份被返回对象的独立的拷贝,组件实例之间的data属性值不会相互影响;而new Vue的实例,是不会复用的,因此不存在引用对象的问题。

14.v-model的原理?

我们在vue项目中主要使用v-model指令在表单input、textarea、select等元素上创建双向数据绑定,我们知道v-model本质上不过是语法糖,v-model在内部为不同的输入元素使用不同的属性并抛出不同的事件:

  • text 和 textarea 元素使用 value 属性和 input 事件;
  • checkbox 和 radio 使用 checked 属性和 change 事件;
  • select 字段将 value 作为 prop 并将 change 作为事件。
//以 input  表单元素为例:
<input v-model='something'>
    
相当于

<input v-bind:value="something" v-on:input="something = $event.target.value">
//如果在自定义组件中,v-model 默认会利用名为 value 的 prop 和名为 input 的事件,如下所示:
父组件:
<ModelChild v-model="message"></ModelChild>

子组件:
<div>{{value}}</div>

props:{
    value: String
},
methods: {
  test1(){
     this.$emit('input', '小红')
  },
},

15.Vue组件间通信有哪几种方式?

主要有三类通信:

父子组件通信、隔代组件通信、兄弟组件通信

下面分别介绍每种通信方式且会说明此种方法可适用于哪类组件间通信。

(1)props/$emit适用父子组件通信
(2)ref与parent/children适用于父子组件通信

ref:如果在普通的DOM元素上使用,引用指向的就是DOM元素;如果用在子组件上,引用就指向组件实例
parent/children:访问父/子实例

(3)EventBus(emit/on)适用于父子、隔代、兄弟组件通信

这种方法通过一个空的Vue实例作为中央事件总线(事件中心),用它来触发事件和监听事件,从而实现任何组件间的通信,包括父子、隔代、兄弟组件。

(4)attrs/listeners适用于隔代 组件通信

attrs:包含了父作用域中不被prop所识别的特性绑定(class和style除外)。当一个组件没有声明任何prop时,这里会包含所有父作用域的绑定 ( class 和 style 除外 ),并且可以通过 v-bind="$attrs" 传入内部组件。通常配合 inheritAttrs 选项一起使用。

listeners:包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件

(5)provide / inject 适用于 隔代组件通信

祖先组件中通过 provider 来提供变量,然后在子孙组件中通过 inject 来注入变量。provide / inject API 主要解决了跨级组件间的通信问题,不过它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系。

(6)Vuex 适用于 父子、隔代、兄弟组件通信

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。每一个 Vuex 应用的核心就是 store(仓库)。“store” 基本上就是一个容器,它包含着你的应用中大部分的状态 ( state )。

Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。

改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化。

16.你使用过Vuex吗?

Vuex是一个专门为vue.js应用程序开发的状态管理模式,每一个Vuex应用的核心就是store(仓库)。store基本上就是一个容器,它包含着你的应用中大部分的状态。

(1)vuex的状态存储是响应式的。当vue组件从store中读取状态的时候,若store中的状态发生变化,那么相应的组件也会相应的得到高效更新。
(2)改变store中的状态的唯一途径就是显式的提交(commit)mutation。这样使我们可以方便的跟踪每一个状态的变化。

主要包括以下几个模块:

  • State:定义了应用状态的数据结构,可以在这里设置默认的初始状态
  • Getter:允许组件从Store中获取数据,mapGetters辅助函数仅仅是将store中的getter映射到局部计算属性。
  • Mutation:是唯一更改store中状态的方法,且必须是同步函数。
  • Action:用于提交mutation,而不是直接变更状态,可以包含任意异步操作。
  • Module:允许将单一的Store拆分为多个store且同时保存在单一的状态树中。

17.使用过Vue SSR吗?说说SSR?

SSR:vue在客户端将标签渲染成整个HTML片段的工作在服务端完成,服务器形成的HTML片段直接返回给客户端这个过程叫做服务端渲染。

(1)服务端渲染的优点:

  • 更好的SEO:因为SPA页面的内容是通过ajax获取,而搜索引擎爬取工具并不会等待ajax异步完成后在抓取页面内容,所以在SPA中是抓取不到页面通过ajax获取到的内容,而SSR是直接由服务端返回已经渲染好的页面(数据已经包含在页面中),所以搜索引擎爬取工具可以抓取渲染好的页面。
  • 更快的内容到达时间(首屏加载更快):SPA会等待所有的vue编译后的js文件都下载完成后,才开始页面的渲染,文件下载等需要一定的时间等,所以首屏渲染需要一定的时间;SSR直接由服务器渲染好页面直接返回显示,无需等待下载js文件及再去渲染等等,所以SSR有更快的内容到达时间。
    (2)服务端渲染的缺点:
  • 更多的开发条件限制:例如服务端渲染只支持 beforCreate 和 created 两个钩子函数,这会导致一些外部扩展库需要特殊处理,才能在服务端渲染应用程序中运行;并且与可以部署在任何静态文件服务器上的完全静态单页面应用程序 SPA 不同,服务端渲染应用程序,需要处于 Node.js server 运行环境;
  • 更多的服务器负载:在 Node.js 中渲染完整的应用程序,显然会比仅仅提供静态文件的 server 更加大量占用CPU 资源 (CPU-intensive - CPU 密集),因此如果你预料在高流量环境 ( high traffic ) 下使用,请准备相应的服务器负载,并明智地采用缓存策略。

18.vue-router路由模式有几种?

vue-router有3种路由模式:hash、history、abstract,对应的源码如下:

switch (mode) {
  case 'history':
	this.history = new HTML5History(this, options.base)
	break
  case 'hash':
	this.history = new HashHistory(this, options.base, this.fallback)
	break
  case 'abstract':
	this.history = new AbstractHistory(this, options.base)
	break
  default:
	if (process.env.NODE_ENV !== 'production') {
	  assert(false, `invalid mode: ${mode}`)
	}
}

其中,3 种路由模式的说明如下:

  • hash:使用URL hash值来作路由。支持所有浏览器,包括不支持HTML5 History Api 的浏览器;
  • history:依赖 HTML5 History API 和服务器配置
  • abstract:支持所有 JavaScript 运行环境,如 Node.js 服务器端。如果发现没有浏览器的 API,路由会自动强制进入这个模式.

19.能说下 vue-router 中常用的 hash 和 history 路由模式实现原理吗?

(1)hash 模式的实现原理
早期的前端路由的实现就是基于 location.hash 来实现的。其实现原理很简单,location.hash 的值就是 URL 中 # 后面的内容。比如下面这个网站,它的 location.hash 的值为 ‘#search’:

https://www.word.com#search

hash 路由模式的实现主要是基于下面几个特性:

  • URL 中 hash 值只是客户端的一种状态,也就是说当向服务器端发出请求时,hash 部分不会被发送;
  • hash 值的改变,都会在浏览器的访问历史中增加一个记录。因此我们能通过浏览器的回退、前进按钮控制hash 的切换;
  • 可以通过 a 标签,并设置 href 属性,当用户点击这个标签后,URL 的 hash 值会发生改变;或者使用 JavaScript 来对 loaction.hash 进行赋值,改变 URL 的 hash 值;
  • 我们可以使用 hashchange 事件来监听 hash 值的变化,从而对页面进行跳转(渲染)。
    (2)history 模式的实现原理
    HTML5 提供了 History API 来实现 URL 的变化。其中做最主要的 API 有以下两个:history.pushState() 和 history.repalceState()。这两个 API 可以在不进行刷新的情况下,操作浏览器的历史纪录。唯一不同的是,前者是新增一个历史记录,后者是直接替换当前的历史记录,如下所示:
window.history.pushState(null, null, path);
window.history.replaceState(null, null, path);

history 路由模式的实现主要基于存在下面几个特性:

  • pushState 和 repalceState 两个 API 来操作实现 URL 的变化 ;
  • 我们可以使用 popstate 事件来监听 url 的变化,从而对页面进行跳转(渲染);
  • history.pushState() 或 history.replaceState() 不会触发 popstate 事件,这时我们需要手动触发页面跳转(渲染)。

20.什么是MVVM?

MVVM
(1)View 层
View 是视图层,也就是用户界面。前端主要由 HTML 和 CSS 来构建 。

(2)Model 层
Model 是指数据模型,泛指后端进行的各种业务逻辑处理和数据操控,对于前端来说就是后端提供的 api 接口。

(3)ViewModel 层
ViewModel 是由前端开发人员组织生成和维护的视图数据层。在这一层,前端开发者对从后端获取的 Model 数据进行转换处理,做二次封装,以生成符合 View 层使用预期的视图数据模型。需要注意的是 ViewModel 所封装出来的数据模型包括视图的状态和行为两部分,而 Model 层的数据模型是只包含状态的,比如页面的这一块展示什么,而页面加载进来时发生什么,点击这一块发生什么,这一块滚动时发生什么这些都属于视图行为(交互),视图状态和行为都封装在了 ViewModel 里。这样的封装使得 ViewModel 可以完整地去描述 View 层。

21.Vue是如何实现数据绑定的?

vue数据双向绑定主要是指:数据变化更新视图,视图变化更新数据,如图:双向数据绑定
其中,view变化更新data,可以通过事件监听的方式来实现,所以vue的数据双向绑定的工作主要是如何根据data变化更新view

vue主要通过以下4个步骤来实现数据双向绑定:

  • 实现一个监听器Observer:对数据对象进行遍历,包括子属性对象的属性,利用object.defineProperty()对属性都加上setter和getter。这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到数据变化。
  • 实现一个解析器Compile:解析vue模板指令,将模板中的变量都替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,调用更新函数进行数据更新。
  • 实现一个订阅者watcher:watcher订阅者是observe和compile之间通信的桥梁,主要任务是订阅observe中的属性值变化的信息,当收到属性值变化的消息时,触发解析器compile中对应的更新函数。
  • 实现一个订阅器dep:订阅器采用发布-订阅设计模式,用来收集订阅者watcher,对监听器observe和订阅者watcher进行统一管理
    双向绑定
    详情可参考0 到 1 掌握:Vue 核心之数据双向绑定

22.vue框架怎么实现对象和数组的监听?

如果被问到vue怎么实现数据双向绑定,我们肯定都会回答通过Obect.definedProperty()对数据进行劫持,但是Obect.definedProperty()只能对属性进行劫持,不能对整个对象进行劫持,同理无法对数组进行劫持,但是我们在使用框架中都知道,vue能检测到对象和数组的变化,那它是怎么实现的呢?

/**
   * Observe a list of Array items.
   */
  observeArray (items: Array<any>) {
    for (let i = 0, l = items.length; i < l; i++) {
      observe(items[i])  // observe 功能为监测数据的变化
    }
  }

  /**
   * 对属性进行递归遍历
   */
  let childOb = !shallow && observe(val) // observe 功能为监测数据的变化

通过以上vue源码部分查看,我们就能知道vue框架是通过遍历数组和递归遍历对象,从而达到利用Obect.definedProperty()也能对对象和数组进行监听。

23.Obect.definedProperty()与Proxy优劣对比

Proxy的优势如下:

  • Proxy可以直接监听对象而非属性;
  • Proxy可以直接监听数组的变化
  • Proxy有多达13种拦截方法,不限于apply、ownKeys、deleteProperty、has等等都是Obect.definedProperty()不具备的。
  • Proxy返回的是一个新对象,我们可以只操作新的对象达到目的,而Obect.definedProperty()只能遍历对象属性直接修改
  • Proxy作为新标准将受到浏览器厂商重点持续的性能优化,也就是传说中的新标准的性能红利

Obect.definedProperty()的优势:

  • 兼容性好,支持IE9,而Proxy存在浏览器兼容性问题,而且无法用polyfill磨平。

24.vue怎么用vm.$set()解决对象新增属性不能响应的问题?

受现代 JavaScript 的限制 ,Vue 无法检测到对象属性的添加或删除。由于 Vue 会在初始化实例时对属性执行 getter/setter 转化,所以属性必须在 data 对象上存在才能让 Vue 将它转换为响应式的。但是 Vue 提供了 Vue.set (object, propertyName, value) / vm.$set (object, propertyName, value) 来实现为对象添加响应式属性,那框架本身是如何实现的呢?

看下源码

export function set (target: Array<any> | Object, key: any, val: any): any {
  // target 为数组  
  if (Array.isArray(target) && isValidArrayIndex(key)) {
    // 修改数组的长度, 避免索引>数组长度导致splcie()执行有误
    target.length = Math.max(target.length, key)
    // 利用数组的splice变异方法触发响应式  
    target.splice(key, 1, val)
    return val
  }
  // key 已经存在,直接修改属性值  
  if (key in target && !(key in Object.prototype)) {
    target[key] = val
    return val
  }
  const ob = (target: any).__ob__
  // target 本身就不是响应式数据, 直接赋值
  if (!ob) {
    target[key] = val
    return val
  }
  // 对属性进行响应式处理
  defineReactive(ob.value, key, val)
  ob.dep.notify()
  return val
}

我们阅读以上源码可知,vm.$set 的实现原理是:

  • 如果目标是数组,直接使用数组的splice方法触发响应式
  • 如果目标是对象,会先判读属性是否存在、对象是否是响应式,最终如果要对属性进行响应式处理,则是通过调用defineReactive 方法进行响应式处理( defineReactive 方法就是 Vue 在初始化对象时,给对象属性采用 Object.defineProperty 动态添加 getter 和 setter 的功能所调用的方法)

25.虚拟DOM的优缺点?

优点:

  • 保证性能下限:框架的虚拟DOM需要适配任何上层API可能产生的操作,它的一些DOM操作的实现必须是普适的,所以它的性能并不是最优的;但是比起粗暴的DOM操作性能要好很多,因此框架的虚拟DOM至少保证在你不需要手动优化的情况下依然可以提供还不错的性能,即保证性能的下限。
  • 无需手动操作DOM:我们不需要手动去操作DOM,只需要写好view-model的代码逻辑,框架会根据虚拟DOM和数据双向绑定,帮我们以可预期的方式更新视图,极大提高我们的开发效率。

缺点:

  • 无法进行极致优化:虽然虚拟DOM+合理的优化,足以应对绝大部分应用的性能需求,但在一些性能要求极高的应用中虚拟DOM无法进行针对性的极致优化。

26.虚拟DOM实现原理?

虚拟DOM的实现原理主要包括以下3部分:

  • (1)利用JavaScript创建DOM树
  • (2)树的diff,同层对比,输出patchs(listDiff/diffChildren/diffProps)
    • a.对比属性(对比新旧属性列表)
    • b.都存在的是否有变化
    • c.是否出现旧列表中没有的新属性
    • d.没有新节点,返回
    • e.新的节点tagName与key不变,对比props,继续递归遍历子树
    • f.tagName和key值变化了,则直接替换成新节点
  • (3)渲染差异
    a.遍历patchs,把需要更改的节点取出来
    b.局部更新DOM

详情参考:深入剖析:Vue核心之虚拟DOM

27.vue中的key有什么作用?

作用:key是为vue中的vnode的唯一标记,通过这个key,我们的diff操作更准确更快速

更准确:因为带key就不是就地复用了,在sameNode函数a.key === b.key 对比中可以避免就地复用的情况。所以会更加准确。

更快速:利用 key 的唯一性生成 map 对象来获取对应节点,比遍历方式更快

28.可以从哪些方面对vue项目进行优化?

代码层面的优化

  • v-if和v-show区分使用场景
  • computed和watch区分使用场景
  • v-for遍历必须为item添加key ,且避免同时使用v-if
  • 长列表性能优化
  • 事件的销毁
  • 图片资源懒加载
  • 路由懒加载
  • 第三方插件的按需引入
  • 优化无限列表性能
  • 服务端渲染SSR or 预渲染

webpack层面的优化

  • webpack对图片进行压缩
  • 减少ES6转为ES5的冗余代码
  • 提取公共代码、
  • 模板预编译
  • 提取组件的css
  • 优化SourceMap
  • 构建结果输出分析
  • vue项目的编译优化

基础的web技术的优化

  • 开启gzip压缩
  • 浏览器缓存
  • CDN的使用
  • 使用 Chrome Performance 查找性能瓶颈

29.对于vue3.0特性有什么了解?

1.监测机制的改变
3.0 将带来基于代理 Proxy 的 observer 实现,提供全语言覆盖的反应性跟踪。这消除了 Vue 2 当中基于 Object.defineProperty 的实现所存在的很多限制:

  • 只能监测属性,不能监测对象
  • 检测属性的添加和删除;
  • 检测数组索引和长度的变更;
  • 支持 Map、Set、WeakMap 和 WeakSet

新的 observer 还提供了以下特性:

  • 用于创建 observable 的公开 API。这为中小规模场景提供了简单轻量级的跨组件状态管理解决方案。
  • 默认采用惰性观察。在 2.x 中,不管反应式数据有多大,都会在启动时被观察到。如果你的数据集很大,这可能会在应用启动时带来明显的开销。在 3.x 中,只观察用于渲染应用程序最初可见部分的数据。
  • 更精确的变更通知。在 2.x 中,通过 Vue.set 强制添加新属性将导致依赖于该对象的 watcher 收到变更通知。在 3.x 中,只有依赖于特定属性的 watcher 才会收到通知。
  • 不可变的 observable:我们可以创建值的“不可变”版本(即使是嵌套属性),除非系统在内部暂时将其“解禁”。这个机制可用于冻结 prop 传递或 Vuex 状态树以外的变化。
  • 更好的调试功能:我们可以使用新的 renderTracked 和 renderTriggered 钩子精确地跟踪组件在什么时候以及为什么重新渲染。

模板

  • 模板方面没有大的变更,只改了作用域插槽,2.x 的机制导致作用域插槽变了,父组件会重新渲染,而 3.0 把作用域插槽改成了函数的方式,这样只会影响子组件的重新渲染,提升了渲染的性能。
  • 对于 render 函数的方面,vue3.0 也会进行一系列更改来方便习惯直接使用 api 来生成 vdom

对象式的组件声明方式

  • vue2.x 中的组件是通过声明的方式传入一系列 option,和 TypeScript 的结合需要通过一些装饰器的方式来做,虽然能实现功能,但是比较麻烦。3.0 修改了组件的声明方式,改成了类式的写法,这样使得和 TypeScript 的结合变得很容易。
  • vue 的源码也改用了 TypeScript 来写。其实当代码的功能复杂之后,必须有一个静态类型系统来做一些辅助管理。现在 vue3.0 也全面改用 TypeScript 来重写了,更是使得对外暴露的 api 更容易结合 TypeScript。静态类型系统对于复杂代码的维护确实很有必要。
课程简介: 历经半个多月的时间,Debug亲自撸的 “企业员工角色权限管理平台” 终于完成了。正如字面意思,本课程讲解的是一个真正意义上的、企业级的项目实战,主要介绍了企业级应用系统中后端应用权限的管理,其中主要涵盖了六大核心业务模块、十几张数据库表。 其中的核心业务模块主要包括用户模块、部门模块、岗位模块、角色模块、菜单模块和系统日志模块;与此同时,Debug还亲自撸了额外的附属模块,包括字典管理模块、商品分类模块以及考勤管理模块等等,主要是为了更好地巩固相应的技术栈以及企业应用系统业务模块的开发流程! 核心技术栈列表: 值得介绍的是,本课程在技术栈层面涵盖了前端和后端的大部分常用技术,包括Spring Boot、Spring MVC、Mybatis、Mybatis-Plus、Shiro(身份认证与资源授权跟会话等等)、Spring AOP、防止XSS攻击、防止SQL注入攻击、过滤器Filter、验证码Kaptcha、热部署插件Devtools、POI、Vue、LayUI、ElementUI、JQuery、HTML、Bootstrap、Freemarker、一键打包部署运行工具Wagon等等,如下图所示: 课程内容与收益: 总的来说,本课程是一门具有很强实践性质的“项目实战”课程,即“企业应用员工角色权限管理平台”,主要介绍了当前企业级应用系统中员工、部门、岗位、角色、权限、菜单以及其他实体模块的管理;其中,还重点讲解了如何基于Shiro的资源授权实现员工-角色-操作权限、员工-角色-数据权限的管理;在课程的最后,还介绍了如何实现一键打包上传部署运行项目等等。如下图所示为本权限管理平台的数据库设计图: 以下为项目整体的运行效果截图: 值得一提的是,在本课程中,Debug也向各位小伙伴介绍了如何在企业级应用系统业务模块的开发中,前端到后端再到数据库,最后再到服务器的上线部署运行等流程,如下图所示:
适用人群 Java开发人员,Vue开发人员,前后端分离开发人员,权限管理和配置开发人员 课程概述 【讲师介绍】 讲师职称: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;现某知名大型互联网公司资深架构师,技术总监,职业规划师,首席面试官,曾在某上市培训机构,高校任教多年。 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Array(Array老师)10多年互联网公司实战经验,知名的大型互联网公司的架构师,高管等职,在企业长期从事于技术的源码阅读和新技术的研究;擅长于职业规划,面试辅导,从事面试官多年;擅长于JAVA,人工智能AI应用,Xmind等等,曾服役于国内某上市培训机构数年,独特的培训思路,培训体系,培训方式,实践的职场技能,职场现状,职场晋升等让你快速适应企业职场的所需。&nbsp; 【课程介绍】 技术选型 开发环境:Eclipse/Idea&nbsp;,JDK&nbsp;1.8以上&nbsp; 后端技术 核心框架:SpringBoot2.x框架系列(同样适用Springcloud&nbsp;F版本以后的版本),如下(节选):&nbsp;&nbsp;&nbsp;&nbsp; 持久层框架:MyBatis&nbsp;3.x&nbsp;+&nbsp;Mybatis-plus&nbsp;3.x 日志管理:SLF4J&nbsp;1.7&nbsp;+&nbsp;Log4j2&nbsp;2.7 工具类:Apache&nbsp;Commons、Jackson&nbsp;、fastjson、Gson 权限验证 前端技术&nbsp;&nbsp; Vue&nbsp;&nbsp; Vue-cli ElementUI&nbsp;---https://element.eleme.io/ JSX&nbsp;(JavaScript&nbsp;Xml) 前台的权限验证和路由设置 开发模式&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;前后端分离的开发 数据库&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Mysql5 IDE &nbsp;&nbsp;&nbsp;&nbsp;Intellij&nbsp;Idea
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页