Vue.js项目开发实战 Vuex

21-Vue.js项目开发实战 Vuex

今日目标:

1.能够说出Vuex的基本使用步骤

2.能够说出Vuex的核心概念

3.能够基于Vuex实现业务功能

1.Vuex概述

Vuex是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间的数据共享

使用Vuex管理数据的好处:
A.能够在vuex中集中管理共享的数据,便于开发和后期进行维护
B.能够高效的实现组件之间的数据共享,提高开发效率
C.存储在vuex中的数据是响应式的,当数据发生改变时,页面中的数据也会同步更新

1.1 组件之间共享数据的方式

父向子传值:v-bind 属性绑定

子向父传值:v-on 事件绑定

兄弟组件之间共享数据: EventBus

  • $on 接收数据的那个组件
  • $emit 发送数据的那个组件

1.2 Vuex 是什么

Vuex 是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间数据的共享。

image-20210701093240608

1.3 使用 Vuex 统一管理状态的好处

① 能够在 vuex 中集中管理共享的数据,易于开发和后期维护
② 能够高效地实现组件之间的数据共享,提高开发效率
③ 存储在 vuex 中的数据都是响应式的,能够实时保持数据与页面的同步

1.4 什么样的数据适合存储到 Vuex 中

一般情况下,只有组件之间共享的数据,才有必要存储到 vuex 中;对于组件中的私有数据,依旧存储在组件
自身的 data 中即可。

2.Vuex的基本使用

1. 安装 vuex 依赖包

npm install vuex --save

2. 导入 vuex 包

import Vuex from 'vuex'
Vue.use(Vuex)

3.创建 store 对象

const store = new Vuex.Store({
 // state 中存放的就是全局共享的数据
 state: { count: 0 }
})

4.将 store 对象挂载到 vue 实例中

new Vue({
 el: '#app',
 render: h => h(app),
 router,
 // 将创建的共享数据对象,挂载到 Vue 实例中
 // 所有的组件,就可以直接从 store 中获取全局的数据了
 store
})

5.实现步骤

创建带有vuex的vue项目,打开终端,输入命令:vue ui
当项目仪表盘打开之后,我们点击页面左上角的项目管理下拉列表,再点击Vue项目管理器
点击创建项目,如下图所示
第一步,设置项目名称和包管理器

第二步,设置手动配置项目

第三步,设置功能项

第四步,创建项目

使用Vuex完成计数器案例

打开刚刚创建的vuex项目,找到src目录中的App.vue组件,将代码重新编写如下:

<template>
  <div>
    <my-addition></my-addition>

    <p>----------------------------------------</p>

    <my-subtraction></my-subtraction>
  </div>
</template>

<script>
import Addition from './components/Addition.vue'
import Subtraction from './components/Subtraction.vue'

export default {
  data() {
    return {}
  },
  components: {
    'my-subtraction': Subtraction,
    'my-addition': Addition
  }
}
</script>

<style>
</style>

在components文件夹中创建Addition.vue组件,代码如下:

<template>
    <div>
        <h3>当前最新的count值为:</h3>
        <button>+1</button>
    </div>
</template>

<script>
export default {
  data() {
    return {}
  }
}
</script>

<style>
</style>

在components文件夹中创建Subtraction.vue组件,代码如下:

<template>
    <div>
        <h3>当前最新的count值为:</h3>
        <button>-1</button>
    </div>
</template>

<script>
export default {
  data() {
    return {}
  }
}
</script>

<style>
</style>

最后在项目根目录(与src平级)中创建 .prettierrc 文件,编写代码如下:

{
    "semi":false,
    "singleQuote":true
}

3. Vuex 的核心概念

3.1 核心概念概述

Vuex 中的主要核心概念如下:

 State

 Mutation

 Action

 Getter

3.2 State

State 提供唯一的公共数据源,所有共享的数据都要统一放到 Store 的 State 中进行存储。

// 创建store数据源,提供唯一公共数据
const store = new Vuex.Store({
  state: { count: 0 }
})
组件访问 State 中数据的第一种方式:
this.$store.state.全局数据名称
组件访问 State 中数据的第二种方式:
// 1. 从 vuex 中按需导入 mapState 函数
import { mapState } from 'vuex'

通过刚才导入的 mapState 函数,将当前组件需要的全局数据,映射为当前组件的 computed 计算属性:

// 2. 将全局数据,映射为当前组件的计算属性
computed: {
 ...mapState(['count'])
}

3.3 Mutation

Mutation 用于变更 Store中 的数据。

