vue2常见面试题

527 阅读11分钟

内容持续更新...

1.vue优点

1. 轻量化

使用 Vue.js 来开发生产应用或个人项目的一个显著优势是它是一个相对轻量化的框架/库。让我们看看不同前端框架/库的下载空间

2. 低复杂性

在使用 React 构建许多应用之后,一旦在混合代码库中添加状态管理,随着应用程序变大,代码库通常会变得非常复杂。我注意到 React 应用变得复杂的原因之一是 JSX 模板、 lifecycle(生命周期)方法和其他方法都存在于同一个对象中。这常常使理解逻辑流程变得非常困难,而Vue呢 :

3. Virtual DOM(虚拟 DOM)

就像 React 一样,Vue.js 实现了使用虚拟 DOM 来操作/渲染视图。通过使用虚拟 DOM,用户界面将通过在每次需要更改时不渲染真实的 DOM,而只是呈现虚拟 DOM 和真实 DOM 之间的部分差异,进而获得更好的性能。

4. 低学习曲线(对初学者友好)

从事 Web 开发的人都会学习以下三种基础技术:HTML、CSS 和 JavaScript。想象一下一个初学者必须学习一个叫做 JSX 的新东西,而不是 HTML。虽然 JSX 看起来类似于 HTML,但确实有很多不同之处将 JSX 与 HTML 区分开来,而这种学习就不是 Vue.js 所必需的。

如上面所示,Vue.js 使用与 HTML 相同的标记名,这使得将知识从 HTML 传输到 Vue.js 更加容易。此外,代码的模块化结构有助于理解 Vue.js 组件的不同动作部分。

对于那些熟悉 React 的人来说,学习 Vue.js 是小菜一碟,因为两者之间有很多相似之处。

2.vue父组件向子组件传递数据?

方式一

父传子主要通过在父组件v-model绑定数据,在子组件进行用props进行数据的接收

方式二

父组件触发子组件的方法,主要通过$refs来触发,同时传参

//触发子组件方法,并传参this.$refs.mychild.init("chrchr","120");

3.子组件像父组件传递事件

通过$emit触发事件

在子组件中触发事件:

`<button @click="toSearchProduct()">搜索</button>`
`export default {`
 `methods: {`
 `show: function () {`
 `console.log(this.name)`
 `},`
 `toSearchProduct: function () {`
 `this.$emit('parentEvent','哈哈啊哈哈')`
 `}`
 `}`
`}`

父组件:

`<x-test :name="username" @parentEvent="toClick"></x-test>`
`export default {`
 `components: {`
 `XTest`
 `},`
 `methods: {`
 `toClick: function (msg){`
 `console.log(msg) // 当子组件触发按钮时,msg获取值为 哈哈啊哈哈`
 `}`
 `}`
`}`
`</script>`

4.v-show和v-if指令的共同点和不同点

1.共同点:都能控制元素的显示和隐藏。

2.不同点:实现本质⽅法不同,v-show本质就是通过控制css中的display设置为none,控制隐藏,只会编译⼀次;v-if是动态的向DOM树内添加或者删除DOM元素,若初始值为false,就不会编译了。⽽且v-if不停的销毁和创建⽐较消耗性能。

3.总结:如果要频繁切换某节点,使⽤v-show(切换开销⽐较⼩,初始开销较⼤)。如果不需要频繁切换某节点使⽤v-if(初始渲染开销较⼩,切换开销⽐较⼤)。

5.如何让CSS只在当前组件中起作用

当前组件写成

6....

7.如何获取dom

方法一:

直接给相应的元素加id,然后再document.getElementById("id");获取,然后设置相应属性或样式

方法二:

使用ref,给相应的元素加ref=“name” 然后再this.$refs.name获取到该元素

8.说出几种vue当中的指令和它的用法?

v-bind: 绑定数据

v-model: 能够实现表单元素值的双向绑定

v-on: 用于事件的绑定

v-if,v-else-if,v-else: 有条件的渲染某些内容

v-for指令:队列表数据的渲染很常用

v-show指令:行所在标签的显示与隐藏

9.vue-loader是什么?使用它的用途有哪些?

10.为什么使用key

