万字总结Vue(包含全家桶),希望这一篇可以帮到您(一)

Vue
352
0
0
2022-03-31
万字总结Vue(包含全家桶),希望这一篇可以帮到您(一)

作者:叫我阿琛

转发链接:
https://mp.weixin.qq.com/s/ph3aUt-H4QtBgw9z-VFlHA

目录

万字总结Vue(包含全家桶),希望这一篇可以帮到您(一)本篇

万字总结Vue(包含全家桶),希望这一篇可以帮到您(二)

基础使用

以下代码均经过自己测试,可以复制直接看效果。「注意引入Vue文件」

渲染优先级

  1. render>template>data的插值表达式
  2. {{}} 放的是表达式的时候会 「输出结果」,内部转为函数
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>基本概念</title>
    <script src="vue.js"></script>
</head>
<body>
<h1>显示优先级</h1>
<ul>
    <li>第一个是render 有render方法就输出render的渲染结果</li>
    <li>第二个是template 有template方法就输出template的内容</li>
    <li>最后一个是data,如果两者不存在 则输出data里面的插值表达式</li>
    {{ }} 当这里面放的是一个表达式的时候,会输出表达式的结果 原因 会转化成一个函数 render
</ul>
<p>指令修饰符,有好多 自己官网看</p>

<div id="app">

    {{ msg }}
</div>
<script>
  let vm = new Vue({
    el: '#app',
    data() {
      return {
        msg: '我是data',
      }
    },
    template: '<div>我是template</div>',
    render(h) {
      return h('div', ['我是render'])
    },
    method: {
      fn(e) { // 不添加括号自动添加事件源, 添加括号 手动传入事件源
        console.log('内部已经使用bind 绑定了this ,再次绑定也没什么用')
        console.log(this)
      },
    },
  })
</script>
</body>
</html>

v-model

v-model 实际上是一个 「语法糖」

<input type="text" :value = 'msg' @input="handleInput">
<!-- 实际上是上述的语法糖-->
<input type="text" v-model="msg">

v-model 的应用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>v-model</title>
    <script src="vue.js"></script>
</head>
<body>
<div id="app">

    {{ msg }}
    <p>@input</p>
    <input type="text" :value = 'msg' @input="handleInput">
    <p>这个是@chage</p>
    <input type="text" :value = 'msg' @change="handleInput">
    <p>v-model  是上面@input的语法糖</p>
    <input type="text" v-model="msg">
    <p>@input 和@change 区别  一个是 聚焦的时候 一个是 失去焦点的时候</p>
    <p>下拉列表</p>
    {{ selected }}<br>
    <select v-model="selected">
        <option value="" disabled>请选择</option>
        <option value="1">a</option>
        <option value="2">b</option>
        <option value="3">c</option>
    </select>

    <p>下拉列表多选 这样绑定的值必须是一个列表</p>
    {{ selectedMore }}<br>
    <select v-model="selectedMore" multiple>
        <option value="" disabled>请选择</option>
        <option value="1">a</option>
        <option value="2">b</option>
        <option value="3">c</option>
    </select>

    <p>复选框</p>
    {{ checked }}<br>
    游泳 <input v-model="checked" type="checkbox" value="游泳">
    洗澡 <input v-model="checked" type="checkbox" value="洗澡">
    睡觉 <input v-model="checked" type="checkbox" value="睡觉">

    <p>单选框</p>
    {{ radioed }}<br><input type="radio" value="男" v-model="radioed"><input type="radio" value="女" v-model="radioed">
    <p>v-model 修饰符</p>
    <p>{{ attr }}</p>
    <input type="number" v-model.number="attr">
    <p>{{ attrText }}作用类似@chage</p>
    <input type="text" v-model.lazy="attrText">
    <p>{{ attrText }} 去除空格</p>
    <input type="text" v-model.trim="attrText">
</div>
<script>
  let vm = new Vue({
    el: '#app',
    data() {
      return {
        msg: '我是data',
        selected:'',
        selectedMore:[],
        checked:[],
        radioed:'',
        attr:0,
        attrText:''
      }
    },
    methods: {
     handleInput(e){
       this.msg = e.target.value
     }
    },
  })
