1、【计算属性(computed)、计算方法(methods)】

1)计算方法,每次都会计算,而且必须得手动调用;而计算属性,只要依赖项发生了变化,就会重新计算,是自动调用;
2)计算方法,不能进行缓存,每次都执行;计算属性,可以缓存计算结果,在复杂计算时,尤其可以发挥优势。

2、计算属性 setter

computed: {
  fullName: {
    get: function () {
      // getter
    },
    set: function (newValue) {
      // setter
    }
  }
}
vm.fullName = 'John Green';    // 会自动调用 setter 方法
alert(vm.fullName);            // 会自动调用 getter 方法

3、侦听器(watch)

当需要在数据变化时执行异步,或执行【开销较大】的操作时,这个方式是最有用的。
他可以设置中间状态。除了 watch 选项之外,您还可以使用命令式的 vm.$watch API。

4、【侦听属性(watch)、计算属性(computed)】

1)watch 擅长处理:一个数据影响多个数据;computed 擅长处理:一个数据受多个数据影响。
2)watch 还擅长执行异步操作,或比较耗时的操作。

5、管理可复用的元素(v-if 切换的元素,如果只有属性差异,则可以进行复用)

如果想不复用,这样做,增加一个 key 即可。

6、【v-if  vs  v-show】

一般来说,v-if(元素直接移除)有更高的切换开销,而 v-show(display: none)有更高的初始渲染开销。
因此,如果需要非常频繁地切换,则使用 v-show 较好;
如果在运行时条件很少改变,则使用 v-if 较好。
当 v-if 与 v-for 一起使用时,v-for 具有比 v-if 更高的优先级!

<li v-for="todo in todos" v-if="!todo.isComplete">
    {{ todo }}
</li>
上面的代码只传递了未完成的 todos(过滤)。

7、数组更新检测和对象更新检测

Vue.set【*】
Vue.set(vm.items, indexOfItem, newValue)

Array.prototype.splice【*】
vm.items.splice(indexOfItem, 1, newValue)

使用 Vue.set(object, key, value) 方法向“嵌套对象”添加响应式属性,例如:

Vue.set(vm.userProfile, 'age', 27)

有时你可能需要为已有对象赋予多个新属性:

vm.userProfile = Object.assign({}, vm.userProfile, {
    age: 27,
    favoriteColor: 'Vue Green'
})

8、访问原始dom事件

有时也需要在内联语句处理器中访问原始的 DOM 事件。可以用特殊变量 $event 把它传入方法:

9、表单数据绑定

v-model 会忽略所有表单元素的 value、checked、selected 特性的初始值,而总是将 Vue 实例的数据作为数据来源。
你应该通过 JavaScript 在组件的 data 选项中声明初始值。

复选框:
<input
type="checkbox"
v-model="toggle"
true-value="yes"
false-value="no">

// 当选中时
vm.toggle === 'yes'
// 当没有选中时
vm.toggle === 'no'

10、组件基础

组件是可复用的 vue 实例,所以它们与 new Vue 接收相同的选项,例如:data、computed、watch、methods、以及生命周期钩子等。仅有的例外是 el 这样的对象根实例特有。

另外,比较特殊的是,组件的 data 必须是一个函数,不能直接是一个对象。
组件的组织:为了能在模板中使用,这些组件必须先注册,以便 Vue 能够识别。
这里有两种组件的注册类型:全局注册和局部注册。

11、组件注册

组件名区分大小写,但强烈建议都用"小写",单词间用减号相连。例如:my-work;

记住全局注册的行为必须在根 Vue 实例 (通过 new Vue) 创建之前发生!

---全局注册---:
Vue.component('component-a', { /* ... */ })
Vue.component('component-b', { /* ... */ })
Vue.component('component-c', { /* ... */ })new Vue({ el: '#app' })
<div id="app">
  <component-a></component-a>
  <component-b></component-b>
  <component-c></component-c>
</div>---局部注册---:
var ComponentA = { /* ... */ }
var ComponentB = { /* ... */ }
var ComponentC = { /* ... */ }new Vue({
  el: '#app'
  components: {
    'component-a': ComponentA,
    'component-b': ComponentB
  }


})

如果你不希望组件的根元素继承特性,你可以设置在组件的选项中设置 inheritAttrs: false。

12、Vue 父子组件之间数据传递的四种方式

1)通过 props 方式,父向子传递数据;
2)通过状态管理 vuex,父子组件和非父子组件传递数据;
3)非父子组件的通信传递 vue Event Bus,使用 Vue 实例,实现事件的监听和发布,实现组件之间的传递;
4)inheritAttrs + $attrs + $listeners 实现(这个要等到工程化应用时才可以尝试)。

13、自定义事件

将原生事件绑定到组件:

v-on 的 .native 修饰符:<base-input v-on:focus.native="onFocus"></base-input>

14、插槽(见专门的章节)

15、动态组件

通过使用保留的<component>元素,动态地绑定到它的 is 特性,我们可以让多个组件使用同一个挂载点,并动态切换。
vue 中的 keep-alive(要求组件必须有自己的名字) 可以配合 router-view 缓存整个路由页面(略)。

16、异步组件

异步组件:在大型应用中,我们可能需要将应用分割成小一些的代码块,并且只在需要的时候才从服务器加载一个模块。为了简化,vue 允许你以一个工厂函数的方式定义你的组件,这个工厂函数会异步解析你的组件定义。vue 只有在这个组件需要被渲染的时候才会被触发,且会把结果缓存起来供未来重渲染。

通过箭头函数加import 可以实现异步加载组件功能,可以实现性能优化:

import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)

export default new Router({
  mode: 'history',  
  routes: [
    {
      path: '/',
      name: 'Home',
      component: () => import('@/pages/home/Home')
    },
    {
      path: '/city',
      name: 'City',
      component: () => import('@/pages/city/City')
    },
    {
      path: '/detail/:id',
      name: 'Detail',
      component: () => import('@/pages/detail/Detail')
    }
  ],
  scrollBehavior (to, from, savedPosition) {
    return { x: 0,y:0}
  }
})
说明:render函数为官网的异步组件构建方式;

17、vue 路由异步组件案例

原理:利用webpack对代码进行分割,是异步调用组件的前提。代码后续参考官方;

18、父组件提供 provide,子组件提供 inject --- 依赖注入

Vue.component('google-map', {
  provide: function () {
    return {
      getMap: this.getMap
    }
  }
}
Vue.component('google-map-marker', {
  inject: ['getMap'],
}

通过 $forceUpdate( ) 来做这件事 --- 例如:本来应该更新的,结果没有更新,那就强制更新一下。

19、过渡 & 动画

vue 可以在如下几种情形中应用过渡效果:

1)在css过渡和动画中自动应用 class;
2)可以配合使用第三方 css 库,如 Animate.css;
3)在过渡钩子函数中使用 javascript 直接操作 DOM;
4)可以配合使用第三方 javascript 动画库,如 Velocity.js;

单元素/组件的过渡 --- transition

如下几种情形中,可以给任何元素和组件添加进入/离开过渡:

1)条件渲染(v-if);
2)条件展示(v-show);
3)动态组件;
4)组件根节点;

当只用 JavaScript 过渡的时候,在 enter 和 leave 中必须使用 done 进行回调。否则,它们将被同步调用,过渡会立即完成。
推荐对于仅使用 JavaScript 过渡的元素添加 v-bind:css="false",Vue 会跳过 CSS 的检测。这也可以避免过渡过程中 CSS 的影响。

20、混入---mixins

是一种分发 vue 组件中的可复用功能的非常灵活的方式。混入对象可以包含任意组件选项。
当组件使用混入对象时,所有混入对象的选项都将被混入该组件本身的选项。

全局混入:也可以全局注册混入对象。注意使用! 一旦使用全局混入对象,将会影响到所有之后创建的 Vue 实例。使用恰当时,可以为自定义对象注入处理逻辑。

21、自定义指令

涉及的钩子函数:
bind、inserted、update、componentUpdated(父和子全部更新后调用)、unbind;

22、插件

插件通常会为 Vue 添加全局功能。Vue.js 的插件应当有一个公开方法 install 。这个方法的第一个参数是 Vue 构造器,第二个参数是一个可选的选项对象:

插件通常会为 Vue 添加全局功能。
Vue.js 的插件应当有一个公开方法 install 。这个方法的第一个参数是 Vue 构造器,第二个参数是一个可选的选项对象:

MyPlugin.install = function (Vue, options) {
  // 1. 添加全局方法或属性
  Vue.myGlobalMethod = function () {
    // 逻辑...
  }

  // 2. 添加全局资源
  Vue.directive('my-directive', {
    bind (el, binding, vnode, oldVnode) {
      // 逻辑...
    }
    ...
  })

  // 3. 注入组件
  Vue.mixin({
    created: function () {
      // 逻辑...
    }
    ...
  })

  // 4. 添加实例方法
  Vue.prototype.$myMethod = function (methodOptions) {
    // 逻辑...
  }
}