使用 v-for 更新已渲染的元素列表时,默认用 就地复用 策略。列表数据修改的时候,vue 会根据 key 去判断某个值是否修改 —— 如果修改,则重新渲染这一项,否则复用之前的元素。在 v-for 中使用 key 是一个最佳实践,但是我们需要注意使用的是什么 key 。

如果是使用 index 作为 key :

在末尾插入 F 的话没有问题,因为这个时候不影响前面元素的 index,每个元素的 index 不变,而 vue 可以依据这些 index 对元素进行复用;但是现在是在中间插入 F,一旦插入成功,那么 CDE 的 index 都会改变,这时候 CDE 都需要重新渲染一次。而 AB 的 index 是不变的,所以 AB 可以得到复用。

如果是使用 id 作为 key :

这里就要注意了,这个 id 是唯一的,也是固定不变的(也可以采用元素本身的值作为这个唯一的 id),不管插入还是删除,元素该是哪个 id 还是哪个 id ,这意味着以这样的 id 作为key 时,所有旧元素都可以得到复用。所以这种情况下,我们只需要渲染新插入的 F 元素即可。

总结:vue中列表循环需加:key="唯一标识" 唯一标识可以是item里面id index等,因为vue组件高度复用增加Key可以标识组件的唯一性,为了更好地区别各个组件 key的作用主要是为了高效的更新虚拟DOM

11.axios及安装

axios的基本概念及安装配置方法

ajax:异步请求,是一种无需再重新加载整个网页的情况下,能够更新部分网页的技术

axios:用于浏览器和node.js的基于promise的HTTP客户端

1.从浏览器制作XMLHttpRequests

2.让HTTP从node.js的请求

3.支持promise api

4.拦截请求和响应

5.转换请求和响应数据

6.取消请求

7.自动转换成json数据

8.客户端支持防止xsrf

axios的安装:

cmd命令行进入到vue项目下,执行npm install axios 然后执行提示npm install --save axios vue-axios

配置方法:

打开vue的编辑器,找到当前项目的main.js文件,输入:

import axios from 'axios'

Vue.prototype.axios = axios

12.axios解决跨域

`在config下的index.js里输入:`
 `proxyTable: {`
 `'/api': {  //使用"/api"来代替"http://f.apiplus.c"` 
 `target: 'http://127.0.0.1:5000/', //源地址` 
 `changeOrigin: true, //改变源 ,允许跨域`
 `pathRewrite: {` 
 `'^/api': '' //路径重写` 
 `}` 
 `}`

13.v-modal的使用

v-model 主要是用于表单上数据的双向绑定

1:主要用于 input,select,textarea,component

2:修饰符:

.lazy- 取代input监听change事件

.number- 输入字符串转为数字

.trim- 输入首尾空格过滤

14.scss的安装以及使用

安装sass 依赖包 ,在cmd界面输入:

npm install sass-loader --save-dev
npm install node-sass --sava-dev

在build文件夹下的webpack.base.conf.js的rules里面添加配置

{
test: /\.scss$/,
loaders: ['style', 'css', 'sass']}

使用scss时候在所在的style样式标签上添加lang=”scss”即可应用对应的语法,否则报错

15.请说出vue.cli项目中src目录每个文件夹和文件的用法?

vue-cli 项目中src目录每个文件夹和文件的用法

assets 文件夹是放静态资源

components 是放组件

router 是定义路由相关的配置

view 视图

app.vue 是一个应用主组件

main.js 是入口文件

webpack目录:

├─build // 保存一些webpack的初始化配置,项目构建│
├─build.js // 生产环境构建│
├─check-version.js // 检查npm、node版本│
├─vue-loader.conf.js // webpack loader配置│
├─webpack.base.conf.js// webpack基础配置│
├─webpack.dev.conf.js // 开发环境配置,构建本地开发服务器│
├─webpack.prod.conf.js// 生产环境的配置│
├─config // config文件夹保存一些项目初始化的配置│
├─dev.env.js // 开发环境的配置│
├─index.js // 项目一些配置变量│
├─prod.env.js // 生产环境的配置│
├─dist // 打包后的项目
├─node_modules // 依赖包│
├─src // 源码目录│
├─assets // 静态文件目录│
├─components // 组件文件│
├─router // 路由│
├─App.vue // 是项目入口文件│
├─main.js // 是项目的核心文件,入口
├─static // 静态资源目录
├─.babelrc // Babel的配置文件
├─.editorconfig // 代码规范配置文件
├─.gitignore // git忽略配置文件
├─.postcssrc.js // postcss插件配置文件
├─index.html // 页面入口文件
├─package-lock.json // 项目包管控文件
├─package.json // 项目配置
└─README.md // 项目说明书