</script>
</body>
</html>

watch

观测值的变化 执行对应函数

三种写法:

  1. 添加deep属性,表明要深度遍历
  2. 添加immediate属性,表明 立即执行
  3. 添加 name属性,执行methods的这个方法
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<div id="app">
    {{ msg }}
    {{ name }}
</div>
<script src="vue.js"></script>
<script>
  let vm = new Vue({
    el: '#app',
    data() {
      return {
        msg: { a: '123' },
        name:'456'
      }
    },
    methods: {
      fn() {
        console.log('这是methods')
      },
    },
    // 第一种
    // watch:{
    //   msg:{
    //     handler(oldValue,newValue){
    //       console.log(oldValue,newValue) // 如果是对象的不到老值
    //     },
    //     deep: true  // 如果是对象继续深度遍历
    //   }
    // }
    watch: {
      msg: [
        // {
        //   handler(oldValue, newValue) {
        //     console.log(oldValue, newValue) // 如果是对象的不到老值
        //   },
        //   immediate: true,  // 立即执行
        // },
        // 'fn', // 不知道为什么不行
      ],
      name:'fn'
    },

  })
  setTimeout(() => {
    vm.msg.a = '456'
    vm.name = '789'
  }, 1000)
</script>
</body>
</html>

computed

经常使用get,但是还有一个set

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<div id="app">
    全选: <input type="checkbox" v-model="checkAll">
    <hr>
    <input type="checkbox" v-for="check in checks" v-model="check.check">
</div>
<script src="vue.js"></script>
<script>
  let vm = new Vue({
    el: '#app',
    data() {
      return {
        checks: [{ check: true }, { check: true }, { check: true }],
      }
    },
    computed: {
      checkAll: {
        get() {
          // 有一个不满足 返回false  并且不往下进行
          return this.checks.every((item) => item.check)
        },
        set(newValue) {
          this.checks.forEach(item => item.check = newValue)
        },
      },
    },
  })
</script>
</body>
</html>

watch 和computed区别

  1. computed不会立马取值,用到的时候才会取值. 并且有缓存,依赖数据不改变不更新结果
  2. watch 「立即执行」,会先算出来一个老值.数据变化就执行函数

filter

过滤器,将属性进行格式化后在进行展示

分为 「全局」「局部」两种

会接受两个参数,一个是要格式化的数据,一个是格式化的规则

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://unpkg.com/dayjs@1.8.21/dayjs.min.js"></script>
    <script src="vue.js"></script>
</head>
<body>
<div id="app">
    <p>局部</p>
    {{ timer | format1('YYYY:MM:DD') }}
    <p>全局</p>
    {{ timer | format('YYYY:MM:DD') }}
</div>
<script>
  Vue.filter('format', function (timer, format) {
    return dayjs(timer).format(format)
  })
  let vm = new Vue({
    el:'#app',
    data() {
      return {
        timer: 123456789,
      }
    },
    filters:{
      format1(timer, format){
        return dayjs(timer).format(format)
      }
    }
  })
</script>
</body>
</html>

指令

同样分为 「局部」「全局」

使用的时候 在想要使用的标签上添加 v-xxx xxx为指令名字就可以

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>指令</title>
    <script src="vue.js"></script>
</head>
<body>
<div id="app">
    <p>自动获取焦点</p>
    <input type="text" v-focus>
    <p>点击显示 日历效果</p>
    <div v-click-outside="hide">
        <input type="text" @focus="show">
        <div v-if="isShow">
            日历显示 时间
        </div>
    </div>
    <h1>指令有生命周期.有钩子</h1>
    <ul>
        <li>bind 绑定上的时候会执行一次</li>
        <li>inserted 插入的时候</li>
        <li>update 当引用数据发生变化的时候</li>
        <li>componentUpdate 模板更新</li>
        <li>unbind 解除绑定</li>
        <li>默认写成一个函数 bind+update</li>
    </ul>
    <h1>指令传入三个参数的含义</h1>
    <ul>
        <li>el 当前元素 </li>
        <li>bindings 有关指令的各个属性</li>
        <li>vNode 虚拟节点</li>
        <li>vNode.context Vue实例</li>
    </ul>
