乐趣区

关于vue.js:什么样的vue面试题答案才是面试官满意的

Vue 组件渲染和更新过程

渲染组件时,会通过 Vue.extend 办法构建子组件的构造函数,并进行实例化。最终手动调用 $mount() 进行挂载。更新组件时会进行 patchVnode 流程,外围就是diff 算法

如何在组件中批量应用 Vuex 的 getter 属性

应用 mapGetters 辅助函数, 利用对象开展运算符将 getter 混入 computed 对象中

import {mapGetters} from 'vuex'
export default{
    computed:{...mapGetters(['total','discountTotal'])
    }
}

个别在哪个生命周期申请异步数据

咱们能够在钩子函数 created、beforeMount、mounted 中进行调用,因为在这三个钩子函数中,data 曾经创立,能够将服务端端返回的数据进行赋值。

举荐在 created 钩子函数中调用异步申请,因为在 created 钩子函数中调用异步申请有以下长处:

  • 能更快获取到服务端数据,缩小页面加载工夫,用户体验更好;
  • SSR 不反对 beforeMount、mounted 钩子函数,放在 created 中有助于一致性。

action 与 mutation 的区别

  • mutation 是同步更新, $watch 严格模式下会报错
  • action 是异步操作,能够获取数据后调用 mutation 提交最终数据

参考:前端 vue 面试题具体解答

Vue data 中某一个属性的值产生扭转后,视图会立刻同步执行从新渲染吗?

不会立刻同步执行从新渲染。Vue 实现响应式并不是数据发生变化之后 DOM 立刻变动,而是按肯定的策略进行 DOM 的更新。Vue 在更新 DOM 时是异步执行的。只有侦听到数据变动,Vue 将开启一个队列,并缓冲在同一事件循环中产生的所有数据变更。

如果同一个 watcher 被屡次触发,只会被推入到队列中一次。这种在缓冲时去除反复数据对于防止不必要的计算和 DOM 操作是十分重要的。而后,在下一个的事件循环 tick 中,Vue 刷新队列并执行理论(已去重的)工作。

SPA 首屏加载速度慢的怎么解决

一、什么是首屏加载

首屏工夫(First Contentful Paint),指的是浏览器从响应用户输出网址地址,到首屏内容渲染实现的工夫,此时整个网页不肯定要全副渲染实现,但须要展现以后视窗须要的内容

首屏加载能够说是用户体验中 最重要 的环节

对于计算首屏工夫

利用 performance.timing 提供的数据:

通过 DOMContentLoad 或者 performance 来计算出首屏工夫

// 计划一:document.addEventListener('DOMContentLoaded', (event) => {console.log('first contentful painting');
});
// 计划二:performance.getEntriesByName("first-contentful-paint")[0].startTime

// performance.getEntriesByName("first-contentful-paint")[0]
// 会返回一个 PerformancePaintTiming 的实例,构造如下:{
  name: "first-contentful-paint",
  entryType: "paint",
  startTime: 507.80000002123415,
  duration: 0,
};

二、加载慢的起因

在页面渲染的过程,导致加载速度慢的因素可能如下:

  • 网络延时问题
  • 资源文件体积是否过大
  • 资源是否反复发送申请去加载了
  • 加载脚本的时候,渲染内容梗塞了

三、解决方案

常见的几种 SPA 首屏优化形式

  • 减小入口文件积
  • 动态资源本地缓存
  • UI 框架按需加载
  • 图片资源的压缩
  • 组件反复打包
  • 开启 GZip 压缩
  • 应用 SSR

1. 减小入口文件体积

罕用的伎俩是路由懒加载,把不同路由对应的组件宰割成不同的代码块,待路由被申请的时候会独自打包路由,使得入口文件变小,加载速度大大增加

vue-router 配置路由的时候,采纳动静加载路由的模式

routes:[ 
    path: 'Blogs',
    name: 'ShowBlogs',
    component: () => import('./components/ShowBlogs.vue')
]

以函数的模式加载路由,这样就能够把各自的路由文件别离打包,只有在解析给定的路由时,才会加载路由组件

2. 动态资源本地缓存

后端返回资源问题:

  • 采纳 HTTP 缓存,设置 Cache-ControlLast-ModifiedEtag 等响应头
  • 采纳 Service Worker 离线缓存

前端正当利用localStorage

3. UI 框架按需加载

在日常应用 UI 框架,例如 element-UI、或者antd,咱们经常性间接援用整个UI