16.分别简述computed和watch的使用场景

特点和区别:

vue的computed选项主要用于同步对数据的处理,而watch选项主要用于事件的派发,可异步.

这两者都能达到同样的效果,但是基于它们各自的特点,使用场景会有一些区分.

computed拥有缓存属性,只有当依赖的数据发生变化时,关联的数据才会变化,适用于计算或者格式化数据的场景.

watch监听数据,有关联但是没有依赖,只要某个数据发生变化,就可以处理一些数据或者派发事件并同步/异步执行.

计算属性

抽象的概念不容易理解,用多了高频的场景自然就熟悉了,计算属性表现为同步处理数据.

金融领域的分期付款,P2P年化收益,带有计算性质的,都可以优先考虑computed.

不需要关注点击事件或者其他数据,只要将计算规则写在属性里,就能实时获取对应的数据.

电商领域的购物车统计,一个数据依赖于一个或者多个数据.

当购物车数量和产品变化时,自动计算出价格*数量的总和.

如果有优惠券或者折扣,自动减去优惠和计算折扣金额即可,同上实时计算.

只要购买数量,购买价格,优惠券,折扣券等任意一个发生变化,总价都会自动跟踪变化.

侦听器

watch侦听器能做到的计算属性computed也能做到,什么时候适合用侦听器呢?

主要适用于与事件和交互有关的场景,数据变化为条件,适用于一个数据同时触发多个事物.

如当借款额度大于可借额度时,弹出toast提示,并将当前借款额度调整到最大额度.

可以看到,数据的变化为触发弹框提示,有且仅在一定金额条件下才触发,而不是实时触发.

总结:弹框提示等事件交互的,适用于watch,数据计算和字符处理的适用于computed

17.v-on可以监听多个方法吗

18.$nextTick的使用

this.$nextTick()将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。它跟全局方法 Vue.nextTick 一样,不同的是回调的 this 自动绑定到调用它的实例上。

我们更改了某个dom元素内部的文本,而这时候我们想直接打印出这个被改变后的文本是需要dom更新之后才会实现的,也就好比我们将打印输出的代码放在setTimeout(fn, 0)中;

19.vue组件中data为什么必须是一个函数

vue组件中的data必须是函数

引用数据类型

Object是引用数据类型,如果不用function 返回,每个组件的data 都是内存的同一个地址,一个数据改变了其他也改变了;

javascipt只有函数构成作用域(注意理解作用域,只有函数的{}构成作用域,对象的{}以及 if(){}都不构成作用域),data是一个函数时,每个组件实例都有自己的作用域,每个实例相互独立,不会相互影响

20.vue事件对象的使用

用 v-on 指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码。

1、普通事件:

`<!-- HTML代码 -->`
`<div id="app">`
 `<button @click="A">1</button>`
 `<p>{{msg}}</P>`
`</div>`
`//每次点击按钮,p标签中的数字都会+1`
`new Vue({`
 `el: "#app",`
 `data:{`
 `msg:0`
 `}`
 `methods: {`
 `A() {`
 `this.msg++`
 `}`
 `},`
`})`

2、事件传参

`<!-- HTML代码 若需要访问原始的DOM对象,可以将$event传入方法-->`
`<div id="app">`
 `<button @click="event(a,b)">1</button>`
`</div>`
`new Vue({`
 `el: "#app",`
 `data: {`
 `a: 20,`
 `b: 20`
 `},`
 `methods: {`
 `event(a, b) {`
 `console.log(a + b)`
 `}`
 `},`
`})`
`//点击button控制台会输出40`

3、事件修饰符

留其名:vue组件间的通信(7种)​

22.渐进式框架的理解

文刀刘:Vue中双向数据绑定是如何实现的​

24.单页面应用和多页面应用区别及优缺点

