Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

state的基础用法 #5

Open
lazyken opened this issue Mar 11, 2018 · 0 comments
Open

state的基础用法 #5

lazyken opened this issue Mar 11, 2018 · 0 comments

Comments

@lazyken
Copy link
Owner

lazyken commented Mar 11, 2018

前一节我们已经知道了通过store.state来获取状态对象,以及通过store.commit方法触发状态变更。
那么我们在Vue组件中怎么才能获取到状态和修值呢

在Vue组件中获得Vuex状态

这里主要有2点:
1.Vuex 通过 store 选项,提供了一种机制,将状态从根组件“注入”到每一个子组件;且子组件能通过 this.$store 访问到store。
2.在vue根实例下的子组件中,通过computed属性读取并返回store中的状态state。computed属性是根据它的依赖自动更新的。所以只要store中的state 发生变化,它就会自动变化。

const app = new Vue({
  el: '#app',
  // 把 store 对象提供给 “store” 选项,这可以把 store 的实例注入所有的子组件
  store,
  components: {
 //简写,相当于Counter:counter
    Counter
  },
  template: `
  <div class="app">
   <counter></counter>
  </div>
 `
})
const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count() {
      return this.$store.state.count
    }
  }
}

vue实例的template选项--template模板会被编译成渲染函数,然后再渲染DOM树。效果是会把#app里的内容全部替换成template的模板内容。
感觉像是slot(关于这点的一个小例子

下面是一个完整的例子:

<div id="app">
  <my-count></my-count>
  <p>
    <button @click="increment">+</button>
    <button @click="decrement">-</button>
  </p>
</div>
<template id="myCount">
  <div>
    <h3>Count is {{count}}</h3>
  </div>
</template>
// 组件
const Counter = {
  template:"#myCount",
  computed: {
    count (){
      return this.$store.state.count
    }
  }
}
// 储存状态state的store仓库
const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment: state => state.count++,
    decrement: state => state.count--
  }
})
// vue实例
new Vue({
  el: '#app',
  // 把 store 对象提供给 “store” 选项,这可以把 store 的实例注入所有的子组件
  store,
  // 注册组件
  components: {
    "my-count":Counter
  },
  methods: {
    increment() {
      store.commit('increment')
    },
    decrement() {
      store.commit('decrement')
    }
  }
})

①[这里想吐槽关于“根组件”和“子组件”具体指的是什么?不过它仅仅是文字上让我产生了歧义,想哔哔的时候再写吧,你不必管它]

mapState 辅助函数

当一个组件需要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用 mapState 辅助函数帮助我们生成计算属性,让你少按几次键(这个键就是键盘上的键,意思少写代码。)

mapState这个辅助函数,它的作用可以理解为一个语法糖,让我们使用简写方法来获取多个状态,下面举例说明:

<div id="app">
  <my-count></my-count>
  <p>
    <button @click="increment">+</button>
    <button @click="decrement">-</button>
  </p>
</div>
<template id="myCount">
  <div>
    <h3>count is {{count}}</h3>
    <h3>num is {{num}}</h3>
    <h3>countPlusLocalState is {{countPlusLocalState}}</h3>
  </div>
</template>
//先整一个store
const store = new Vuex.Store({
  state: {
    count: 0,
    num: 0
  },
  mutations: {
    increment: state => {
      state.num++;
      state.count++
    },
    decrement: state => {
      state.num--;
      state.count++
    }
  }
})
// 组件
const Counter = {
  data() {
    return {
      localCount: 10
    }
  },
  template: "#myCount",
  //下面列举了一些使用mapState函数和不使用它的对比,当你复制代码自己调试的时候请保留一个computed,把其他的注释掉
  //先看不使用的例子
  computed: {
    count() { return this.$store.state.count},
    num() { return this.$store.state.num},
    countPlusLocalState() { return this.$store.state.num + this.localCount }
  }
  //使用mapState辅助函数
  //方法一
  computed: Vuex.mapState({
    // 省去了return语句
    count: state => state.count,
    num: state => state.num,
    // 为了能够使用 `this` 获取局部状态,必须使用常规函数,下同
    countPlusLocalState() { return this.$store.state.num + this.localCount }
  })
  //方法二
  computed: Vuex.mapState({
    // 传字符串参数 'count' 等同于 `state => state.count`
    count: 'count',
    num: 'num',
    countPlusLocalState() { return this.$store.state.num + this.localCount }
  })
  //方法三
  computed: Vuex.mapState({
    count: state => state.count,
    num: 'num',
    countPlusLocalState() { return this.$store.state.num + this.localCount }
  })
  //方法四
  //当映射的计算属性的名称与 state 的子节点名称相同时,我们也可以给 mapState 传一个字符串数组。
  //由于mapState函数参数为数组,countPlusLocalState无法添加,所以模板里的对应的h3标签先给它注释掉吧
  computed: Vuex.mapState([
    // 映射 this.count 为 store.state.count;this.num 为 store.state.num
    'count', 'num'
  ])
//最后还需要一个vue实例
new Vue({
  el: '#app',
  // 把 store 对象提供给 “store” 选项,这可以把 store 的实例注入所有的子组件
  store,
  // 注册组件
  components: {
    "my-count": Counter
  },
  methods: {
    increment() {
      store.commit('increment')
    },
    decrement() {
      store.commit('decrement')
    }
  }
})

对象展开运算符

上面的方法四,我们的computed无法一同返回countPlusLocalState状态,其实我们还有办法来解决这个问题。使用对象展开运算符,如果你不了解对象展开运算符是什么,只看官方文档也许会有点懵逼,请先查找资料了解一下,再看下面的例子就会明白了:
我们改写一下方法四

computed: {
  countPlusLocalState(){ return this.$store.state.num + this.localCount },
  ...Vuex.mapState([ 'count', 'num'])
}

使用对象展开运算符将可以把count,num与 countPlusLocalState混合为一个对象,然后返回给computed。是不是很简单

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant