Vue知识总结

文章目录

  • 1.概念
    • 1.1 对SPA单页面的理解,优缺点是什么?
    • 1.2 什么是MVVM?
  • 2. 基础知识
    • 2.1 v-show 和 v-if 的区别?
    • 2.2 computed ,methods, watch 的区别和运用场景?
  • 3.组件
    • 3.1 组价中的data为什么是一个函数?
    • 3.2 Vue组件间通信的方式?
    • 3.3 对keep-alive的理解?
  • 4.生命周期
    • 4.1谈谈你对 Vue 生命周期的理解?
    • 4.2 Vue 的父组件和子组件生命周期钩子函数执行顺序?
    • 4.3 父组件可以监听到子组件的生命周期吗?
    • 4.4 在哪个生命周期内调用异步请求?
  • 5.全家桶
    • 5.1 vuex介绍
    • 5.2 dispatch和commit的区别?
  • 6. vue路由
    • 6.1 $route 和 $router的区别?
    • 6.2 vue-router 中常用的 hash 和 history 路由模式实现原理吗?(1)hash 模式的实现原理
    • 6.3 vue-router有哪几种导航钩子?
  • 7. 原理
    • 7.1 怎样理解Vue单向数据流?
    • 7.2 直接给一个数组赋值,Vue能检测到数据变化吗?
    • 7.3 v-model的原理?
    • 7.4 runtime-only 和 compiler+runtime的区别?
    • 6.5 render函数解析
    • 6.6 Vue中key的作用?
    • 6.7 Vue的响应式原理?
    • 6.8 Vue检测数组或对象的变化的注意事项?
      • 1. 数组
      • 2. 对象

1.概念

1.1 对SPA单页面的理解,优缺点是什么?

signal page application 单页面应用,仅在页面初始化的时候加载相应的html,cssjs.一旦页面的加载完成,SPA不会因为用户操作而进行页面的重新加载或跳转,取而代之的是利用路由机制实现html内容的变换,UI与用户交互,避免页面的重新加载.

优点:

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

缺点:

  1. 初次加载耗时多:为实现单页面web应用功能及显示效果,需要在加载页面时候将js、css统一加载,部分页面按需加载
  2. SEO难度大:所有内容都在一个页面中动态切换显示

1.2 什么是MVVM?

Model-view-ViewModel (MVVM) 是一个软甲架构的设计模式.又微软 WPF 和 Silverlight 的架构师 Ken Cooper 和 Ted Peters 开发,是一种简化用户界面的事件驱动变成方式.
Model–View–ViewModel (MVVM) 是一个软件架构设计模式,由微软 WPF 和 Silverlight 的架构师 Ken Cooper 和 Ted Peters 开发,是一种简化用户界面的事件驱动编程方式。

MVC:Model–View–Controller(MVC)模式.

MVVM:model view viewModel 视图模式。MVVM 的出现促进了前端开发与后端业务逻辑的分离,极大地提高了前端开发效率,MVVM 的核心是 ViewModel 层,它就像是一个中转站(value converter),负责转换 Model 中的数据对象来让数据变得更容易管理和使用,该层向上与视图层进行双向数据绑定,向下与 Model 层通过接口请求进行数据交互,起呈上启下作用。

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

  <div id="app">
      <p>{
    {message}}p>
      <button v-on:click="showMessage()">Click mebutton>
  div>

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

{
     
    "url": "/your/server/data/api",
    "res": {
     
        "success": true,
        "name": "IoveC",
        "domain": "www.cnblogs.com"
    }
}

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

var app = new Vue({
     
    el: '#app',
    data: {
       // 用于描述视图状态   
        message: 'Hello Vue!', 
    },
    methods: {
       // 用于描述视图行为  
        showMessage(){
     
            let vm = this;
            alert(vm.message);
        }
    },
    created(){
     
        let vm = this;
        // Ajax 获取 Model 层的数据
        ajax({
     
            url: '/your/server/data/api',
            success(res){
     
                vm.message = res;
            }
        });
    }
})

