Vue2+Vue3

92 阅读4分钟

Vue的核心技术

MVVM思想

  • M->model 模型

    • 通过VM绑定视图
  • V->view 视图

    • 通过VM监听模型
  • VM-> vue实例对象(模型和视图通过它进行数据的绑定和渲染)

Vue可以访问哪些属性,Vue属性命名规范

  • vue本身属性,data数据

  • 命名规范

    • 不能以$或者_开头

      • $->vue的公开访问属性
      • _->vue的(私有)属性一般不访问

Vue的数据绑定机制

  1. 通过代理模式实现,Object.defineProperty()方法给Vue实例对象增加属性;
  2. 访问时,底层通过get方法访问被代理对象的属性
  3. 赋值时,底层通过set方法给被代理对象的属性赋值

简单实现Vue的数据绑定机制

  •   const vm = new Vue({
      data:{
          name: '张三',
          age: 17
      }
      })
    

    实例化

  • 编写Vue类(ES6新特性)

  •   class Vue{
          constructor(options){
              // 通过Object.keys获取某个对象{}的全部属性名
              const propertyNames= Object.keys(options.data);
              propertyNames.foreach(propertyName=>{
                  // 给vue 添加属性
      // 遍历options中的属性
              // 1. this->表示Vue
              // 2. propertyName ->需要代理的属性
              // 3. {}-> get set 当通过vue获取/修改值时,触发的函数
              // 注意->读值时,需要用data[key] 类[属性名]
                  Object.defineProperty(this,propertyName,{
                      get(){
                          return options.data[propertyName];
                      },
                      set(val){
                          options.data[propertyName] = val;
                      }
                      
                  })
              })
              
          }
      }
    

-# Vuex插件的使用

  • 网址

    https://vuex.vuejs.org/zh/
    
  • 用于多个组件之间共享的数据store

  • 相当于vm和所有vc共享该属性store

  • 安装

    • npm i vuex@3 vue2安装
      
    • npm i vuex@4 vue3安装
      

核心配置项

  • actions
    • 用于处理业务逻辑的action
  • mutations
    • 用于更新state的mutation
  • state
    • 存储共享属性
  • getters
    • 相当于计算属性一样使用
  • module

入门案例(vue2)

目标:实现一个按钮,点击一次数字加1

1. 安装vuex

npm i vuex@2

2. 创建vuex目录和store.js

image-20231113203027820转存失败,建议直接上传图片文件

3. 编写store.js

// 引入vue插件。使用vuex插件时,需要vue
import Vue from 'vue'
// 引入vuex插件
import Vuex from 'vuex'

Vue.use(Vuex)

// 创建三个对象 actions mutations state
// 处理业务逻辑,一个个回调函数
const actions = {
    // context vuex的上下文,相当于一个压缩版的store
    // value 组件传递过来的参数
    plusOne(context,value){ 
        // 业务逻辑
        // ....
        // 也可以通过context进行分发
        // context.dispatch('otherAction',value); 
        // 继续下一个环节,action已经完成了自己的工作,下一个工作由其他(人)来做
        // 通过context提交数据,由其他人进行更新
        // 提交到mutations中的某个mutation,加上value
        value = value+1
        context.commit('PULS_ONE',value)

    }
}
const mutations = {
    // state 需要更新的数据,
    //value  值
    PULS_ONE(state,value){
        state.num += value
    }
}
// 数据对象,做了响应式处理
const state = {
    num:0
}

// 创建store对象
const store = new Vuex.Store({
    // 负责执行某个行为的对象

    actions:actions,
    // 负责更新的对象
    mutations:mutations,
    // 状态对象
    state:state
})

// 暴露Store对象
export default store;

// 简写形式
// export default new Vuex.Store({actions,mutations,state})

4. APP组件中使用

<template>
  <div id="app">
    <h1>数字:{{$store.state.num}}</h1>
    <button @click="plusOne">点我加一</button>
  </div>
</template>

<script>
export default {
  name: 'App',
  components: {
 
  },
  data(){
    return{
      startNum :0
    }
  },
  methods:{
    plusOne(){
      // 这里,这个函数只需要调用vuex的dispatch分发API,完成代码的复用
      // dispatch('action',传递的参数), action--->actions中的某个回调函数
      this.$store.dispatch('plusOne',this.startNum)
    }
  }
}
</script>

<style>

vuex的工作原理

Map简化开发

通过这个可以简化开发

  • ...mapState
  • ...mapMutations
  • ...mapActions
  • ...mapGetters

ES6扩展运算符...

... 该运算符可以将一个数组或者对象去掉[]、{}

  • 数组

    let a =[1,2,3,4,56,7,8]
    ...a => 1 2 3 4 56 7 8
    let b = {
        x:1,
        y:2
    }
    // 此时,对象c拥有b中的所有属性,但b和c不是同一个对象
    // {...b} 可以构建出一个新的对象
    let c = {...b} 
    // 可以给某个对象添加其他对象的属性
    let d = {
        k:3,
        ...b,
        v:4,
    }
    

    使用数组时需要方法名一致,对象则不考虑

模块化开发

  1. 将每个业务分成一个个模块,例如A模块,B模块

  2. 每个模块都有自己的actions,mutations,state

  3. 通过mouble配置项完成注册

    a模块
    export default {
        // 开启命名空间
        namespace: true,
        acitons:{...},
        mutations:{...},
        getters:{...}
    }
    
    // 创建store对象
    const store = new Vuex.Store({
        modules:{
            a : aModule,
            b : bModule
        }
    })
    
  4. 访问时需要指定模块

    • this.$store.state.模块名.属性
  5. 开启命名空间后,可以访问指定的actions等

    ['a/dosome']
    
  6. 访问getters计算属性时

    this.$store.getters['a/reservedName']
    

注意:使用map简化时,注意一下几点

  • 命名空间是否开了?

    • namespaced: true,
      
  • 获取对应东西时,要加上命名空间

  •  computed:{
                ...mapState('a', ['users']),
                ...mapGetters('a',['userLength']),
                 ...mapGetters('b',['vipLength'])
    
            },
            methods:{
                ...mapActions({addUser:'a/saveUser'}),
                // 另一种写法,需要回调函数与store中函数名一致
                // ...mapActions('a',['saveUser'])
            
            }
    
    
  • 两种写法

  • //第一种适用于导入多个
    methods:{
                ...mapMutations('b',{addVip:'SAVE_VIP'})
            }
    //第二种适用于导入单个
     methods:{
                ...mapActions({addUser:'a/saveUser'}),