① 只能通过 mutation 变更 Store 数据,不可以直接操作 Store 中的数据。

② 通过这种方式虽然操作起来稍微繁琐一些,但是可以集中监控所有数据的变化。

1.触发 mutations 的第一种方式

this.$store.commit() 是触发 mutations 的第一种方式

// 定义 Mutation
const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    add(state) {
      // 变更状态
      state.count++
    }
  }
})
// 触发mutation
methods: {
  handle1() {
    // 触发 mutations 的第一种方式
    this.$store.commit('add')
  }
}

可以在触发 mutations 时传递参数:

// 定义Mutation
const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
  	// 第一个参数永远是state也就是$state对象
  	// 第二个参数是调用add时传递的参数
    addN(state, step) {
      // 变更状态
      state.count += step
    }
  }
})
  // 触发mutation
  methods: {
    handle2() {
      // 在调用 commit 函数,
      // 触发 mutations 时携带参数
      this.$store.commit('addN', 3)
    }
  }
2.触发 mutations的第二种方式

this.$store.commit() 是触发 mutations 的第一种方式,触发 mutations 的第二种方式:

// 1. 从 vuex 中按需导入 mapMutations 函数
import { mapMutations } from 'vuex'

通过刚才导入的 mapMutations 函数,将需要的 mutations 函数,映射为当前组件的 methods 方法:

// 2. 将指定的 mutations 函数,映射为当前组件的 methods 函数
methods: {
 ...mapMutations(['add', 'addN'])
}

3.4 Action

Action 用于处理异步任务。

如果通过异步操作变更数据,必须通过 Action,而不能使用 Mutation,但是在 Action 中还是要通过触发

Mutation 的方式间接变更数据。

触发 actions 的第一种方式

this.$store.dispatch() 是触发 actions 的第一种方式

// 定义 Action
const store = new Vuex.Store({
  // ...省略其他代码
  mutations: {
    add(state) {
      state.count++
    }
  },
  actions: {
    addAsync(context) {
      setTimeout(() => {
      	// 在action中,不能直接修改state中的数据;
      	// 必须通过context.commit()触发某个mutation才行
        context.commit('add')
      }, 1000)
    }
  }
})
// 触发 Action
  methods: {
    handle() {
      // 触发 actions 的第一种方式
      //这里的dispatch函数,专门用来触发action
      this.$store.dispatch('addAsync')
    }
  }

触发 actions 异步任务时携带参数:

// 定义 Action
const store = new Vuex.Store({
  // ...省略其他代码
  mutations: {
    addN(state, step) {
      state.count += step
    }
  },
  actions: {
    addNAsync(context, step) {
      setTimeout(() => {
        context.commit('addN', step)
      }, 1000)
    }
  }
})
// 触发 Action
  methods: {
    handle() {
      // 在调用 dispatch 函数,
      // 触发 actions 时携带参数
      this.$store.dispatch('addNAsync', 5)
    }
  }
触发 actions 的第二种方式:

this.$store.dispatch() 是触发 actions 的第一种方式,触发 actions 的第二种方式:

// 1. 从 vuex 中按需导入 mapActions 函数
import { mapActions } from 'vuex'

通过刚才导入的 mapActions 函数,将需要的 actions 函数,映射为当前组件的 methods 方法:

// 2. 将指定的 actions 函数,映射为当前组件的 methods 函数
methods: {
 ...mapActions(['addASync', 'addNASync'])
}

3.5 Getter

Getter 用于对 Store 中的数据进行加工处理形成新的数据。

Getter不会修改原来的数据,只起到包装的作用。

① Getter 可以对 Store 中已有的数据加工处理之后形成新的数据,类似 Vue 的计算属性。

② Store 中数据发生变化,Getter 的数据也会跟着变化。

// 定义 Getter
const store = new Vuex.Store({
  state: {
    count: 0
  },
  getters: {
  	// 添加了一个showNum的属性
    showNum: state => {
      return '当前最新的数量是【' + state.count + '】'
    }
  }
})

使用 getters 的第一种方式:
this.$store.getters.名称
使用 getters 的第二种方式:
import { mapGetters } from 'vuex'
computed: {
 ...mapGetters(['showNum'])
}

4. 基于 Vuex 的案例

案例:Todos

image-20210702102906137

实现步骤

1. 初始化项目

① 通过 vue ui 命令打开可视化面板,创建新项目 vuex-demo2

② 安装 vuex 依赖包 npm install vuex axios ant-design-vue –S

③ 实现 Todos 基本布局(基于已有样式模板)