MVVM 框架实现了双向绑定,这样 ViewModel 的内容会实时展现在 View 层,前端开发者再也不必低效又麻烦地通过操纵 DOM 去更新视图,MVVM 框架已经把最脏最累的一块做好了,我们开发者只需要处理和维护 ViewModel,更新数据视图就会自动得到相应更新。这样 View 层展现的不是 Model 层的数据,而是 ViewModel 的数据,由 ViewModel 负责与 Model 层交互,这就完全解耦了 View 层和 Model 层,这个解耦是至关重要的,它是前后端分离方案实施的重要一环。

2. 基础知识

2.1 v-show 和 v-if 的区别?

v-show 通过display设置为none来控制元素的隐藏与现实,导尿管v-show为fasle时,将页面中已经渲染的 DOM 元素的 display 设置为 none,且是行内样式.用于频繁切换的场景

v-if 是真正的重新渲染,确保在每次切换的过程中条件块内的事件监听器和子组件都适当的销毁和创建,当v-if 为false 时,根本不会有元素渲染在页面中.用于不频繁切换的场景

2.2 computed ,methods, watch 的区别和运用场景?

computed : 是计算属性,依赖其他的属性值,用来计算复杂的逻辑运算,并且 computed 的值会有缓存,只有它依赖的属性值发生改变,下一次重新获取 computed的时候才会重新计算,

methods : methods 将被混入到 Vue 实例中。可以直接通过 VM 实例访问这些方法,或者在指令表达式中使用。方法中的 this 自动绑定为 Vue 实例。

watch : 监听,用于监听数据的变化,其中可以监听的数据来源有三部分data,prop,computed,两个参数,一个是新值.一个是旧值.

注意,不应该使用箭头函数来定义 watcher 函数 (例如 searchQuery: newValue => this.updateAutocomplete(newValue))。理由是箭头函数绑定了父级作用域的上下文,所以 this 将不会按照期望指向 Vue 实例,this.updateAutocomplete 将是 undefined。

运用场景:
当我们需要数值计算,并且依赖于其他数据是,应该使用 computed ,因为可以利用 computed 的缓存特性,避免每次获取值时,都需要重新计算.

当我们需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用 watch 选项允许我们执行异步操作 ( 访问一个 API ),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。

methods存储方法,computed用来存储需要处理的数据,methods每一次都会调用,computed只有依赖的属性值发生变化的时候才会重新计算.

3.组件

3.1 组价中的data为什么是一个函数?

  • 首先,如果不是一个函数,Vue直接就会报错。
  • 其次,原因是在于Vue让每个组件对象都返回一个新的对象,因为如果是同一个对象的,组件在多次使用后会相互影响。

使用后会相互影响。

3.2 Vue组件间通信的方式?

  1. 父子组件通信
  • props 和 $emit

父组件通过props向子组件传递数据
子组件通过事件向父组件发送消息
Vue知识总结_第1张图片

  • ref和 $children/$parent

子组件直接访问父组件,或者是子组件访问跟组件。
父组件访问子组件:使用$children或$refs
子组件访问父组件:使用$parent
this.$children是一个数组类型,它包含所有子组件对象。

  1. 非父子组件通信
  • 事件总线

这种方法通过一个空的 Vue 实例作为中央事件总线(事件中心),用它来触发事件和监听事件,从而实现任何组件间的通信,包括父子、隔代、兄弟组件。
定义
Vue.prototype.$bus = new Vue()
发出事件$bus.$emit(‘事件名’,参数)
触发事件$bus.$on(‘事件名’)

  • vuex

全局变量, 状态管理模式

3.3 对keep-alive的理解?

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

它们有两个非常重要的属性:

  • include - 字符串或正则表达,只有匹配的组件会被缓存
  • exclude - 字符串或正则表达式,任何匹配的组件都不会被缓存

router-view 也是一个组件,如果直接被包在 keep-alive 里面,所有路径匹配到的视图组件都会被缓存:

通过create生命周期函数来验证

