Vue2相关知识点

199 阅读2分钟

Vue生命周期(8个)

每个生命周期都由钩子函数调用(callHook)
created()
mounted()
updated()
destroy()
keep-alive(LRU算法)
activated
deactivated

include/exclude

父组件监听子组件mounted

child

mounted () { this.$emit(“mounted”) }

parent

<child @hook:mounted=”dosomething”><child>

js

vm.$on('hooks:created', cb) ;

父子组件生命周期顺序

  • 渲染
    父beforeCreate created beforeMount
    子beforeCreate created beforeMount mounted
    父mounted
  • 子更新
    父beforeUpdate
    子beforeUpdate updated
    父updated
  • 销毁
    父beforeDestory
    子beforeDestory destroyed
    父destroyed

Vue组件通信(单向数据流)

props
on/on/emit
ref.child.data/.method()vuexref.child.data / .method() vuex parent $children
eventBus跨组件
provide inject 插件 父供子消费

Vue公共逻辑抽离(Vue.mixin)

mergeOptions(data,生命周期等)

  • 全局
    Vue.mixin(mixin)
    
  • 局部
    import mixin from ‘...’
    export default {
        mixins: [mixin],
        data () { return {} }
    }
    

多个组件中的引用相同mixin,mixin是独立的,不互相影响
调用时,先生成mixin,same options时组件会覆盖mixin的

异步组件 (Vue2.0一定是函数)

components: {
    AddComp: (resolve) => import('../components/Confirm.vue')
}

动态组件

<component :is="settingTabs[currentTab].component"></component>
currentTab: 0,
settingTabs: [{ title: '基本设置', component: 'basic-setting' }]

插槽

  • slot:作用域为父组件 my-component
    <modal>
        <slot name="content"></slot>
    </modal>
    
    父组件调用my-component
    <ConfirmEle>
        <template #content 或者 slot=“content”></template>
    </ConfirmEle>
    
  • slot-scope 作用域子组件

computed watch method区别

  • 方法m:
    c、w原理都是watcher实现
    计算c:缓存,依赖变化才更新视图
  • 监视w:
    1
    2

Vuex

  • 基础属性
import Vuex from 'vuex';
Vue.use(Vuex);
new Vuex.Store({
    state: {
        name: ‘’
    },
    mutations: {
        setName (state, name) {
            state.name = name
        }
    },
    actions: {
        login({ commit }, res) {
            commit('setName', res.data.name);
            localStorage.setItem('userName', res.data.name)
            // axios.defaults.headers.common.Authorization = token;
        },
        logout({ commit }) {
            return new Promise((resolve) => {
                localStorage.clear();
                sessionStorage.clear();
                // axios.defaults.headers.common.Authorization = '';
                resolve();
            });
        },
    },
    modules: {
        user,
        setting
    }
})
  • vuex引用
computed: {
    ...mapState('module1', ['state1', 'state2'])
},
methods: {
    ...mapMutations('module2', ['mutations1', 'mutations2']),
}
this.$store.dispatch('user/login', res).then(() => {
    this.$router.push({ name: 'workSpace' });
});
this.$stroe.commit()
computed: {
    audioStatus: {
        get () {
            return this.$store.state.setting.audioStatus;
        },
        set (val) {
            this.$store.state.setting.audioStatus = val;
        }
    }
}

自定义指令

钩子函数bind inserted update 全局

Vue.directive('image-preview', function (el, binding, vnode) {})

局部

export defaults {
    directives: {
        focus: {
            inserted: function (el) { el.focus() }
        }
    }
}
Vue.directive('has', {
    // 当被绑定的元素插入到 DOM 中时
    inserted: function(el, binding) {
        var role = store.state.user.role
        if (!role) return false
        let auth = role.some(e => {
            return e.id === 1
        })
        !auth ? el.style.display = 'none' : el.style.display = 'inline-block'
    }
})

vue双向绑定原理(响应式)

数据劫持+发布订阅模式
递归遍历整个data,Object.defineProperty()劫持各个属性的setter和getter方法; 数据get时添加订阅者到订阅中心,set时通知订阅中心,依赖收集Watcher,稍后Dep.notify通知watcher,异步渲染更新)

  1. initData()
  2. Observer(监听者,劫持并监听)
  3. Dep 依赖
  4. Watcher订阅者
  5. Compile编译解析
vue-template-complier // 将模板解析成vue的浏览器语法
VueTemplateComplier.compile(`<div v-if=”true”></div>`)

‘with(this){
	return
}’

data采用工厂函数

new Vue({ data:{} }) new Vue()只一次,创建一个根实例 data: {}
data () { return {} } 工厂函数
组件数据间独立,防止组件VueComponent多次new实例化时data复用,污染数据
data() => ( return obj: {name: ‘123’ }) 引用时 vc.$options.data()

var Component1 = function() {
    this.data = this.data()
}
Component1.prototype.data = function() {
    return {
        a: 1,
        b: 2
    }
}
var Component2 = function() {
    this.data = this.data()
}
Component2.prototype.data = () => {
    return {
        a: 1,
        b: 2
    }
}
var Component3 = function() {}
Component3.prototype.data = {
    a: 1,
    b: 2
}

var c1 = new Component1()
var c2 = new Component2()
var c3 = new Component3()

// 改变组件
component1.data.b = 3
component2.data.b // 2

Vue采用异步渲染

页面中N条数据,等N条数据全update后,再异步更新视图
nextTick(清空watcher队列)

nextTick()

保证当前视图渲染完成(更新图标echarts)
nextTick(系统的异步更新 、直接调用$nextTick)
把这些更新全放到 callback=[] 数组中
之后异步微任务 timerFunc=(Promise.resolve().then(依次执行callback))
(根据浏览器支不支持,依次使用promise.then、setImmediate、setTimeout)

Vue模板编译原理 (parse解析、optimize优化、generate生成)

将template模板转为 ast(抽象语法)树(用Object描述JS语法),生成render函数
render( _c() ),转成虚拟dom
虚拟dom(用Object描述dom)

  • Vue实例渲染权重
    let vue = new Vue({
        el: '#app',
        data() {
            return {
                a: 1,
                b: [1]
            }
        },
        render(h) {
            return h('div', { id: 'hhh' }, 'hello')
        },
        template: `<div id='hhh' style="aa:1;bb:2"><a>{{xxx}}{{ccc}}</a></div>`
    }).$mount('#app')
    console.log(vue)
    
    // 渲染根节点
    // 有el直接取, 没有调用$mount()
    
    // 渲染模板
    // 有render优先执行
    // 有template: 解析, 调用render渲染
    // 无template: 解析el根节点的outerHTML, 调用render渲染
    
  • 组件渲染
    用Vue.extend() 构建子组件构造函数
    调用子组件时实例化,$mount() 挂载组件到 vm.$el 上,添加子组件的watcher
    Vue.use(MyPlugin)
    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) {}
    }
    
    var MyCompontent = Vue.extend({template: ‘<div></div>’})
    
    Vue.component(‘my-component’, MyCompontent)
    
    new MyCompontent().$mount(‘#app’) / new MyCompontent({el:‘#app’})
    
  • 模板下只能有一个根节点(diff算法只允许一个·根节点)
    patchVnode()
    diff 先比同级,再比子节点
    判断有没有子节点
    比较都有子节点
    递归比较同级子节点

git 前端提交规范

commitizen(vue+commitlint+husky)
npm install --save-dev
"@commitlint/cli": "^8.2.0"
"@commitlint/config-conventional": "^8.2.0"
npm install husky --save-dev
新建commitlint.config.js

后端文件流返回时有哪些字段

header: {},
data: {},
config: {}