</div>

<script>
  // 全局注册指令
  Vue.directive('focus', {
    // 当被绑定的元素插入到 DOM 中时……
    inserted: function (el) {
      // 聚焦元素
      el.focus()
    },
  })
  let vm = new Vue({
    el: '#app',
    // 局部指令
    directives: {
      clickOutside: {
        bind(el, bindings, vNode) {
          el.handler = function (e) {
            // console.log(e.target)
            console.log(vNode.context)
            if (!el.contains(e.target)) {
              vNode.context[bindings.expression]()
            }
          }
          document.addEventListener('click', el.handler)
        },
        unbind(el) {
          document.removeEventListener('click', el.handler)
        },
      },
    },
    data() {
      return {
        isShow: false,
      }
    },
    methods: {
      show() {
        this.isShow = true
      },
      hide() {
        this.isShow = false
      },
    },
  })
</script>
</body>
</html>

实例属性

介绍一些常用的 「实例属性」

  1. $mount() 挂载,参数写要挂载的节点。如果不写,则挂载的$el属性上,可以手动挂载(比如写Message弹框)
  2. $options 获取用户写的配置
  3. $watch 跟watch 用法一样
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>实例属性</title>
    <script src="vue.js"></script>
</head>
<body>
<div id="app">
    {{ msg }}
</div>
<script>
  let vm = new Vue({
    // el:'#app',
    data() {
      return {
        msg: '我是data',
      }
    },
    template: '<div>我是template</div>',
    render(h) {
      return h('div', ['我是render'])
    },
  })
  vm.$mount() // 挂载 提供值了就挂载到对应的 节点上
  // 不提供就挂载到$el 属性上 代表要手动挂载
  console.log(vm.$el) // 获取真实节点
  document.body.appendChild(vm.$el)

  console.log(vm.$options) // 用户参数
  console.log(vm.$watch('msg', function (oldValue, newValue) {
    console.log(oldValue, newValue)
  })) //  就是 watch  另一种写法  批量更新 只更新一次 内部有队列
</script>
</body>
</html>

进阶

动画

动画分为两种,一种是CSS动画,一种是js动画。各位按照需求选择

因为个人推荐使用CSS作动画,所以JS版本就不再写出来了。有兴趣的朋友可以点击这里

「css版本」

就是把 「要做动画的DOM元素用transition包裹一下

然后记住一下6个名字,分别对应动画不同的周期

  1. .v-enter 进入动画时候
  2. .v-enter-active 进入动画过程中
  3. .v-enter-to 进入动画进行到最后
  4. .v-leave 这个没有实际意义,为了美感
  5. .v-leave-active 离开动画过程中
  6. .v-leave-to 离开动画结束
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>动画</title>
    <script src="../vue.js"></script>
</head>
<body>
<div id="app">
    <p>transiton 可以有name 属性 给改名字,这样一些 v-leave 则变成的  name-leave</p>
    <transition>
        <div v-show="isShow" class="box" style=" width: 100px;height: 100px;">
        </div>
    </transition>
    <button @click="handleShow">点我</button>
    <p>transition Vue动画标签 transition-group 动画组</p>
</div>
<script>
  let vm = new Vue({
    el: '#app',
    data() {
      return {
        isShow: false,
      }
    },
    methods: {
      handleShow() {
        this.isShow = !this.isShow
      },
    },
  })
</script>
<style>
    .box {
        background-color: red
    }

    /*进入动画时候的颜色*/ 
    .v-enter {
        background-color: blue;
    }

    /*动画过程中*/ 
    .v-enter-active {
        transition: all 2s linear;
    }

    /*动画进行到最后*/ 
    .v-enter-to {
        background-color: yellow;
    }

    /*    进行完之后会变成红色*/ 

    /*这个没有实际意义,为了美感*/ 
    .v-leave {
        background-color: purple;
    }
    .v-leave-active{
        transition: all 2s linear;
    }
    .v-leave-to{
        background-color: blue;
    }
</style>
</body>
</html>

动画组

与上一个不一样的是,这个数多组动画。

「区别」 使用了 transition-group

