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