import ElementUI from 'element-ui'
Vue.use(ElementUI)

但实际上我用到的组件只有按钮,分页,表格,输出与正告 所以咱们要按需援用

import {Button, Input, Pagination, Table, TableColumn, MessageBox} from 'element-ui';
Vue.use(Button)
Vue.use(Input)
Vue.use(Pagination)

4. 组件反复打包

假如 A.js 文件是一个罕用的库,当初有多个路由应用了 A.js 文件,这就造成了反复下载

解决方案:在 webpackconfig文件中,批改 CommonsChunkPlugin 的配置

minChunks: 3

minChunks为 3 示意会把应用 3 次及以上的包抽离进去,放进公共依赖文件,防止了反复加载组件

5. 图片资源的压缩

图片资源尽管不在编码过程中,但它却是对页面性能影响最大的因素

对于所有的图片资源,咱们能够进行适当的压缩

对页面上应用到的 icon,能够应用在线字体图标,或者雪碧图,将泛滥小图标合并到同一张图上,用以加重http 申请压力。

6. 开启 GZip 压缩

拆完包之后,咱们再用 gzip 做一下压缩 装置compression-webpack-plugin

cnmp i compression-webpack-plugin -D

vue.congig.js 中引入并批改 webpack 配置

const CompressionPlugin = require('compression-webpack-plugin')