单页面应用
一个项目中只有一个完整的html页面,其他的都是部分的html片段组成。页面跳转只是局部刷新,不会重新加载全部资源。片段之间的切换快,比较容易实现转场动画。

缺点:

1,不利于seo,2,导航不可用,如果一定要导航需要自行实现前进、后退。(由于是单页面不能用浏览器的前进后退功能,所以需要自己建立堆栈管理)3,初次加载时耗时多4,页面复杂度提高很多
多页面应用
一个项目是由多个完整的html页面组成,页面跳转所有的资源都要重新加载,页面之间的切换会出现卡顿空白的问题,不容易实现切换动画等

借鉴:前端:你要懂的单页面应用和多页面应用 - 掘金

25.vue中过滤器有什么作用及详解

运用的地方

`<!-- 在双花括号中 -->`
`{{ date | formatDate}}`
``<!-- 在 `v-bind` 中 -->``
`<div v-bind:id="data | formatDate"></div>`

场景: 时间格式的转化

注册过滤器函数

第一种是全局过滤器,我们可以直接在vue对象上使用filter方法注册过滤器,这种全局注册的过滤器在任何一个组件内都可以使用。

`// 全局函数Vue.filter('formatTime', function (value) {`
 `const date = new Date(val);`
 `const hour = date.getHours();`
 ``const minutes = date.getMinutes();  const seconds = date.getSeconds();  return `${hour} : ${minutes} : ${seconds}`;``
`})`

第二种则是组件内部的过滤器,注册组件内部过滤器则只能在当前组件内使用,接下来我们使用这两种方式注册过滤器函数。

特点:过滤器可以串联

{{ message | filterA | filterB }}

接收参数

{{ message | filterA('arg1', arg2) }}

filterA 被定义为接收三个参数的过滤器函数。其中 message 的值作为第一个参数,普通字符串 'arg1' 作为第二个参数,表达式 arg2 的值作为第三个参数。

注意使用:

1、 当有局部和全局两个名称相同的过滤器时候,会以就近原则进行调用,即:局部过滤器优先于全局过滤器被调用!

2、 一个表达式可以使用多个过滤器。过滤器之间需要用管道符“|”隔开。其执行顺序从左往右

26.v-if和v-for的优先级

当 Vue 处理指令时,v-forv-if 具有更高的优先级

那么我们从源码的角度去看他
源码位置compiler/codegen/index.js

genElement方法中,我们可以看到一些if else的判断