「动画名称」

  • enter-class
  • enter-active-class
  • enter-to-class (2.1.8+)
  • leave-class
  • leave-active-class
  • leave-to-class (2.1.8+)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>动画</title>
    <script src="../vue.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
</head>
<body>
<div id="app">
    <p>vue中动画组</p>
    <input type="text" v-model="content">
    <transition-group
            enter-active-class="animated bounceInLeft"
            leave-active-class="animated bounceOutRight"
    >
        <li v-for="arr in computedArr" :key="arr">{{ arr }}</li>
    </transition-group>
</div>
<script>
  let vm = new Vue({
    el: '#app',
    data() {
      return {
        content:'',
        arrs:['abc','basd','zxcw','awqec','kjea']
      }
    },
    methods: {
      handleShow() {
        this.isShow = !this.isShow
      },
    },
    computed:{
      computedArr(){
        return this.arrs.filter(item => item.includes(this.content))
      }
    }
  })
</script>
<style>
li{
    width: 200px;
    background-color: blue;
    line-height: 35px;
}
</style>
</body>
</html>

组件

组件通讯(重点)

我总结了 一下,大概以下几种

  1. props+emit
  2. provide+inject 单项 数据流
  3. $parent+$children 直接触发父/子类的事件
  4. $broadcast + $dispatch 自己在原型上写的
  5. $attrs+$listeners 通过所有属性和方法的集合获取
  6. $bus 类似Vuex
  7. Vuex Vue插件

props+emit

// parents
<template>
    <div>
        <h1>Parent</h1>
        <h2>第一种</h2>
        <Son :money="money" :changMoney="changMoney"></Son>
        <p>第二中方法 click2是自己定义的名字,不是原生事件</p>
        <Son :money="money" @click2="changMoney"></Son>
    </div>
</template>
<script>
  import Son from './Son'
  export default {
    name: 'Parent',
    data() {
      return {
        money: 200,
      }
    },
    components: {
      Son
    },
    methods: {
      changMoney(value) {
        this.money = value
      },
      changMoney2(val) {
        this.money += val
      },
    },
  }
</script>

// son
<template>
    <div>
        <h1>Son</h1>
        <p>子组件接收到之后,利用props 属性接受,然后可以直接使用</p>
        <p>子组件可以使用父组件传递的属性和函数</p>
        我是爸爸给我的钱{{ money }}
        <h2>第一种</h2>
		<button @click="changMoney(500)">改变父亲钱数</button>
        <h2>第二种方法</h2>
        <button @click="change">改变父亲钱数2</button>
    </div>
</template>
<script>
  export default {
    props:{
      money: {
        type:Number,
        default:100
      },
      changMoney:{
        type:Function,
        default: ()=>{}
      }
    },
    methods:{
      change(){
        this.$emit('click2',300)
      }
    }
  }
</script>

第一种是 传递一个属性还有一个函数,子代接收到之后,可以在使用

第二种是 利用$emit, 直接触发 「在父级定义的函数」

「特别注意」,这个click2「不是原生的」,你把它叫做 a , b 之类等都可以

provide+inject

「官方建议」

provideinject 主要在开发高阶插件/组件库时使用。并不推荐用于普通应用程序代码中。

这个就比较简单。类似于reactredux

// parent
<template>
    <div>
        <h1>Parent</h1>
        <h1> 关于son2  跨代通讯</h1>
        <Son2 @eat="eat"></Son2>
    </div>
</template>
<script>
  import Son2 from './Son2'

  export default {
    provide(){
      return {parent:this}
    },
    name: 'Parent',
    data() {
      return {
        money: 200,
      }
    },
    components: {
      Son2,
    },
    methods: {
      eat(){
        console.log('patent中的eat方法')
      }
    },
  }
</script>

// son2
<template>
    <div>
        Son2
        <GrandSon></GrandSon>
    </div>
</template>
<script>
  import GrandSon from './GrandSon'

  export default {
    name:'Son2',
    components: {
      GrandSon,
    },
  }
</script>

// grandSon
<template>
<div>
    GrandSon
    <p>跨代通讯的值</p>
    {{ parent.money }}
    <button @click="$parent.$emit('eat')">触发父组件的eat方法</button>
