使用 Vuex + Vue.js 构建单页应用【新篇】

使用 Vuex + Vue.js 构建单页应用【新篇】

在去年的七月六号的时候,发布了一篇 使用 Vuex + Vue.js 构建单页应用 的文章,文章主要是介绍 vuex 的基本使用方法,发现对大部分的入门同窗有很大的帮助,时至今日还有不少同窗不断的点赞与收藏,浏览量最高达到 20.4K 。鉴于前端技术发展更新快速,特此在这里从新整理一篇 vue2.0 版本的 vuex 基本使用方法,但愿能给更多刚入门或者将要入门的同窗带来帮助。javascript

这篇文章主要是介绍最新 vue2.0 API 的使用方法, 和 vue1.x 的一些差别的地方。html

阅读建议

一、在阅读这篇文章以前,我但愿你已经阅读过我上一篇文章 使用 Vuex + Vue.js 构建单页应用 ,明白咱们须要实现的基本需求。前端

二、但愿你阅读并掌握如下知识点vue

目录层级变化

首先是目录层级的变更,咱们看下先后对比:java

2.0 版本,vuex 的文件夹改成了 storegit

├── index.html
├── src
│   ├── App.vue
│   ├── assets
│   │   └── logo.png
│   ├── components
│   │   ├── Editor.vue
│   │   ├── NoteList.vue
│   │   └── Toolbar.vue
│   ├── main.js
│   └── store
│       ├── actions.js
│       ├── getters.js
│       ├── index.js
│       ├── mutation-types.js
│       └── mutations.js
└── static

1..0 版本es6

├── index.html
├── src
│   ├── App.vue
│   ├── assets
│   │   └── logo.png
│   ├── components
│   │   ├── Editor.vue
│   │   ├── NotesList.vue
│   │   └── Toolbar.vue
│   ├── main.js
│   └── vuex
│       ├── actions.js
│       ├── getters.js
│       └── store.js
└── static

使用方式的变更

在文件的 main.js 中注入,2.0 的注入方式以下

import Vue from 'vue'
import App from './App'
import store from './store';

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  template: '<App/>',
  store,
  components: { App }
})

在组件中使用方式

咱们来看 Editor.vue 组件内部如何使用 vuexgithub

<template>
  <div class="note-editor">
    <div class="form-group">
      <input type="text" name="title"
        class="title form-control"
        placeholder="请输入标题"
        @input="updateNote"
        v-model="currentNote.title">
      <textarea
        v-model="currentNote.content" name="content"
        class="form-control" row="3" placeholder="请输入正文"
        @input="updateNote"></textarea>
    </div>
  </div>
</template>

<style>
  ...
</style>

<script>
import { mapState, mapActions, mapGetters } from 'vuex';
export default {
  name: 'Editor',
  computed: {
    ...mapGetters([
      'activeNote'
    ]),

    currentNote() {
      return this.activeNote;
    }
  },
  methods: {
    ...mapActions({
      update: 'updateNote'
    }),

    updateNote() {
      this.update({
        note: this.currentNote
      });
    }
  }
}
</script>

因为咱们在入口文件 main.js 中已经注入 store 对象,使得咱们可以在子组件中获取到它,在这里,咱们使用了 vuex 提供的三个扩展方法 mapStatemapActionsmapGettersvuex

另一个不一样点是在咱们的 NodeList.vue 组件中,在 vue2.0 里面已经移除了自带的过滤器函数,官方建议咱们使用计算属性,下面是咱们更改后的使用方法:segmentfault

<template>
  <div class="notes-list">
    <div class="list-header">
      <h2>Notes | heavenru.com</h2>
      <div class="btn-group btn-group-justified" role="group">
        <!-- all -->
        <div class="btn-group" role="group">
          <button type="button" class="btn btn-default"
            @click="toggleShow('all')"
            :class="{active: show === 'all'}">All Notes</button>
        </div>

        <!-- favorites -->
        <div class="btn-group" role="group">
          <button type="button" class="btn btn-default"
            @click="toggleShow('favorite')"
            :class="{active: show === 'favorite'}">Favorites</button>
        </div>
      </div>

      <div class="btn-group btn-group-justified" role="group">
        <div class="input-group search">
          <input type="text" class="form-control" v-model="search" placeholder="Search for...">
          <span class="input-group-addon">
            <i class="glyphicon glyphicon-search"></i>
          </span>
        </div>
      </div>

    </div>

    <!-- 渲染笔记列表 -->
    <div class="container">
      <div class="list-group">
        <div
          v-for="(note, index) in searchNotes" :key="index"
          class="list-group-item"
          :class="{active: activeNote === note}"
          @click="updateActiveNote(note)">
          <h4 class="list-group-item-heading">
            {{note.title.trim().substring(0,30)}}
          </h4>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped>
  ...
</style>

<script>
import { mapGetters, mapState, mapActions } from 'vuex';
export default {
  name: 'NoteList',
  data() {
    return {
      search: ''
    }
  },
  computed: {
    ...mapGetters([
      'filteredNotes'
    ]),

    // state 内部状态
    ...mapState([
      'show',
      'activeNote'
    ]),

    // 计算属性,自定义过滤
    searchNotes() {
      if (this.search.length > 0) {
        return this.filteredNotes.filter((note) => note.title.toLowerCase().indexOf(this.search) > -1);
      } else {
        return this.filteredNotes;
      }
    }
  },
  methods: {
    ...mapActions([
      'toggleListShow',
      'setActiveNote'
    ]),

    // 切换列表,所有或者收藏
    toggleShow(type) {
      this.toggleListShow({ show: type});
    },

    // 点击列表,更新当前激活文章
    updateActiveNote(note) {
      this.setActiveNote({ note });
    }
  }
}
</script>

Q&A

其余的变更,你们自行的查看源码学习:vuex-notes-app2

相关文章
相关标签/搜索