configureWebpack: (config) => {if (process.env.NODE_ENV === 'production') {
            // 为生产环境批改配置...
            config.mode = 'production'
            return {
                plugins: [new CompressionPlugin({
                    test: /\.js$|\.html$|\.css/, // 匹配文件名
                    threshold: 10240, // 对超过 10k 的数据进行压缩
                    deleteOriginalAssets: false // 是否删除原文件
                })]
            }
        }

在服务器咱们也要做相应的配置 如果发送申请的浏览器反对 gzip,就发送给它gzip 格局的文件 我的服务器是用 express 框架搭建的 只有装置一下 compression 就能应用

const compression = require('compression')
app.use(compression())  // 在其余中间件应用之前调用

7. 应用 SSR

SSR(Server side),也就是服务端渲染,组件或页面通过服务器生成 html 字符串,再发送到浏览器

从头搭建一个服务端渲染是很简单的,vue利用倡议应用 Nuxt.js 实现服务端渲染

四、小结

缩小首屏渲染工夫的办法有很多,总的来讲能够分成两大部分:资源加载优化 页面渲染优化

下图是更为全面的首屏优化的计划

大家能够依据本人我的项目的状况抉择各种形式进行首屏渲染的优化

Vue 中 computed 和 watch 有什么区别?

计算属性 computed

(1)** 反对缓存 **,只有依赖数据发生变化时,才会从新进行计算函数;(2)计算属性内 ** 不反对异步操作 **;(3)计算属性的函数中 ** 都有一个 get**(默认具备,获取计算属性)** 和 set**(手动增加,设置计算属性)办法;(4)计算属性是主动监听依赖值的变动,从而动静返回内容。

侦听属性 watch

(1)** 不反对缓存 **,只有数据发生变化,就会执行侦听函数;(2)侦听属性内 ** 反对异步操作 **;(3)侦听属性的值 ** 能够是一个对象,接管 handler 回调,deep,immediate 三个属性 **;(3)监听是一个过程,在监听的值变动时,能够触发一个回调,并 ** 做一些其余事件 **。

vue-loader 是什么?它有什么作用?

答复范例

  1. vue-loader是用于解决单文件组件(SFCSingle-File Component)的webpack loader
  2. 因为有了 vue-loader,咱们就能够在我的项目中编写SFC 格局的 Vue 组件,咱们能够把代码宰割为 <template><script><style>,代码会异样清晰。联合其余 loader 咱们还能够用 Pug 编写 <template>,用SASS 编写 <style>,用TS 编写 <script>。咱们的<style> 还能够独自作用以后组件
  3. webpack打包时,会以 loader 的形式调用vue-loader
  4. vue-loader被执行时,它会对 SFC 中的每个语言块用独自的 loader 链解决。最初将这些独自的块装配成最终的组件模块

原理

vue-loader会调用 @vue/compiler-sfc 模块解析 SFC 源码为一个描述符(Descriptor),而后为每个语言块生成 import 代码,返回的代码相似上面

// source.vue 被 vue-loader 解决之后返回的代码
​
// import the <template> block
import render from 'source.vue?vue&type=template'
// import the <script> block
import script from 'source.vue?vue&type=script'
export * from 'source.vue?vue&type=script'
// import <style> blocks
import 'source.vue?vue&type=style&index=1'
​
script.render = render
export default script

咱们想要 script 块中的内容被作为 js 解决(当然如果是 <script lang="ts"> 被作为 ts 理),这样咱们想要 webpack 把配置中跟 .js 匹配的规定都利用到形如 source.vue?vue&type=script 的这个申请上。例如咱们对所有 *.js 配置了babel-loader,这个规定将被克隆并利用到所在Vue SFC

import script from 'source.vue?vue&type=script

将被开展为:

import script from 'babel-loader!vue-loader!source.vue?vue&type=script'

相似的,如果咱们对 .sass 文件配置了style-loader + css-loader + sass-loader,对上面的代码

<style scoped lang="scss">

vue-loader将会返回给咱们上面后果:

import 'source.vue?vue&type=style&index=1&scoped&lang=scss'

而后 webpack 会开展如下:

import 'style-loader!css-loader!sass-loader!vue-loader!source.vue?vue&type=style&index=1&scoped&lang=scss'
  • 当解决开展申请时,vue-loader将被再次调用。这次,loader将会关注那些有查问串的申请,且仅针对特定块,它会选中特定块外部的内容并传递给前面匹配的loader
  • 对于 <script> 块,解决到这就能够了,然而 <template><style> 还有一些额定工作要做,比方

    • 须要用 Vue 模板编译器编译 template,从而失去render 函数
    • 须要对 <style scoped>中的 CSS 做后处理(post-process),该操作在 css-loader 之后但在 style-loader 之前

实现上这些附加的 loader 须要被注入到曾经开展的 loader 链上,最终的申请会像上面这样:

// <template lang="pug">
import 'vue-loader/template-loader!pug-loader!source.vue?vue&type=template'
​
// <style scoped lang="scss">
import 'style-loader!vue-loader/style-post-loader!css-loader!sass-loader!vue-loader!source.vue?vue&type=style&index=1&scoped&lang=scss'

Vue 模板编译原理

Vue 的编译过程就是将 template 转化为 render 函数的过程 分为以下三步

第一步是将 模板字符串 转换成 element ASTs(解析器)第二步是对 AST 进行动态节点标记,次要用来做虚构 DOM 的渲染优化(优化器)第三步是 应用 element ASTs 生成 render 函数代码字符串(代码生成器)

v-on 能够监听多个办法吗?

能够监听多个办法

<input type="text" :value="name" @input="onInput" @focus="onFocus" @blur="onBlur" />

v-on 罕用修饰符

  • .stop 该修饰符将阻止事件向上冒泡。同理于调用 event.stopPropagation() 办法
  • .prevent 该修饰符会阻止以后事件的默认行为。同理于调用 event.preventDefault() 办法
  • .self 该指令只当事件是从事件绑定的元素自身触发时才触发回调
  • .once 该修饰符示意绑定的事件只会被触发一次

Computed 和 Methods 的区别

能够将同一函数定义为一个 method 或者一个计算属性。对于最终的后果,两种形式是雷同的

不同点:

  • computed: 计算属性是基于它们的依赖进行缓存的,只有在它的相干依赖产生扭转时才会从新求值;
  • method 调用总会执行该函数。

Vue 为什么没有相似于 React 中 shouldComponentUpdate 的生命周期

  • 考点: Vue的变动侦测原理
  • 前置常识: 依赖收集、虚构DOM、响应式零碎

根本原因是 VueReact的变动侦测形式有所不同

  • 当 React 晓得发生变化后,会应用 Virtual Dom Diff 进行差别检测,然而很多组件实际上是必定不会发生变化的,这个时候须要 shouldComponentUpdate 进行手动操作来缩小diff,从而进步程序整体的性能
  • Vue在一开始就晓得那个组件产生了变动,不须要手动管制 diff,而组件外部采纳的diff 形式实际上是能够引入相似于 shouldComponentUpdate 相干生命周期的,然而通常正当大小的组件不会有适量的 diff,手动优化的价值无限,因而目前 Vue 并没有思考引入 shouldComponentUpdate 这种手动优化的生命周期

Vue Ref 的作用

  • 获取 dom 元素this.$refs.box
  • 获取子组件中的datathis.$refs.box.msg
  • 调用子组件中的办法this.$refs.box.open()

Vue 修饰符有哪些

事件修饰符

  • .stop 阻止事件持续流传
  • .prevent 阻止标签默认行为
  • .capture 应用事件捕捉模式, 即元素本身触发的事件先在此处解决,而后才交由外部元素进行解决
  • .self 只当在 event.target 是以后元素本身时触发处理函数
  • .once 事件将只会触发一次
  • .passive 通知浏览器你不想阻止事件的默认行为

v-model 的修饰符

  • .lazy 通过这个修饰符,转变为在 change 事件再同步
  • .number 主动将用户的输出值转化为数值类型
  • .trim 主动过滤用户输出的首尾空格

键盘事件的修饰符

  • .enter
  • .tab
  • .delete (捕捉“删除”和“退格”键)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

零碎润饰键

  • .ctrl
  • .alt
  • .shift
  • .meta

鼠标按钮修饰符

  • .left
  • .right
  • .middle

v-if、v-show、v-html 的原理

  • v-if 会调用 addIfCondition 办法,生成 vnode 的时候会疏忽对应节点,render 的时候就不会渲染;
  • v-show 会生成 vnode,render 的时候也会渲染成实在节点,只是在 render 过程中会在节点的属性中批改 show 属性值,也就是常说的 display;
  • v-html 会先移除节点下的所有节点,调用 html 办法,通过 addProp 增加 innerHTML 属性,归根结底还是设置 innerHTML 为 v -html 的值。

Vue.extend 作用和原理

官网解释:Vue.extend 应用根底 Vue 结构器,创立一个“子类”。参数是一个蕴含组件选项的对象。

其实就是一个子类结构器 是 Vue 组件的外围 api 实现思路就是应用原型继承的办法返回了 Vue 的子类 并且利用 mergeOptions 把传入组件的 options 和父类的 options 进行了合并

相干代码如下

export default function initExtend(Vue) {
  let cid = 0; // 组件的惟一标识
  // 创立子类继承 Vue 父类 便于属性扩大
  Vue.extend = function (extendOptions) {
    // 创立子类的构造函数 并且调用初始化办法
    const Sub = function VueComponent(options) {this._init(options); // 调用 Vue 初始化办法
    };
    Sub.cid = cid++;
    Sub.prototype = Object.create(this.prototype); // 子类原型指向父类
    Sub.prototype.constructor = Sub; //constructor 指向本人
    Sub.options = mergeOptions(this.options, extendOptions); // 合并本人的 options 和父类的 options
    return Sub;
  };
}

SPA、SSR 的区别是什么

咱们当初编写的 VueReactAngular利用大多数状况下都会在一个页面中,点击链接跳转页面通常是内容切换而非页面跳转,因为良好的用户体验逐步成为支流的开发模式。但同时也会有首屏加载工夫长,SEO不敌对的问题,因而有了SSR,这也是为什么面试中会问到两者的区别

  1. SPA(Single Page Application)即单页面利用。个别也称为 客户端渲染(Client Side Render),简称 CSRSSR(Server Side Render)即 服务端渲染。个别也称为 多页面利用(Mulpile Page Application),简称 MPA
  2. SPA利用只会首次申请 html 文件,后续只须要申请 JSON 数据即可,因而用户体验更好,节约流量,服务端压力也较小。然而首屏加载的工夫会变长,而且 SEO 不敌对。为了解决以上毛病,就有了 SSR 计划,因为 HTML 内容在服务器一次性生成进去,首屏加载快,搜索引擎也能够很不便的抓取页面信息。但同时 SSR 计划也会有性能,开发受限等问题
  3. 在抉择上,如果咱们的利用存在首屏加载优化需要,SEO需要时,就能够思考SSR
  4. 但并不是只有这一种代替计划,比方对一些不常变动的动态网站,SSR 反而浪费资源,咱们能够思考预渲染(prerender)计划。另外 nuxt.js/next.js 中给咱们提供了 SSG(Static Site Generate) 动态网站生成计划也是很好的动态站点解决方案,联合一些 CI 伎俩,能够起到很好的优化成果,且能节约服务器资源

内容生成上的区别:

SSR

SPA

部署上的区别

Vue 我的项目中有封装过 axios 吗?次要是封装哪方面的?

一、axios 是什么

axios 是一个轻量的 HTTP客户端

基于 XMLHttpRequest 服务来执行 HTTP 申请,反对丰盛的配置,反对 Promise,反对浏览器端和 Node.js 端。自Vue2.0 起,尤大发表勾销对 vue-resource 的官网举荐,转而举荐 axios。当初 axios 曾经成为大部分 Vue 开发者的首选

个性

  • 从浏览器中创立 XMLHttpRequests
  • node.js 创立 http申请
  • 反对 Promise API
  • 拦挡申请和响应
  • 转换申请数据和响应数据
  • 勾销申请
  • 主动转换JSON 数据
  • 客户端反对进攻XSRF

根本应用

装置

// 我的项目中装置
npm install axios --S
// cdn 引入
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

导入

import axios from 'axios'

发送申请

axios({        
  url:'xxx',    // 设置申请的地址
  method:"GET", // 设置申请办法
  params:{      // get 申请应用 params 进行参数凭借, 如果是 post 申请用 data
    type: '',
    page: 1
  }
}).then(res => {  
  // res 为后端返回的数据
  console.log(res);   
})

并发申请axios.all([])

function getUserAccount() {return axios.get('/user/12345');
}

function getUserPermissions() {return axios.get('/user/12345/permissions');
}

axios.all([getUserAccount(), getUserPermissions()])
    .then(axios.spread(function (res1, res2) { 
    // res1 第一个申请的返回的内容,res2 第二个申请返回的内容
    // 两个申请都执行实现才会执行
}));

二、为什么要封装

axios 的 API 很敌对,你齐全能够很轻松地在我的项目中间接应用。

不过随着我的项目规模增大,如果每发动一次 HTTP 申请,就要把这些比方设置超时工夫、设置申请头、依据我的项目环境判断应用哪个申请地址、错误处理等等操作,都须要写一遍

这种重复劳动不仅浪费时间,而且让代码变得冗余不堪,难以保护。为了进步咱们的代码品质,咱们应该在我的项目中二次封装一下 axios 再应用

举个例子:

axios('http://localhost:3000/data', {
  // 配置代码
  method: 'GET',
  timeout: 1000,
  withCredentials: true,
  headers: {
    'Content-Type': 'application/json',
    Authorization: 'xxx',
  },
  transformRequest: [function (data, headers) {return data;}],
  // 其余申请配置...
})
.then((data) => {
  // todo: 真正业务逻辑代码
  console.log(data);
}, (err) => {
  // 错误处理代码  
  if (err.response.status === 401) {// handle authorization error}
  if (err.response.status === 403) {// handle server forbidden error}
  // 其余错误处理.....
  console.log(err);
});

如果每个页面都发送相似的申请,都要写一堆的配置与错误处理,就显得过于繁琐了

这时候咱们就须要对 axios 进行二次封装,让应用更为便当

三、如何封装

  • 封装的同时,你须要和 后端协商好一些约定,申请头,状态码,申请超时工夫 …….
  • 设置接口申请前缀:依据开发、测试、生产环境的不同,前缀须要加以辨别
  • 申请头 : 来实现一些具体的业务,必须携带一些参数才能够申请(例如:会员业务)
  • 状态码: 依据接口返回的不同status,来执行不同的业务,这块须要和后端约定好
  • 申请办法:依据 getpost 等办法进行一个再次封装,应用起来更为不便
  • 申请拦截器: 依据申请的申请头设定,来决定哪些申请能够拜访
  • 响应拦截器:这块就是依据 后端 ` 返回来的状态码断定执行不同业务

设置接口申请前缀

利用 node 环境变量来作判断,用来辨别开发、测试、生产环境

if (process.env.NODE_ENV === 'development') {axios.defaults.baseURL = 'http://dev.xxx.com'} else if (process.env.NODE_ENV === 'production') {axios.defaults.baseURL = 'http://prod.xxx.com'}

在本地调试的时候,还须要在 vue.config.js 文件中配置 devServer 实现代理转发,从而实现跨域

devServer: {
    proxy: {
      '/proxyApi': {
        target: 'http://dev.xxx.com',
        changeOrigin: true,
        pathRewrite: {'/proxyApi': ''}
      }
    }
  }

设置申请头与超时工夫

大部分状况下,申请头都是固定的,只有少部分状况下,会须要一些非凡的申请头,这里将普适性的申请头作为根底配置。当须要非凡申请头时,将非凡申请头作为参数传入,笼罩根底配置

const service = axios.create({
    ...
    timeout: 30000,  // 申请 30s 超时
      headers: {
        get: {
          'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
          // 在开发中,个别还须要单点登录或者其余性能的通用申请头,能够一并配置进来
        },
        post: {
          'Content-Type': 'application/json;charset=utf-8'
          // 在开发中,个别还须要单点登录或者其余性能的通用申请头,能够一并配置进来
        }
  },
})

封装申请办法

先引入封装好的办法,在要调用的接口从新封装成一个办法裸露进来

// get 申请
export function httpGet({
  url,
  params = {}}) {return new Promise((resolve, reject) => {
    axios.get(url, {params}).then((res) => {resolve(res.data)
    }).catch(err => {reject(err)
    })
  })
}

// post
// post 申请
export function httpPost({
  url,
  data = {},
  params = {}}) {return new Promise((resolve, reject) => {
    axios({
      url,
      method: 'post',
      transformRequest: [function (data) {
        let ret = ''
        for (let it in data) {ret += encodeURIComponent(it) + '=' + encodeURIComponent(data[it]) + '&'
        }
        return ret
      }],
      // 发送的数据
      data,
      // url 参数
      params

    }).then(res => {resolve(res.data)
    })
  })
}

把封装的办法放在一个 api.js 文件中

import {httpGet, httpPost} from './http'
export const getorglist = (params = {}) => httpGet({url: 'apps/api/org/list', params})

页面中就能间接调用

// .vue
import {getorglist} from '@/assets/js/api'

getorglist({id: 200}).then(res => {console.log(res)
})

这样能够把 api 对立治理起来,当前保护批改只须要在 api.js 文件操作即可

申请拦截器

申请拦截器能够在每个申请里加上 token,做了对立解决后保护起来也不便

// 申请拦截器
axios.interceptors.request.use(
  config => {
    // 每次发送申请之前判断是否存在 token
    // 如果存在,则对立在 http 申请的 header 都加上 token,这样后盾依据 token 判断你的登录状况,此处 token 个别是用户实现登录后贮存到 localstorage 里的
    token && (config.headers.Authorization = token)
    return config
  },
  error => {return Promise.error(error)
  })

响应拦截器

响应拦截器能够在接管到响应后先做一层操作,如依据状态码判断登录状态、受权

// 响应拦截器
axios.interceptors.response.use(response => {
  // 如果返回的状态码为 200,阐明接口申请胜利,能够失常拿到数据
  // 否则的话抛出谬误
  if (response.status === 200) {if (response.data.code === 511) {// 未受权调取受权接口} else if (response.data.code === 510) {// 未登录跳转登录页} else {return Promise.resolve(response)
    }
  } else {return Promise.reject(response)
  }
}, error => {
  // 咱们能够在这里对异样状态作对立解决
  if (error.response.status) {
    // 解决申请失败的状况
    // 对不同返回码对相应解决
    return Promise.reject(error.response)
  }
})

小结

  • 封装是编程中很有意义的伎俩,简略的 axios 封装,就能够让咱们能够领略到它的魅力
  • 封装 axios 没有一个相对的规范,只有你的封装能够满足你的我的项目需要,并且用起来不便,那就是一个好的封装计划

理论工作中,你总结的 vue 最佳实际有哪些

从编码格调、性能、平安等方面说几条:

编码格调方面:

  • 命名组件时应用“多词”格调防止和 HTML 元素抵触
  • 应用“细节化”形式定义属性而不是只有一个属性名
  • 属性名申明时应用“驼峰命名”,模板或 jsx 中应用“肉串命名”
  • 应用 v-for 时务必加上 key,且不要跟v-if 写在一起

性能方面:

  • 路由懒加载缩小利用尺寸
  • 利用 SSR 缩小首屏加载工夫
  • 利用 v-once 渲染那些不须要更新的内容
  • 一些长列表能够利用虚构滚动技术防止内存适度占用
  • 对于深层嵌套对象的大数组能够应用 shallowRefshallowReactive升高开销
  • 防止不必要的组件形象

平安:

  • 不应用不可信模板,例如应用用户输出拼接模板:template: <div> + userProvidedString + </div>
  • 防止应用 v-html:url:style 等,防止htmlurl、款式等注入

vue 中应用了哪些设计模式

1. 工厂模式 – 传入参数即可创立实例

虚构 DOM 依据参数的不同返回根底标签的 Vnode 和组件 Vnode

2. 单例模式 – 整个程序有且仅有一个实例

vuex 和 vue-router 的插件注册办法 install 判断如果零碎存在实例就间接返回掉

3. 公布 - 订阅模式 (vue 事件机制)

4. 观察者模式 (响应式数据原理)

5. 装璜模式: (@装璜器的用法)

6. 策略模式 策略模式指对象有某个行为, 然而在不同的场景中, 该行为有不同的实现计划 - 比方选项的合并策略

退出移动版