</div>
</template>
<script>
export default {
  inject:['parent']
}
</script>

写一个Son2的作用,就是让大家明白,隔代也是可以的。一个提供,一个接收之后就可以使用

$parent+$children

这个我就直接用上面的代码了。这个比较简单。就是通过$parent/$children 找到它的父/子级。然后 使用或者触发他们的属性或者方法

$broadcast + $dispatch

再次引用官方的话

$dispatch$broadcast 已经被弃用。请使用更多简明清晰的组件间通信和更好的状态管理方案,如:Vuex。

当然,我们还是介绍一些这两个方法,各位看需要使用(小声bb一下,我觉得Vuex真香)

// 在main.js上
import Vue from 'vue'
import App from './App';

/**
 *  找父节点触发事件
 * @param eventName
 * @param ComName
 * @param Value
 */ 
Vue.prototype.$dispatch = function (eventName, ComName = '', Value = '') {
  let parent = this.$parent;
  while (parent) {
    if (ComName && parent.$options.name === ComName) {
      parent.$emit(eventName, Value)
      return
    } else {
      parent.$emit(eventName, Value)
      parent = parent.$parent
    }
  }
}
/**
 * 找子节点触发事件
 * @param eventName
 * @param ComName
 * @param value
 */ 
Vue.prototype.$broadcast = function (eventName, ComName = '', value = '') {
  let children = this.$children // 获取得是数组
  function broadcast(children) {
    for (let i = 0; i < children.length; i++) {
      let child = children[i]
      if (ComName === child.$options.name) {
        child.$emit(eventName, value)
        return
      } else {
        if (child.$children) {
          broadcast(child)
        }
      }
    }
  }
  broadcast(children)
}

这两个方法利用了$parent$children。不断获取父/子节点,触发相对应的事件。

我这个$dispatchelse写的是,如果不是这个组件的事件,我也触发了。其实应该把这句删除。只 继续往上找就可以

「使用」

// 直接这样使用就好
<button @click="$parent.$emit('eat')">触发父组件的eat方法</button>

$attrs+$listeners

官方定义

// APP.vue
<template>
    <div>
        <Test :a="1" :b="2" :c="3" :d="4" @click="click"></Test>
    </div>
</template>
<script>
  import Test from './test'
  export default {
    data() {
      return {
        msg: 'hello',
      }
    },
    components: {
      Test,
    },
    methods:{
      click(){
        console.log('我是APP中的click')
      }
    }
  }
</script>

// test.vue
<template>
<div>
    我是test
    <h1>使用$attrs可以获得,但是会绑定在DOM元素上</h1>
    <ul>
        <li>设置 <strong>inheritAttrs:false </strong>就不会绑定了</li>
        <li>当props接收后,arrts将不会显示已经被接收的</li>
        {{ $attrs }}
        <li>这样子代传递</li>
        <button @click="$listeners.click">触发APP中的click</button>
        <test2 v-bind="$attrs" v-on="$listeners"></test2>
    </ul>
</div>
</template>
<script>
    import test2 from './test2';
    export default {
      props:['a'],
      name:'Test',
      inheritAttrs:false,
      components:{
        test2
      }
    }
</script>

//test2.vue
<template>
    <div>
        <h1>我是test2</h1>
        {{ $attrs }}
        <button @click="$listeners.click">触发APP中的click</button>
    </div>
</template>
<script>
  export default {
    name: 'test2',
  }
</script>

「注意」

  1. 父级这样传递属性的过程中,会把这个属性绑定在DOM元素上,(被props接收的不会被绑定),可以在子类中使用inheritAttrs:false,来设置取消绑定
  2. 使用得时候,直接使用$attrs.x/$listeners.x使用
  3. 往下一代传递的时候,直接使用v-bind="$attrs" v-on="$listeners",就可以把没有被props接收过的都传给下一代使用

$bus

就是挂载了一个Vue实例

// APP.vue
<template>
    <div>
        <h1>子组件如何监听父组件的mounted</h1>
        <p>组件挂载, 先挂载父组件 -》渲染子组件,子mounted -》 父mounted</p>
        <p>可以实现任意组件之间的通讯,但只适合小规模的</p>
        <bus></bus>
    </div>