---使用插件---
通过全局方法 Vue.use() 使用插件:

// 调用 `MyPlugin.install(Vue)`
Vue.use(MyPlugin)

也可以传入一个选项对象:

Vue.use(MyPlugin, { someOption: true })

// 用 Browserify 或 webpack 提供的 CommonJS 模块环境时
var Vue = require('vue')
var VueRouter = require('vue-router')

// 不要忘了调用此方法
Vue.use(VueRouter)

23、过滤器

Vue.js 允许你自定义过滤器,可被用于一些常见的文本可视化。过滤器可以用在两个地方:
双花括号插值和 v-bind 表达式。过滤器应该添加在 javascript 尾部,由管道符号指示。

过滤器可以串联:

{{ message | filterA | filterB }}
在这个例子中,filterA 被定义为接收单个参数的过滤器函数,表达式 message 的值将作为参数传入到函数中。然后继续调用同样被定义为接收单个参数的过滤器函数 filterB,将 filterA 的结果传递到 filterB 中。

24、单元测试

常规可以使用 Karma + Jasmine 进行单元测试,Karma 的一个强大特性就是:它可以监控文件的变化,然后自动执行,通过 console.log 显示测试结果。
istanbul是一个单元测试代码覆盖率检查工具,可以很直观地告诉我们,单元测试对代码的控制程度。

<script>
  export default {
    data () {
      return {
        message: 'hello!'
      }
    },
    created () {
      this.message = 'bye!'
    }
  }
</script>

// 导入 Vue.js 和组件,进行测试
import Vue from 'vue'
import MyComponent from 'path/to/MyComponent.vue'

// 这里是一些 Jasmine 2.0 的测试,你也可以使用你喜欢的任何断言库或测试工具(describe + it)。

describe('MyComponent', () => {
  // 检查原始组件选项
  it('has a created hook', () => {
    expect(typeof MyComponent.created).toBe('function')
  })

  // 评估原始组件选项中的函数的结果
  it('sets the correct default data', () => {
    expect(typeof MyComponent.data).toBe('function')
    const defaultData = MyComponent.data()
    expect(defaultData.message).toBe('hello!')
  })

  // 检查 mount 中的组件实例
  it('correctly sets the message when created', () => {
    const vm = new Vue(MyComponent).$mount()
    expect(vm.message).toBe('bye!')
  })

  // 创建一个实例并检查渲染输出
  it('renders the correct message', () => {
    const Constructor = Vue.extend(MyComponent)
    const vm = new Constructor().$mount()
    expect(vm.$el.textContent).toBe('bye!')
  })
})

25、TypeScript 支持

要让 TypeScript 正确推断 Vue 组件选项中的类型,您需要使用 Vue.component 或 Vue.extend 定义组件:

import Vue from 'vue'
const Component = Vue.extend({
    // 类型推断已启用
})

const Component = {
    // 这里不会有类型推断,
    // 因为TypeScript不能确认这是Vue组件的选项
}

---基于类的 Vue 组件---

如果您在声明组件时更喜欢基于类的 API,则可以使用官方维护的 vue-class-component 装饰器:

import Vue from 'vue'
import Component from 'vue-class-component'

// @Component 修饰符注明了此类为一个 Vue 组件
@Component({
  // 所有的组件选项都可以放在这里
  template: '<button @click="onClick">Click!</button>'
})
export default class MyComponent extends Vue {
  // 初始数据可以直接声明为实例的属性
  message: string = 'Hello!'

  // 组件方法也可以直接声明为实例的方法
  onClick (): void {
    window.alert(this.message)
  }
}

26、深入响应式原理

当你把一个普通的 JavaScript 对象传给 Vue 实例的 data 选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是为什么 Vue 不支持 IE8 以及更低版本浏览器的原因。这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。这里需要注意的问题是浏览器控制台在打印数据对象时getter/setter 的格式化并不同,所以你可能需要安装 vue-devtools 来获取更加友好的检查接口。每个组件实例都有相应的 watcher 实例对象,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的 setter 被调用时,会通知 watcher 重新计算,从而致使它关联的组件得以更新。

27、异步更新队列

在组件内使用 vm.$nextTick() 实例方法特别方便,因为它不需要全局 Vue ,并且回调函数中的 this 将自动绑定到当前的 Vue 实例上。

28、babel 和 polyfill

babel 为了支持新的语法特性,polyfill 为了支持新的API。一般 import babel-polyfill。

个人统计【2】:2019-05-26、2019-05-27