`if (el.staticRoot && !el.staticProcessed) {`
 `return genStatic(el, state)`
 `} else if (el.once && !el.onceProcessed) {`
 `return genOnce(el, state)`
 `} else if (el.for && !el.forProcessed) {`
 `return genFor(el, state)`
 `} else if (el.if && !el.ifProcessed) {`
 `return genIf(el, state)`
 `} else if (el.tag === 'template' && !el.slotTarget && !state.pre) {`
 `return genChildren(el, state) || 'void 0'`
 `} else if (el.tag === 'slot') {`
 `return genSlot(el, state)`
 `} else {`
 `// component or element`
 `let code`
 `if (el.component) {`
 `code = genComponent(el.component, el, state)`
 `} else {`
 `let data`
 `if (!el.plain || (el.pre && state.maybeComponent(el))) {`
 `data = genData(el, state)`
 `}`
 `const children = el.inlineTemplate ? null : genChildren(el, state, true)`
 ``code = `_c('${el.tag}'${``
 ``data ? `,${data}` : '' // data``
 `}${`
 ``children ? `,${children}` : '' // children``
 ``})` ``
 `}`
 `// module transforms`
 `for (let i = 0; i < state.transforms.length; i++) {`
 `code = state.transforms[i](el, code)`
 `}`
 `return code`
 `}`

所以可以得出结论,v-for的优先级是高于v-if的,如果两者同时出现的话,那每次循环都会执行v-if,会很浪费性能,我们正确的做法应该是再v-for的外面新增一个模板标签template,在template上使用v-if

类似:

`<template v-if="isTrue">`
 `<p v-for="item in arr" >{{item}}</p>`
`</template>`

27.assets和static的区别

相同点:

assets和static两个都是存放静态资源文件。项目中所需要的资源文件图片,字体图标,样式文件等都可以放在这两个文件下,这是相同点

不相同点:

assets中存放的静态资源文件在项目打包时,也就是运行npm run build时会将assets中放置的静态资源文件进行打包上传,所谓打包简单点可以理解为压缩体积,代码格式化。而压缩后的静态资源文件最终也都会放置在static文件中跟着index.html一同上传至服务器

static中放置的静态资源文件就不会要走打包压缩格式化等流程,而是直接进入打包好的目录,直接上传至服务器。因为避免了压缩直接进行上传,在打包时会提高一定的效率,但是static中的资源文件由于没有进行压缩等操作,所以文件的体积也就相对于assets中打包后的文件提交较大点。在服务器中就会占据更大的空间。所以简单点使用建议如下:

将项目中template需要的样式文件js文件等都可以放置在assets中,走打包这一流程。减少体积。而项目中引入的第三方的资源文件如iconfoont.css等文件可以放置在static中,因为这些引入的第三方文件已经经过处理,我们不再需要处理,直接上传。

当然具体情况,具体分析,在不同的开发环境,不同的需求下,不同具体情况采用合适方式

28.列举常用的指令

1. 文本插值:{{ }} Mustache

2. DOM属性绑定: v-bind

3. 指令绑定一个事件监听器:v-on

4. 实现表单输入和应用状态之间的双向绑定:v-model

5. 控制切换一个元素的显示:v-if 和 v-else

6. 列表渲染:v-for

7. 根据条件展示元素:v-show

8.更新DOM对象的 textContent: v-text

9.更新DOM对象的innerHTML:v-html

29.vue常用的修饰符

.lazy

在默认情况下,v-model 在每次 input 事件触发后将输入框的值与数据进行同步 。你可以添加 lazy 修饰符,从而转变为使用 change 事件进行同步:

.number

如果想自动将用户的输入值转为数值类型,可以给 v-model 添加 number 修饰符

.trim

如果要自动过滤用户输入的首尾空白字符,可以给 v-model 添加 trim 修饰符:

事件修饰符:

`<!-- 阻止单击事件继续传播 -->`
`<a v-on:click.stop="doThis"></a>`
`<!-- 提交事件不再重载页面 -->`
`<form v-on:submit.prevent="onSubmit"></form>`
`<!-- 修饰符可以串联 -->`
`<a v-on:click.stop.prevent="doThat"></a>`
`<!-- 只有修饰符 -->`
`<form v-on:submit.prevent></form>`
`<!-- 添加事件监听器时使用事件捕获模式 -->`
`<!-- 即元素自身触发的事件先在此处处理,然后才交由内部元素进行处理 -->`
`<div v-on:click.capture="doThis">...</div>`
`<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->`
`<!-- 即事件不是从内部元素触发的 -->`
`<div v-on:click.self="doThat">...</div>`
`注意:`
`使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用 v-on:click.prevent.self 会阻止所有的点击,`
`而 v-on:click.self.prevent 只会阻止对元素自身的点击。`
`<!-- 点击事件将只会触发一次 -->`
`<a v-on:click.once="doThis"></a>`

按键修饰符

在监听键盘事件时,我们经常需要检查常见的键值。Vue 允许为 v-on 在监听键盘事件时添加按键修饰符:

``<!-- 只有在 `keyCode` 是 13 时调用 `vm.submit()` -->``
`<input v-on:keyup.13="submit">`
`记住所有的 keyCode 比较困难,所以 Vue 为最常用的按键提供了别名:`
`<!-- 同上 -->`
`<input v-on:keyup.enter="submit">`
`<!-- 缩写语法 -->`
`<input @keyup.enter="submit">`
`全部的按键别名:`
`.enter`
`.tab`
`.delete (捕获“删除”和“退格”键)`
`.esc`
`.space`
`.up`
`.down`
`.left`
`.right`

30.数组更新检测

Vue包含一组观察数组的变异方法,所以它们也将会触发视图更新。这些方法如下:

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reserve()
`替换数组`
 `变异方法会改变被这些方法调用的原始数组。相比之下,也有非变异方法,例如: filter(), concat() 和 slice() 。这些方法不会改变原始数组,但总是会返回一个新数组。当使用非变异方法时,可以用新数组替换旧数组:`
`example.items = example.items.filter(function (item) {`
 `return item.message.match(/Foo/)`
`})`
  1. 注意事项
    由于 Javascript 的限制,Vue 不能检测到以下变动的数组:
    1.利用索引直接设置一个项,例如: vm.items[index] = newVal
    2.修改数组的长度时,例如: vm.items.length = newLength
`var vm = new Vue({`
 `data: {`
 `items: ['a', 'b', 'c']`
 `}`
`})`
`vm.items[1] = 'x'   // 不是响应性的`
`vm.items.length = 2 // 不是响应性的`

为了解决第一类问题,一下两种方法都可以实现和vm.items[index] = newVal相同的效果,同时也将触发状态更新:

31.Vue.set视图更新

`// Vue.set`
`Vue.set(vm.items, index, newVal)`
`vm.$set(vm.items, index, newVal)`
`// Array.prototype.splice`
`vm.items.splice(index, 1, newVal)`
`vm.items.splice(newLength)`

32.自定义指令详解

vue自定义指令--directive

官方详解:

`/*  自定义指 */`
`import Vue from 'vue'`
`/**`
 `* 模板`
 `* v-lang`
 `* 五个注册指令的钩子函数`
 `*/`
`Vue.directive('mydirective', {`
 `/**`
 `* 1.被绑定`
 `* 做绑定的准备工作`
 `* 比如添加事件监听器,或是其他只需要执行一次的复杂操作`
 `*/`
 `bind: function(el, binding, vnode) {`
 `console.log('1 - bind');`
 `},`
 `// 2.绑定到节点`
 `inserted: function(el, binding, vnode) {`
 `console.log('2 - inserted');`
 `},`
 `/**`
 `* 3.组件更新`
 `* 根据获得的新值执行对应的更新`
 `* 对于初始值也会调用一次`
 `*/`
 `update: function(el, binding, vnode, oldVnode) {`
 `console.log('3 - update');`
 `},`
 `// 4.组件更新完成`
 `componentUpdated: function(el, binding, vnode, oldVnode) {`
 `console.log('4 - componentUpdated');`
 `},`
 `/**`
 `* 5.解绑`
 `* 做清理操作`
 `* 比如移除bind时绑定的事件监听器`
 `*/`
 `unbind: function(el, binding, vnode) {`
 `console.log('5 - bind');`
 `}`
`})`
`/**`
`钩子函数`
`1、bind:只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个绑定时执行一次的初始化动作。`
`2、inserted:被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于document中)。`
`3、update:被绑定于元素所在的模板更新时调用,而无论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新。`
`4、componentUpdated:被绑定元素所在模板完成一次更新周期时调用。`
`5、unbind:只调用一次,指令与元素解绑时调用。`
`*/`

33.vue的两个核心点

数据驱动、组件系统

**数据驱动:**ViewModel,保证数据和视图的一致性。

**组件系统:**应用类UI可以看作全部是由组件树构成的。

34.vue和jQuery的区别

35 引进组件的步骤

36.Vue-cli打包命令是什么?打包后悔导致路径问题,应该在哪里修改

37.三大框架的对比

38.跨组件双向数据绑定

39.delete和Vue.delete删除数组的区别

40.SPA首屏加载慢如何解决

41.Vue-router跳转和location.href有什么区别

42.vue slot

43.你们vue项目是打包了一个js文件,一个css文件,还是有多个文件?

44.vue遇到的坑,如何解决的?

45.Vue里面router-link在电脑上有用,在安卓上没反应怎么解决?

46.Vue2中注册在router-link上事件无效解决方法

47.RouterLink在IE和Firefox中不起作用(路由不跳转)的问题

48.axios的特点有哪些

49.请说下封装 vue 组件的过程?

50.vue 各种组件通信方法(父子 子父 兄弟 爷孙 毫无关系的组件)

51.params和query的区别

52.vue mock数据

53 vue封装通用组件

54.vue初始化页面闪动问题

55.vue禁止弹窗后的屏幕滚动

56.vue更新数组时触发视图更新的方法

57.vue常用的UI组件库

58.vue如何引进本地背景图片

59.vue如何引进sass

60.vue修改打包后静态资源路径的修改