</template>
<script>
  import bus from './$bus使用';
  export default {
    data() {
      return {
        msg: 'hello',
      }
    },
    mounted(){
      this.$bus.$emit('监听事件','hello')
    },
    components: {
      bus
    },
  }
</script>
// $bus使用
<template>
<div>
    bus
    {{ $bus.a }}
</div>
</template>
<script>
  export default {
    name: 'bus',
    mounted() {
      // 发布订阅模式  可以多次订阅
      this.$bus.$on('监听事件', function (value) {
        console.log(value)
      })
    },
    beforeDestroy(){
      // 解绑组件
      this.$bus.$off('监听组件')
    }
  }
</script>

Vuex

请往后面看

插槽

<template>
    <div>
        <h1>插槽</h1>
        <test1>
            我是标签里面的内容
        </test1>
        <h1>具名插槽</h1>
        <p>新版写法只可以用 template</p>
        <p>这里插值表达式的数据用的是父类的</p>
        <test1>
<!--            老版本写法-->
<!--            <div slot="header">asd</div>-->
<!--            <div slot="footer">qwe</div>-->
            <template v-slot:header>header {{ msg }}<br></template>
            <template v-slot:footer>footer</template>
        </test1>

        <h1>作用域插槽</h1>
        <p>这样用的是子类的数据</p>
        <test1>
<!--            老版本写法-->
<!--            <div slot="header" slot-scope="{a,b}">{{ a }}{{ b }}</div>-->
            <template v-slot:header="{a,b}" >{{ a }},{{ b }}</template>
        </test1>
    </div>
</template>
<script>
import test1 from './test1';
  export default {
    data() {
      return {
        msg: 'hello',
      }
    },
    components:{
      test1
    }
  }
</script>

// test1
<template>
    <div>
        <h1>我是test1</h1>
        <slot></slot>
        <slot name="header" a="1" b="2"></slot>
        <slot name="footer"></slot>
    </div>
</template>
<script>
  export default {
    name: 'test1',
  }
</script>

这个比较简单,就不再多多叙述。强调一点,新老版本区别

  1. 「新版本」只可以用template进心包裹
  2. 「老版本」可以用div

总结

看完上面的内容可以尝试模仿写一下 element-ui的表单组件。他们使用了async-validator作为校验。

Vue

同样有一个简单版本Vue数据响应式和编译原理分析 和 模拟实战.这个版本没有用到虚拟Dom等。

虚拟dom。个人也总结了一篇帮你深入了解虚拟DOM和DOM-diff,希望能帮到各位

仅仅是一个简单的实现。但是实现了 「部分指令」

完整部分(即这次总结的,带上虚拟dom等等),这个内容由于太多(标题细分太多。不好去寻找)。我另写了一篇文章,还在整理中,1号大概可以放出来。

「贴一个图证明一下。实在是考虑的太多,所以写出来比较慢」

万字总结Vue(包含全家桶),希望这一篇可以帮到您(一)

UTOOLS1593399637478.png

vueX

推荐一下自己的另一篇文章Vuex的简单实现,感觉这一篇写的相对简单一点

Vuex 用法

这个就不多做解释了。不太熟练的朋友可以先去看官方文档

给出一下我的数据定义

// store/index.js
import Vue from 'vue'
// import Vuex from 'vuex'
import Vuex from './../vuex2'

Vue.use(Vuex)
const store = new Vuex.Store({
  state: {
    age: 10
  },
  strict: true,
  getters: {
    myAge(state) {
      return state.age + 30
    }
  },
  mutations: {
    // 同步更改state  在严格模式下不可以使用异步
    change(state, payload) {
      state.age += payload
    }
  },
  actions: {
    // 异步更改state
    asyncChange({ commit }, payload) {
      setTimeout(()=>{
        commit('change', payload)
      }, 1000)
    }
  }
})
export default store

本篇未完结,请见下一篇

作者:叫我阿琛

转发链接:
https://mp.weixin.qq.com/s/ph3aUt-H4QtBgw9z-VFlHA