2. 完成具体功能

① 动态加载任务列表数据

② 实现文本框与store数据的双向同步

③ 完成添加任务事项的操作

④ 完成删除任务事项的操作

⑤ 动态绑定复选框的选中状态

⑥ 修改任务事项的完成状态

⑦ 统计未完成的任务的条数

⑧ 清除已完成的任务事项

⑨ 实现任务列表数据的动态切换

A.初始化案例

首先使用vue ui初始化一个使用vuex的案例,安装运行依赖axios、ant-design-vue

在项目根目录下新建一个.prettierrc文件

{  "singleQuote": true,  "semi": false}

打开main.js,添加store文件夹下index.js的引入,如下:

import Vue from 'vue'import App from './App.vue'import store from './store/index.js'// 1. 导入 ant-design-vue 组件库import Antd from 'ant-design-vue'// 2. 导入组件库的样式表import 'ant-design-vue/dist/antd.css'Vue.config.productionTip = false// 3. 安装组件库Vue.use(Antd)new Vue({  store,  render: h => h(App)}).$mount('#app')

打开App.vue文件,将store中的数据获取并展示:

<template>  <div id="app">    <a-input placeholder="请输入任务" class="my_ipt" />    <a-button type="primary">添加事项</a-button>    <a-list bordered :dataSource="list" class="dt_list">      <a-list-item slot="renderItem" slot-scope="item">        <!-- 复选框 -->        <a-checkbox>{{ item.info }}</a-checkbox>        <!-- 删除链接 -->        <a slot="actions">删除</a>      </a-list-item>      <!-- footer区域 -->      <div slot="footer" class="footer">        <!-- 未完成的任务个数 -->        <span>0条剩余</span>        <!-- 操作按钮 -->        <a-button-group>          <a-button type="primary">全部</a-button>          <a-button>未完成</a-button>          <a-button>已完成</a-button>        </a-button-group>        <!-- 把已经完成的任务清空 -->        <a>清除已完成</a>      </div>    </a-list>  </div></template><script>export default {  name: 'app',  data() {    return {      list: [        {          id: 0,          info: 'Racing car sprays burning fuel into crowd.',          done: false        },        { id: 1, info: 'Japanese princess to wed commoner.', done: false },        {          id: 2,          info: 'Australian walks 100km after outback crash.',          done: false        },        { id: 3, info: 'Man charged over missing wedding girl.', done: false },        { id: 4, info: 'Los Angeles battles huge wildfires.', done: false }      ]    }  }}</script><style scoped>#app {  padding: 10px;}.my_ipt {  width: 500px;  margin-right: 10px;}.dt_list {  width: 500px;  margin-top: 10px;}.footer {  display: flex;  justify-content: space-between;  align-items: center;}</style>

将App.vue中的数据抽取出来

....data() {    return {    }} ....

打开public文件夹,创建一个list.json文件,文件代码如下:

[  {    "id": 0,    "info": "Racing car sprays burning fuel into crowd.",    "done": false  },  {    "id": 1,    "info": "Japanese princess to wed commoner.",    "done": false  },  {    "id": 2,    "info": "Australian walks 100km after outback crash.",    "done": false  },  {    "id": 3,    "info": "Man charged over missing wedding girl.",    "done": false  },  {    "id": 4,    "info": "Los Angeles battles huge wildfires.",    "done": false  }]

再接着打开store文件夹下index.js,添加axios请求json文件获取数据的代码,如下:

