vue项目中所用的模块分析
1. Data:Vue 将会递归将 data 的 property 转换为 getter/setter,从而让 data 的 property 能够响应数据变化。当一个组件被定义,data必须声明为返回一个初始数据对象的函数,因为组件可能被用来创建多个实例。如果data仍然是一个纯粹的对象,则所有的实例将共享引用同一个数据对象!通过提供data函数,每次创建一个新实例后,我们能够调用data函数,
在开发项目的过程中不太明确的问题,过了一下官方文档,根据文档整理出比较常用的部分:
数据
1. Data:Vue 将会递归将 data 的 property 转换为 getter/setter,从而让 data 的 property 能够响应数据变化。当一个组件被定义,data
必须声明为返回一个初始数据对象的函数,因为组件可能被用来创建多个实例。如果 data
仍然是一个纯粹的对象,则所有的实例将共享引用同一个数据对象!通过提供 data
函数,每次创建一个新实例后,我们能够调用 data
函数,从而返回初始数据的一个全新副本数据对象。
2.Computed:计算属性将被混入到 Vue 实例中。所有 getter 和 setter 的 this 上下文自动地绑定为 Vue 实例。注意如果你为一个计算属性使用了箭头函数,则 this不会指向这个组件的实例,不过你仍然可以将其实例作为函数的第一个参数来访问。
3.Methods:不应该使用箭头函数来定义 method 函数 (例如 plus: () => this.a++
)。理由是箭头函数绑定了父级作用域的上下文,所以 this
将不会按照期望指向 Vue 实例,this.a
将是 undefined。
4.Watch:不应该使用箭头函数来定义 watcher 函数 (例如 searchQuery: newValue => this.updateAutocomplete(newValue)
)。理由是箭头函数绑定了父级作用域的上下文,所以 this
将不会按照期望指向 Vue 实例,this.updateAutocomplete
将是 undefined。
生命周期函数
1. beforeCreate:在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。
2. created:在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),property 和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el
property 目前尚不可用。
3. beforeMount:在挂载开始之前被调用:相关的 render
函数首次被调用。
4. mounted:实例被挂载后调用,这时 el
被新创建的 vm.$el
替换了。如果根实例挂载到了一个文档内的元素上,当 mounted
被调用时 vm.$el
也在文档内。注意 mounted
不会保证所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以在 mounted
内部使用 vm.$nextTick。
5. beforeUpdate:数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。该钩子在服务器端渲染期间不被调用,因为只有初次渲染会在服务端进行。
6. updated:如果要相应状态改变,通常最好使用计算属性或 watcher取而代之。注意 updated
不会保证所有的子组件也都一起被重绘。如果你希望等到整个视图都重绘完毕,可以在 updated
里使用vm.$nextTick。该钩子在服务器端渲染期间不被调用。
7. activated:被 keep-alive 缓存的组件激活时调用。该钩子在服务器端渲染期间不被调用。
8. deactivated:被 keep-alive 缓存的组件停用时调用。该钩子在服务器端渲染期间不被调用。
9. beforeDestory:实例销毁之前调用。在这一步,实例仍然完全可用。该钩子在服务器端渲染期间不被调用。
10. deatoryed:实例销毁后调用。该钩子被调用后,对应 Vue 实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁。该钩子在服务器端渲染期间不被调用
11. errorCaptured:当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回 false
以阻止该错误继续向上传播。
组合
1. mixins:选项接收一个混入对象的数组。这些混入对象可以像正常的实例对象一样包含实例选项,这些选项将会被合并到最终的选项中,使用的是和 Vue.extend()
一样的选项合并逻辑。也就是说,如果你的混入包含一个 created 钩子,而创建组件本身也有一个,那么两个函数都会被调用。Mixin 钩子按照传入顺序依次调用,并在调用组件自身的钩子之前被调用。
2. 动态组件:<component v-bind:is="currentTabComponent"></component>
3. 通用组件的全局注册:避免再每一个vue页面中引入公用(自己封装的)的组件
import Vue from 'vue'
import upperFirst from 'lodash/upperFirst'
import camelCase from 'lodash/camelCase'
const requireComponent = require.context(
// 其组件目录的相对路径
'./components',
// 是否查询其子目录
false,
// 匹配基础组件文件名的正则表达式
/Base[A-Z]\w+\.(vue|js)$/
)
requireComponent.keys().forEach(fileName => {
// 获取组件配置
const componentConfig = requireComponent(fileName)
// 获取组件的 PascalCase 命名
const componentName = upperFirst(
camelCase(
// 获取和目录深度无关的文件名
fileName
.split('/')
.pop()
.replace(/\.\w+$/, '')
)
)
// 全局注册组件
Vue.component(
componentName,
// 如果这个组件选项是通过 `export default` 导出的,
// 那么就会优先使用 `.default`,
// 否则回退到使用模块的根。
componentConfig.default || componentConfig
)
})
4. 单项数据流:父组件通过props传给子组件,子组件中不可以更改传入的值,否则控制台会报错。
5. 自定义指令:根据本地存储里面的角色,判断按钮是否可点
const buttonDirective = Vue => {
Vue.directive('button', {
bind: function (el, binding, vnode) {
let roleObject = JSON.parse(localStorage.getItem('roleObject'))// 权限的json对象
let args = _.split(binding.arg, '-')
_.forEach(roleObject, (item) => {
if (args[0] === 'inline') {
if (roleObject[args[1]]) {
/**
* 获取el节点的属性,是否有disabled
* 1. 有,设置为true
* 2. 没有,设置为false
*/
if (_.has(el.attributes, 'disabled')) {
el.disabled = true
} else {
el.disabled = false
}
} else {
el.disabled = true
}
} else {
if (roleObject[args[0]]) {
el.style.display = 'inline-block'
} else {
el.style.display = 'none'
}
}
})
}
})
}
// <Button v-button:isAdd >新增</Button>
// render函数渲染时
/*render: (h, params) => {
return h('div', [
h('Button', {
directives: [{
name: 'button',
arg: 'inline-isEdit'}],
props: {size: 'small'},
on: {
click: () => {
this.toLoad(params)
}
}
}, '修改')*/
export default buttonDirective
7. 响应式原理:Vue 将遍历 data 中所有的 property,并使用 Object.defineProperty
把这些 property 全部转为 getter/setter。这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在 property 被访问和修改时通知变更。每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。
8. 响应式原理中vue不能检测的类型及解决办法:Vue 不能检测数组和对象的变化
- 对于已经创建的实例,Vue 不允许动态添加根级别的响应式 property。但是,可以使用
Vue.set(object, propertyName, value)
方法向嵌套对象添加响应式 property。 - 有时你可能需要为已有对象赋值多个新 property。比如使用
Object.assign();
this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 }) - 当你利用索引直接设置一个数组项时,Vue.set(vm.items, indexOfItem, newValue)
- 当你修改数组的长度时,vm.items.splice(newLength)
9. 异步更新:为了在数据变化之后等待 Vue 完成更新 DOM,可以在数据变化之后立即使用 Vue.nextTick(callback)
// $nextTick() 返回一个 Promise 对象
export default {
// ...
methods: {
updateMessage: async function () {
this.message = '已更新'
console.log(this.$el.textContent) // => '未更新'
await this.$nextTick()
console.log(this.$el.textContent) // => '已更新'
}
}
}
更多推荐
所有评论(0)