4.生命周期

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

  • beforeCreate:组件实例被创建之初,组件的属性生效之前

  • created:在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,el 还不可用

  • beforeMount:在挂载开始之前被调用:相关的 render 函数首次被调用。

  • mounted:实例被挂载后调用,这时 el 被新创建的 vm.el也在文档内。

  • beforeUpdate:数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。

  • updated:由于数据更新导致虚拟DOM重新渲染和打补丁,在这之后调用该钩子。
    当这个钩子被调用时,组件DOM已经更新,所有现在可以执行依赖于DOM的操作。
    updated不会保证所有的子组件也都一起被重绘,如果希望等整个视图重绘完毕,可以在updated里面使用vm.$nextTick

  • beforeDestroy:实例销毁之前调用。在这一步,实例仍然完全可用。

  • destroyed:实例销毁后调用。该钩子被调用后,对应 Vue 实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁。

  • activated:keep-alive 组件的相关事件,被keep-alive缓存的组件启用的时候调用

  • deactivated:keep-alive 组件的相关事件,被keep-alive缓存的组件停掉的时候调用

Vue知识总结_第2张图片

4.2 Vue 的父组件和子组件生命周期钩子函数执行顺序?

渲染

父beforeCreate => 父created => 父beforeMount => 子beforeCreate => 子created => 子beforeMount => 子mounted => 父mounted

更新过程

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

销毁

父beforeDestroy => 子beforeDestroy => 子destroy => 父destroy

4.3 父组件可以监听到子组件的生命周期吗?

  1. 钩子函数
<chile @hook:mounted = 'doSomethind'></child>
  1. $emit

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

created/beforeMounted/mounted

5.全家桶

5.1 vuex介绍

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
核心概念和方法

  • State 单一状态树,包含了全部应用级状态,是唯一的数据源。 一般computed中计算,mapState
  • Getter 从state中派生一些状态,根据依赖进行缓存,只有依赖变化才重新计算,一般computed,mapGetters
  • Mutation 修改数据的方法 commit,methods, MapMutations
  • Action 异步方法 dispatch,methods,mapActions
  • Module 模块化

5.2 dispatch和commit的区别?

  1. commit => mutations 用来触发同步操作的方法
  2. dispatch => commit 用来触发异步操作的方法

6. vue路由

6.1 $route 和 $router的区别?

  1. $route获取的是当前处于活跃状态的路由
  2. $router是 router 实例通过 this.$router 访问路由器,相当于获取了整个路由文件,在$router.option.routes中,或查看到当前项目的整个路由结构 具有实例方法

6.2 vue-router 中常用的 hash 和 history 路由模式实现原理吗?(1)hash 模式的实现原理

(1)hash 模式的实现原理

  • 早期的前端路由的实现就是基于 location.hash 来实现的。