import Vue from 'vue'import Vuex from 'vuex'import axios from 'axios'Vue.use(Vuex)export default new Vuex.Store({  state: {    // 所有任务列表    list: [],      },  mutations: {    initList(state, list) {      state.list = list    }  },  actions: {    getList(context) {      axios.get('/list.json').then(({ data }) => {        console.log(data)        context.commit('initList', data)      })    }  }})

在App.js中

created() {    this.$store.dispatch('getList')}
文本框内容双向绑定

在store文件夹下新增

state: {  // 文本输入框中的值  inputValue: 'AAA'}

在App.vue中

<a-input placeholder="请输入任务" class="my_ipt" :value="inputValue" />
computed: {  ...mapState(['list','inputValue'])}
methods: {  handleInputChange(e) {    // console.log(e.target.value)    this.$store.commit('setInputValue', e.target.value)  }}

在index.js中

mutations: {  setInputValue(state, value) {    state.inputValue = value  },}
B.完成添加事项

首先,打开App.vue文件,给“添加事项”按钮绑定点击事件,编写处理函数

//绑定事件<a-button type="primary" @click="addItemToList">添加事项</a-button>//编写事件处理函数methods:{    ......    addItemToList(){      //向列表中新增事项      if(this.inputValue.trim().length <= 0){        return this.$message.warning('文本框内容不能为空')      }      this.$store.commit('addItem')    }  }

然后打开store.js编写addItem

export default new Vuex.Store({  state: {    //所有任务列表    list: [],    //文本输入框中的值    inputValue: 'AAA',    //下一个id    nextId:5  },  mutations: {    ........    //添加列表项    addItem(state){      const obj = {        id :state.nextId,        info: state.inputValue.trim(),        done:false      }      //将创建好的事项添加到数组list中      state.list.push(obj)      //将nextId值自增      state.nextId++      state.inputValue = ''    }  }  ......})
C.完成删除事项

首先,打开App.vue文件,给“删除”按钮绑定点击事件,编写处理函数

//绑定事件<a slot="actions" @click="removeItemById(item.id)">删除</a>//编写事件处理函数methods:{    ......    removeItemById(id){      //根据id删除事项      this.$store.commit('removeItem',id)    }  }

然后打开store.js编写addItem

export default new Vuex.Store({  ......  mutations: {    ........    removeItem(state,id){      //根据id删除事项数据      const index = state.list.findIndex( x => x.id === id )      // console.log(index);      if(index != -1) state.list.splice(index,1);    }  }  ......})
D.完成选中状态的改变

首先,打开App.vue文件,给“复选”按钮绑定点击事件,编写处理函数

//绑定事件<a-checkbox :checked="item.done" @change="cbStateChanged(item.id,$event)">{{item.info}}</a-checkbox>//编写事件处理函数methods:{    ......    cbStateChanged(id,e){      //复选框状态改变时触发      const param = {        id:id,        status:e.target.checked      }      //根据id更改事项状态      this.$store.commit('changeStatus',param)    }  }

然后打开store.js编写addItem

export default new Vuex.Store({  ......  mutations: {    ........    changeStatus(state,param){      //根据id改变对应事项的状态      const index = state.list.findIndex( x => x.id === param.id )      if(index != -1) state.list[index].done = param.status    }  }  ......})
E.剩余项统计

打开store.js,添加getters完成剩余项统计

getters:{  unDoneLength(state){    const temp = state.list.filter( x => x.done === false )    console.log(temp)    return temp.length  }}

打开App.vue,使用getters展示剩余项

//使用映射好的计算属性展示剩余项<!-- 未完成的任务个数 --><span>{{unDoneLength}}条剩余</span>//导入gettersimport { mapState,mapGetters } from 'vuex'//映射computed:{  ...mapState(['list','inputValue']),  ...mapGetters(['unDoneLength'])}
F.清除完成事项

首先,打开App.vue文件,给“清除已完成”按钮绑定点击事件,编写处理函数

<!-- 把已经完成的任务清空 --><a @click="clean">清除已完成</a>//编写事件处理函数methods:{  ......  clean(){    //清除已经完成的事项    this.$store.commit('cleanDone')  }}

然后打开store.js编写addItem

export default new Vuex.Store({  ......  mutations: {    ........    cleanDone(state){      state.list = state.list.filter( x => x.done === false )    }  }  ......})
G.点击选项卡切换事项

打开App.vue,给“全部”,“未完成”,“已完成”三个选项卡绑定点击事件,编写处理函数
并将列表数据来源更改为一个getters。

<a-list bordered :dataSource="infoList" class="dt_list">  ......  <!-- 操作按钮 -->  <a-button-group>    <a-button :type="viewKey ==='all'?'primary':'default'" @click="changeList('all')">全部</a-button>    <a-button :type="viewKey ==='undone'?'primary':'default'" @click="changeList('undone')">未完成</a-button>    <a-button :type="viewKey ==='done'?'primary':'default'" @click="changeList('done')">已完成</a-button>  </a-button-group>  ......</a-list>//编写事件处理函数以及映射计算属性methods:{  ......  changeList( key ){    //点击“全部”,“已完成”,“未完成”时触发    this.$store.commit('changeKey',key)  }},computed:{  ...mapState(['list','inputValue','viewKey']),  ...mapGetters(['unDoneLength','infoList'])}

打开store.js,添加getters,mutations,state

export default new Vuex.Store({  state: {    ......    //保存默认的选项卡值    viewKey:'all'  },  mutations: {    ......    changeKey(state,key){      //当用户点击“全部”,“已完成”,“未完成”选项卡时触发      state.viewKey = key    }  },  ......  getters:{    .......    infoList(state){      if(state.viewKey === 'all'){        return state.list      }      if(state.viewKey === 'undone'){        return state.list.filter( x => x.done === false )      }      if(state.viewKey === 'done'){        return state.list.filter( x => x.done === true )      }    }  }})
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 《Vue.js前端开发基础与项目实战PDF》是一本关于Vue.js前端开发的实用教程。本书共分为两个部分,前半部分是关于Vue.js基础知识的介绍,后半部分通过实战项目的方式加深读者对Vue.js的理解与应用。 在前半部分,本书首先介绍了Vue.js的基本概念和原则,包括Vue实例、模板语法、计算属性、指令、生命周期等。读者通过这些基础知识的学习,能够了解Vue.js的基本工作原理,掌握Vue.js的基本语法和核心功能。 后半部分,本书通过一个完整的实战项目,引导读者将前半部分所学知识运用于实践。项目从需求分析、项目搭建到页面设计、数据交互等方面进行了详细的讲解。读者通过跟随实战项目的步骤,能够从中学会如何使用Vue.js构建一个完整的前端应用。 《Vue.js前端开发基础与项目实战PDF》的特点在于其结合了理论和实践,让读者既能够理解Vue.js的基本原理和语法,又能够通过实战项目的方式进行实际操作。这种结合使得读者可以更好地掌握Vue.js开发技巧,提升自己的前端开发能力。 总之,《Vue.js前端开发基础与项目实战PDF》是一本适合前端开发初学者的实用教程,通过学习本书,读者能够系统地了解和掌握Vue.js开发技术和应用,为自己的前端开发之路奠定坚实的基础。 ### 回答2: "vue.js前端开发基础与项目实战pdf" 是一本关于Vue.js前端开发的书籍,涵盖了基础知识和实战经验。该书以提供全面详细的教程和示例代码为目标,可用于初学者和有一定经验的开发者。 在基础部分,该书讲解了Vue.js的基本概念和特点,包括Vue.js的生命周期、组件和指令的使用方法、数据绑定和事件处理等。读者将学会如何搭建Vue.js项目,包括使用Vue CLI进行项目初始化和依赖管理,以及使用Webpack进行模块化开发和打包。 在项目实战部分,该书提供了多个实际案例供读者学习和实践。这些案例涵盖了常见的前端开发需求,如用户登录认证、数据可视化、实时通信等。每个案例都由浅入深地介绍了解决方案和实现细节,读者可以从中学习到实际项目开发中的技巧和经验。 此外,该书还介绍了Vue.js的常用插件和工具库,如Vue Router、Vuex、Element UI等,以及与后端API交互和服务器部署等相关内容。读者可以根据自己的需求选择合适的工具和技术栈,提高项目开发的效率和质量。 总之,"vue.js前端开发基础与项目实战pdf"是一本全面介绍Vue.js前端开发的教程书籍,适合想要学习Vue.js开发者。通过学习该书,读者可以掌握Vue.js的基础知识,提升前端开发技能,并能够应用Vue.js开发实际项目。 ### 回答3: 《vue.js前端开发基础与项目实战pdf》是一本介绍Vue.js前端开发基础及实战项目的电子书籍。 Vue.js是一款流行的JavaScript框架,用于构建用户界面。它采用了MVVM(Model-View-ViewModel)架构模式,使开发者能够快速构建高性能的单页面应用程序。本书通过详细的讲解和实例演示,系统地介绍了Vue.js基础知识和开发实践。 首先,本书从Vue.js的概述入手,介绍了Vue.js的特点和优势,并介绍了其与其他流行框架的比较。接着,本书详细介绍了Vue.js的基本语法、组件和指令,以及其数据绑定、事件处理、过滤器和表单验证等常用功能。读者可以通过学习这些基础知识,快速掌握Vue.js开发方法和技巧。 然后,本书通过实战项目来帮助读者更好地理解和应用Vue.js。这些项目包括购物车应用、电影列表和用户管理系统等,涵盖了常见的业务场景。每个项目都有详细的代码实现和步骤说明,读者可以根据实际需求进行修改和扩展,提高自己的开发能力。 总的来说,《vue.js前端开发基础与项目实战pdf》是一本适合初学者和有一定经验的开发者的实用指南。通过学习这本书,读者可以从零开始掌握Vue.js的基础知识,并通过实践项目提升自己的开发能力。无论是对于想要学习Vue.js的新手,还是对于想要深入了解和运用Vue.js开发者,都是一本值得推荐的书籍。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值