chenfei-hnu / Blog

个人整理的跟前端相关的文档 ( This is some front-end development related documentation )
9 stars 2 forks source link

Vue 学习总结 #29

Open chenfei-hnu opened 4 years ago

chenfei-hnu commented 4 years ago

1. 入口

main.js中通过将vue基础组件绑定到id = 'app'的DOM元素上, 并添加路由, 状态管理等对象

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount("#app");

2. vue组件的生命周期

beforeCreate

--合并mixins中的各项属性, 初始化data, props, computed, 绑定watch函数

created

--声明$el属性, 绑定computed监听函数_computedWatchers

beforeMount

--调用Vue._render根据template, components, directives及组件其他属性值初始化渲染DOM, 递归执行子组件的声明周期, 绑定$el属性

mounted

beforeUpdate

根据computed, watch等监听, 判断属性变化后, 调用Vue._render更新元素显示

updated

根据交互修改数据, 监听数据变化后继续触发beforeUpdate

beforeDestroy

Vue组件对应的属性解绑定, 所有的事件监听器会被移除, 所有的子组件也会被销毁

destroyed

3. vue对象的各项常用属性

data、 computed、 watch、 methods

data定义组件中不常改变的属性

computed返回部分根据其他属性计算出来表达式属性, 在HTML DOM加载后马上执行, 计算属性的结果会被缓存, 除非依赖的响应式属性变化才会重新计算 a.使用箭头函数时将组件实例作为函数的第一个参数来访问 b.computed中可以通过在属性对象中定义get和set来同时管理属性的定义和变动时的监听回调 c.可以通过Vuex的mapState来替代this.$store.state的取值方式

methods通常用来定义组件中的静态方法, 必须要有一定的触发条件才能执行, 如点击事件, 通过vue实例访问这些方法, 或者在指令表达式中使用 a.不应该使用箭头函数来定义 method 函数 b.可以通过Vuex的mapActions及mapMutations 来快捷的获取状态管理中的actions、 mutation 方法

watch: 进行由于某些数据的变化来执行的回调处理, 比如状态管理里面的全局变量发生修改, 页面需要对应进行某些处理

4. 父子组件通信

属性传递 prop vue父组件通过prop将属性及方法传递给子组件, 且只能在父组件中改变数据传递到子组件, 不应该在一个子组件内部改变 prop 需要改动时, 将其定义为由prop通过compute计算出来的值, 再进行修改

事件监听 父组件监听子组件触发的事件, 需要在子组件用使用 $emit 触发, 在父组件中使用 v-on或者@ 自定义事件监听

5.状态管理

vue中通过store来保存全局的公共对象,并通过vuex来简化store的用法 获取 1)直接通过store.state.XXX获取当前值 2)根据store值变化动态直接获取属性,computed定义方法返回store.state.XXX相关的表达式 3)根据store值变化动态获取相关属性,computed定义属性对象,并在对象中定义get方法

computed: {
    property: {
        get () {
            return this.$store.state.property;
        }
    }
}

4)在computed中通过Vuex.mapState批量定义,与store中属性对应

computed: {
    ...Vuex.mapState(
      {
        property1: state => state.property1,
        property2: state => state.property2
      }
    )
}

更新 更改 Vuex 的 store 中的状态的唯一方法是在components的代码中commit store中mutation对应的方法

store

mutations: {
    UPDATE_PROPERTY(state, { property }) {
        state.property = property
    }
}
components
computed: {
    property: {
      set (value) {
          this.$store.commit('UPDATE_PROPERTY', { property: value });
      }
    }
}

如果需要在更新时进行一个前置后置逻辑,在store actions中定义方法调用commit,在components代码中执行store.dispatch调用actions对应的方法

store
actions: {
    doAction({ state, commit }) {
        //前置逻辑
        commit('xxx',{});
        //后置逻辑
    }
}

components
store.dispatch('doAction',{})

