Action

Action 类似于 mutation,不同在于:

  • Action 提交的是 mutation,而不是直接变更状态。
  • Action 可以包含任意异步操作。

4. 如何调用action呢?

  1. this.$store.dispatch('action的名字', payload)
  2. this.$store.dispatch({

        type: 'action的名字',
        ...payload
    })
  3. 通过 mapActions() 辅助函数(更推荐)

?明明可以在组件内实现异步代码之后再去调用mutation。为何要使用action呢?
!为了能够共享(复用)!

actions - 里面存放的是 action, action 是可以异步去修改 state 数据的地方,但是它并不能直接修改 state 数据,而是在里面调用了 某个 mutation.

  • 第一个参数,是自动接受到的 context (上下文对象,当前的仓库实例)
  • 第二个参数,是payload
  • 可以实现异步代码
  • 要修改 state 的数据,其实是通过 context.commit() 再去调用了某个 mutation

异步添加商品到购物车

  • 需要先将数据调用后端接口来存储到数据库中
  • 然后把本地的仓库也给更新。
  • 在通过 context.commit() 来调用 mutation

一个 store.dispatch 在不同模块中可以触发多个 action 函数。在这种情况下,只有当所有触发函数完成后,返回的 Promise 才会执行。

Module

  • 由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
  • 为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割
  // 引入拆分出去的子模块
import moduleA from './modules/a'
import moduleB from './modules/b'  
Vue.use(Vuex)
 const store = new Vuex.Store({
      // 将state数据都拆分到子模块中
      state: {
        name: '主'
      },
      modules: {
        a: moduleA,
        b: moduleB
      }
    })

拆分模块

如何访问子模块的state数据?

  1. this.$store.state.xx模块的名字.yy数据
  2. computed
  3. mapState()

?当在子模块中定义了相同名字的 getter 数据,发现抱错。 duplicate getter key: nameLength ?

原因是,子模块的 getter 数据,是挂载到全局的上面。

默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的——这样使得多个模块能够对同一 mutation 或 action 作出响应。

这时就不能取同样的名字

? 当在子模块中定义了相同名字的 mutation 或 action 数据时,后续调用的话,都会被执行。

我们希望拆分出来的模块能够独立,这时就需要命名空间

  1. 定义模块的时候,设置一个 namespaced: true
  2. mutation 与 action 找不到了

    1. mutation

      1. this.$store.commit('模块名/mutation的名字', payload)
      2. mapMutations('模块名', ['mutation的名字'])
    2. action

      1. this.$store.dispatch('模块名/action的名字', payload)
      2. mapActions('模块名', ['action的名字'])
  3. getter 数据也找不到了

    1. mapGetters('模块名', ['getter的名字'])

指令

  • v-if
  • v-show
  • v-else
  • v-else-if
  • v-bind
  • v-on
  • v-model
  • v-for
  • v-once
  • v-html
  • v-slot v2.6.0
  • v-pre
  • v-text
    能解决{{}}的闪烁问题
  • v-cloak
    能解决{{}}的闪烁问题

    1. 将 v-cloak 放在挂载点元素上。
    2. 设置一个 div[v-clock] { display: none }

中间事件管理器

其实就是一个发布订阅者模式。在 vue 中我们可以通过实例化一个空的vue实例对象来操作

  1. const bus = new Vue()
  2. A -> B 先在 B 组件中通过 bus.$on() 来监听一个自定义事件
  3. A -> B 在 A 组件的某个时刻通过 bus.$emit() 来触发自定义事件

组件通信

  1. 父->子 props
  2. 子->父 $emit
  3. 兄弟组件之间 找到相同的父级组件
  4. 更复杂的组件之间 中间事件管理器|中间事件总线|bus(公交车) || vuex
  5. 路由页面组件之间 vuex

特殊情况 (不要直接去修改人家的数据)

  1. $root 能够获取到根组件的实例对象
  2. $parent 能够获取到父组件的实例对象
  3. $children 能够获取到子组件的实例对象集合
  4. $refs 能够获取到子组件或者元素,
    如果是子组件的话,得到的就是子组件的实例对象
    如果是元素的话,得到的就是元素的DOM对象

    1. 先给子组件或者元素做一个标记,通过 ref 属性。ref="box"
    2. 这时就可以通过 this.$refs.box 去获取到了。

过滤器

如果需要对数据做一些格式化的操作,就可以使用过滤器了。

需求:

  1. 有一个 price = 10, 需要在页面上显示为 $10
  2. 有一个 str = 'abc', 需要在页面上显示为 Abc || ABC
  3. 有一个 date = 123123123123, 需要在页面上显示为 2019-12-04 12:03:56

使用

  1. 在 filters 选项中定义好 过滤器
  2. 通过 管道符号去使用过滤器即可
{{ msg | 过滤器的名字 }}

<div :id="msg | 过滤器的名字"></div>

过滤器传参

toUpperCase 这个过滤器能够接受第二个参数,isAll 值是 Boolean 类型,为true是就全部转大写,否则只首字母大写

过滤器链式调用

{{ msg | 过滤器1 | 过滤器2 | 过滤器3 }}

全局过滤器,

filters 选项设置的过滤器是局部过滤器,想要实现一个全局过滤器的话,使用
Vue.filter('过滤器名字', () => {

})

动态组件

vue 内置了一款 component 组件,可以通过设置这个组件的 is 属性为某个组件的名字,从而实现用某个组件去替换这个动态组件的模板内容

<div id="app" v-cloak>
    <button :class="{'active': curPage === 'home'}" @click="curPage = 'home'">首页</button>
    <button :class="{'active': curPage === 'list'}" @click="curPage = 'list'">列表页</button>
    <button :class="{'active': curPage === 'about'}" @click="curPage = 'about'">关于页</button>

    <!-- <home v-if="curPage === 'home'"></home>
    <list v-else-if="curPage === 'list'"></list>
    <about v-else></about> -->

    <!-- 动态组件 component 内置组件 -->
    <comopnent :is="curPage"></comopnent>
  </div>

属性代理

  • ES5 Object.defineProperty() 实现数据代理
  • Object.defineProperty(要代理的对象,要代理的属性,配置项)
Last modification:December 26th, 2019 at 08:58 am
如果觉得我的文章对你有用,请随意赞赏