URL的hash也就是锚点(#), 本质上是改变window.location的href属性.
我们可以通过直接赋值location.hash来改变href, 但是页面不发生刷新

其实现原理很简单,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 事件,这时我们需要手动触发页面跳转(渲染)。

6.3 vue-router有哪几种导航钩子?

vue-router 的导航钩子,主要用来作用是拦截导航,让他完成跳转或取消。

有三种方式可以植入路由导航过程中:

  1. 全局的(beforeEach,afterEach)

  2. 单个路由独享的(beforeEnter)

  3. 组件级的(beforeRouterEnter,beforeRouterLeave,beforeUpdate)

1. 全局导航钩子

全局导航钩子主要有两种钩子:前置守卫、后置钩子,

注册一个全局前置守卫:

const router = new VueRouter({
      ... });
router.beforeEach((to, from, next) => {
     
    // do someting
});

这三个参数 to 、from 、next 分别的作用:

  • to: Route,代表要进入的目标,它是一个路由对象

  • from: Route,代表当前正要离开的路由,同样也是一个路由对象

  • next: Function,这是一个必须需要调用的方法,而具体的执行效果则依赖 next 方法调用的参数

    • next():进入管道中的下一个钩子,如果全部的钩子执行完了,则导航的状态就是 confirmed(确认的)
    • next(false):这代表中断掉当前的导航,即 to 代表的路由对象不会进入,被中断,此时该表 URL 地址会被重置到 from 路由对应的地址
    • next(‘/’) 和 next({path: ‘/’}):在中断掉当前导航的同时,跳转到一个不同的地址
    • next(error):如果传入参数是一个 Error 实例,那么导航被终止的同时会将错误传递给 router.onError() 注册过的回调
      对于全局后置钩子:
router.afterEach((to, from) => {
     
    // do someting
});

不同于前置守卫,后置钩子并没有 next 函数,也不会改变导航本身

  1. 路由独享的钩子
    顾名思义,即单个路由独享的导航钩子,它是在路由配置上直接进行定义的:
cont router = new VueRouter({
     
    routes: [
        {
     
            path: '/file',
            component: File,
            beforeEnter: (to, from ,next) => {
     
                // do someting
            }
        }
    ]
});

至于他的参数的使用,和全局前置守卫是一样的

  1. 组建内的导航钩子
    组件内的导航钩子主要有这三种:-
  • beforeRouteEnter
  • beforeRouteUpdate
  • beforeRouteLeave。

他们是直接在路由组件内部直接进行定义的

我们看一下他的具体用法:

const Foo = {
     
  template: `...`,
  beforeRouteEnter (to, from, next) {
     
    // 在渲染该组件的对应路由被 confirm 前调用
    // 不!能!获取组件实例 `this`
    // 因为当守卫执行前,组件实例还没被创建
  },
  beforeRouteUpdate (to, from, next) {
     
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
    // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 可以访问组件实例 `this`
  },
  beforeRouteLeave (to, from, next) {
     
    // 导航离开该组件的对应路由时调用
    // 可以访问组件实例 `this`
  }
}

需要注意是:

beforeRouteEnter 不能获取组件实例 this,因为当守卫执行前,组件实例被没有被创建出来,剩下两个钩子则可以正常获取组件实例 this

但是并不意味着在 beforeRouteEnter 中无法访问组件实例,我们可以通过给 next 传入一个回调来访问组件实例。在导航被确认是,会执行这个回调,这时就可以访问组件实例了,如:

beforeRouteEnter(to, from, next) {
     
    next (vm => {
     
        // 这里通过 vm 来访问组件实例解决了没有 this 的问题
    })
}

注意,仅仅是 beforRouteEnter 支持给 next 传递回调,其他两个并不支持。因为归根结底,支持回调是为了解决 this 问题,而其他两个钩子的 this 可以正确访问到组件实例,所有没有必要使用回调

最后是完整的导航解析流程:

  1. 导航被触发
  2. 在失活的组件里调用离开守卫
  3. 调用全局的 beforeEach 守卫
  4. 在重用的组件里调用 beforeRouteUpdate 守卫
  5. 在路由配置里调用 beforEnter
  6. 解析异步路由组件
  7. 在被激活的组件里调用 beforeRouteEnter
  8. 调用全局的 beforeResolve 守卫
  9. 导航被确认
  10. 调用全局的 afterEach 钩子
  11. 触发 DOM 更新
  12. 在创建好的实例调用 beforeRouteEnter 守卫中传给 next 的回调函数

7. 原理

7.1 怎样理解Vue单向数据流?

基本概念 : 子组件更改 props 中的数据不会触发父组件数据的改变, 但是由于响应式原理,父组件数据的改变会导致子组件 props 中值的改变

目的:防止子组件意外的改变父组件中的状态,从而导致应用的数据流向难以理解.

结果 : 子组件的prop数据自动刷新,但是子组件内部不能改变prop的值

解决方案 : 只能通过自定义事件,父组件接受到事件后,有父组件修改数据,

有两种常见的视图改变props值的场景:

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

7.2 直接给一个数组赋值,Vue能检测到数据变化吗?

由于JavaScript的限制,vue不能检测如下数据变化:

  • 直接通过下标修改数组的值arr[index] = num;
  • 修改数组的长度

所以修改数组的值可以可以通过同种方式实现

//方案一
//使用数组的splice方法修改
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)
//方案二
//通过vue提供的set方法设置
Vue.set(this.arr,1,2)
// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
// vm.$set,Vue.set的一个别名
vm.$set(vm.items, indexOfItem, newValue)

第二个问题的解决方法

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

7.3 v-model的原理?

v-model其实是一个语法糖,它的背后本质上是包含两个操作:

  1. v-bind绑定一个value属性
  2. v-on指令给当前元素绑定input事件

也就是说下面的代码:等同于下面的代码:

//以input表单元素为例
input type="text" v-model="message">
等同于
<input type="text" v-bind:value="message" v-on:input="message = $event.target.value">

上面的说法仅仅是针对与输入框,那么其他的表单元素呢,如单选,多选,下拉框等

v-model 本质上不过是语法糖,v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件:

  1. text 和 textarea 元素使用 value 属性和 input 事件;
  2. checkbox 和 radio 使用 checked 属性和 change 事件;
  3. select 字段将 value 作为 prop 并将 change 作为事件。