下拉列表绑定了store里面的变量,必须在computed中定义set来调用mutation中的方法更新值,不然会报错

6.路由

定义路由表实例

const router = new VueRouter({
  routes: [
    { path: "/home", name: 'home', component: HomeContainer }
  ]
});

路由间传值有声明式和函数式两种方式,跳转到对应路由路径的组件后可以在$router.params中找到所需传递的参数

声明式 {/ /}

函数式 router.push(name: 'home', params: { data: data }) router.push({ path: '/home', query: { index: index }}) router.push({ path: /home/${index} })

this.$router就是全局的路由的实例,可以调用路由的back、forward、go、onready、push…等方法 this. $route存储了当前页面的一些路由的信息,包含了当前URL解析得到的信息,如name、path、params、query等属性

可以使用前置守卫和后置守卫来处理一些跳转相关的通用逻辑,比如权限检测,埋点等 router.beforeEach 全局前置守卫 router.afterEach 全局后置守卫

(to: Route): 即将要进入的目标 路由对象 (from: Route): 当前导航正要离开的路由 next(): 进行管道中的下一个钩子 next(false): 中断当前的导航 next('/') 或者 next({ path: '/' }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航

7.常用指令

a.v-bind可以使用:property的形式简写,绑定的属性如果是数组,利用索引直接修改某个数组项值或者通过 arr.length= 赋值改变数值长度,不会触发视图更新 可以使用Vue.set(vm.items, indexOfItem, newValue),或者指向一个新数组替换进行数组视图更新

b.v-on可以使用@event的形式简写,事件监听器在 DOM 模板中会被自动转换为全小写,并支持使用对象的方式绑定多个事件处理函数 v-on="{mouseenter:onEnter,mouseout:onOut}"

c.v-if 隐藏时会从文档中删除该元素,组件被destroyed,切换一次就需要重新渲染一次组件

d.v-show 切换状态元素都存在于文档中,仅修改样式来显示隐藏

e.keep-alive 动态组件, 里面的组件通过v-if隐藏时, 元素会从页面中删除, 但组件不会被destroyed,仍被保留在内存里可以访问另外两个生命周期钩子:activated 和 deactivated

8.快捷用法

a.使用Vue.prototype定义全局属性 Vue.prototype.$ajax = api; 使用时在组件中通过this.$ajax访问

9.性能相关问题

a.内存泄漏往往会发生在使用第三方库进行 DOM 操作时,DOM元素不会自动被vue生命周期函数给自动销毁 Vue 组件销毁时,会自动清理它与其它组件实例的绑定,解绑它的全部指令及事件监听器, 但是仅限于Vue组件的内置事件。如果在 js 内使用 addEventListene 等方式绑定原生的DOM事件, 我们需要在组件销毁时手动移除这些事件的监听,以免造成内存泄露

b.频繁执行页面交互操作时,触发过多的 diff 计算,会导致页面卡顿,可以通过删除掉不在可视区域的节点

c.长列表性能优化 Vue 通过 Object.defineProperty 对数据进行劫持,来实现更新视图以响应数据的变化 当我们的组件是静态的数据展示,不会有任何改变,无需Vue 来劫持我们的数据 在大量数据展示的情况下,能够很明显的减少组件初始化的时间,可以通过 Object.freeze 方法来冻结一个对象

d.优化无限列表性能 采用 窗口化 的技术来优化性能,只需要渲染少部分区域的内容,减少重新渲染组件和创建 dom 节点的时间 可以参考以下开源项目 vue-virtual-scroll-list 和 vue-virtual-scroller 来优化这种无限列表的场景的

10.打包调试方面

a.第三方插件的按需引入 借助 babel-plugin-component ,可以只引入需要的组件,以达到减小项目体积的目的 然后对应修改 .babelrc配置文件

b.浏览器调试 VS code 安装 Debugger for Chrome插件 webpack.config.js中配置 devtool: 'source-map',