vue项目中所用的模块分析

在开发项目的过程中不太明确的问题,过了一下官方文档,根据文档整理出比较常用的部分:

数据

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 不能检测数组对象的变化

  1. 对于已经创建的实例,Vue 不允许动态添加根级别的响应式 property。但是,可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式 property。
  2. 有时你可能需要为已有对象赋值多个新 property。比如使用 Object.assign();this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 }) 
  3. 当你利用索引直接设置一个数组项时,Vue.set(vm.items, indexOfItem, newValue)
  4. 当你修改数组的长度时,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
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值