7.4 runtime-only 和 compiler+runtime的区别?

如果我们需要在客户端编译模板(例如,想template选项传入一个字符串,或者需要将模板中的非DIN的HTML挂载到一个元素),这是就需要带有编译器的版本,因为需要完整构建版本.

//这种情况需要编译器(compiler)
new Vue({
     
	template : `
{ {hello}}
`
}) //这种情况不需要 new Vue({ render(h) { return h('div',this.hello); } })

具体二者之间的差别我们先来看看vue的运行过程
template->ast(abstract syntax tree)->render->virtual dom->UI

1、1. runtime-compiler:template->ast(abstract syntax tree)->render->virtual dom->UI
runtime-only:性能更高、代码量更少
runtime-only :render->virtual dom->UI

  1. Runtime-Compiler和Runtime-only的选择使用情况?
    如果在之后的开发中,你依然使用template,就需要选择Runtime-Compiler
    如果你之后的开发中,使用的是.vue文件夹开发,那么可以选择Runtime-only

6.5 render函数解析

render函数的基本用法:

function(createElement) {
     
   //用法1
   return createElement('标签',{
     标签的属性},[标签中的内容]);
   return createElement('h2',{
     class:box},['Hello world]);

//用法2
//传入一个组件对象
return createElemen(cpn)
}

6.6 Vue中key的作用?

key让每个item元素有一个唯一标识的身份,可以使用下标值或者唯一的id值,主要是为了vue能够精准的追踪到每一个元素,高效的更新虚拟DOM,使用v-for遍历数据的时候需要加上key关键字.

6.7 Vue的响应式原理?

当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter。Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。

这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在 property 被访问和修改时通知变更。这里需要注意的是不同浏览器在控制台打印数据对象时对 getter/setter 的格式化并不同,所以建议安装 vue-devtools 来获取对检查数据更加友好的用户界面。

每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。

Vue知识总结_第3张图片

6.8 Vue检测数组或对象的变化的注意事项?

1. 数组

Vue不能检测以下数组的变动:
- 当你利用索引值直接设置一个数组项时,例如:vm.items[index] = newValue
- 当你修改数组的长度时,例如:vm.items.length = ewLength

一个例子:

let vm = new Vue({
     
	data : {
     
		items :[1,2,3,4],
	}
})

//利用下标修改数组值
vm.items[0] = 5;   //不是响应式的
//直接修改数组长度
vm.items.length = 6;  //不是响应式的

第一个问题(不能通过下标值修改数组元素)的解决方案:

  1. 利用vue.set()
Vue.set(vm.items, indexOfItem, newValue)
  1. 利用数组的splice方法
vm.items.splice(indexOfItem, 1, newValue)

你也可以使用 vm.$set 实例方法,该方法是全局方法 Vue.set 的一个别名:

vm.$set(vm.items, indexOfItem, newValue)

第二个问题(不能直接改变数组长度)的解决方案
使用splice方法

vm.items.splice(newLength)

2. 对象

Vue 无法检测 property 的添加或移除。由于 Vue 会在初始化实例时对 property 执行 getter/setter 转化,所以 property 必须在 data 对象上存在才能让 Vue 将它转换为响应式的。例如:

var vm = new Vue({
     
  data:{
     
    a:1
  }
})

// `vm.a` 是响应式的

vm.b = 2
// `vm.b` 是非响应式的

对于已经创建的实例,Vue 不允许动态添加根级别的响应式 property。但是,可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式 property。例如,对于:

Vue.set(vm.someObject, 'b', 2)

还可以使用 vm.$set 实例方法,这也是全局 Vue.set 方法的别名:

this.$set(this.someObject,'b',2)

有时你可能需要为已有对象赋值多个新 property,比如使用 Object.assign() 或 _.extend()。但是,这样添加到对象上的新 property 不会触发更新。在这种情况下,你应该用原对象与要混合进去的对象的 property 一起创建一个新的对象。

// 代替 `Object.assign(this.someObject, { a: 1, b: 2 })`
this.someObject = Object.assign({
     }, this.someObject, {
      a: 1, b: 2 })

你可能感兴趣的:(vue)