Vue 之 Vuex 使用 vuex 实现一个 todo 列表的简单实例
目录
Vue 之 Vuex 使用 vuex 实现一个 todo 列表的简单实例
一、简单介绍
Vue 开发的一些知识整理,方便后期遇到类似的问题,能够及时查阅使用。
本节介绍,Vue 开发的实例实战,使用Vue 中的 vuex 来实现一个简单的 todo 案例,熟悉一下 vuex 的使用,如有不足,欢迎指出,或者你有更好的方法,欢迎留言。
操作环境:
- win10
- node v16.14.2
- npm 8.5.0
- vue 2.5.2
- webpack 3.6.0
- vuex 3.6.2
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
状态自管理应用包含以下几个部分:
- 状态,驱动应用的数据源;
- 视图,以声明方式将状态映射到视图;
- 操作,响应在视图上的用户输入导致的状态变化。
以下是一个表示“单向数据流”理念的简单示意:
vue中 vuex 的交互示意图如下:
Vuex 官网地址:Vuex 是什么? | Vuex
vuex中,有默认的五种基本的对象简单理解:
- state : (初始化数据)
- getter (输出给外界数据)
- mutation (定义的方法,必须同步)
- action (输出给外界方法,可异步)
- module(每一个js 文件都可以包含state getter mutation action四项,统一进行管理)
二、实现原理
1、vue init webpack project_name 创建工程
2、router 路由管理 Home 和 Todos 界面跳转
3、store 管理 todos 的数据的添加删除,其中 store 由 state 、getters、actions、mutations 组成
三、注意事项
1、注意 vue 和 vuex 版本要搭配,不然 vuex 会无法使用,报 vuex computed Cannot read property 'getters' of undefined
类似错误
2、基础 node 、npm 、vue 环境已经配置好,这里不再赘述
可参见博文:Web 前端 之 Vue webpack 环境的搭建及工程创建简单整理
四、效果预览
五、实现步骤
基础环境提前配置好:Web 前端 之 Vue webpack 环境的搭建及工程创建简单整理
1、在控制台输入 vue init webpack project_name ,创建工程,根据需要设置即可
2、创建好工程,cd 切换进工程文件夹,npm run dev ,浏览器输入对应网址 http://localhost:8080 即可看到 Vue 说明创建成功
3、这里用到 vuex ,输入 npm install vuex --save ,进行安装 vuex ,出现如图,可能vue 与 vuex 版本适配问题,这里 vue 2.5.2 ,适配 vuex 3 版本,使用 npm install vuex@3 --save ,重新安装 vuex
4、创建文件夹 store 使用 vuex 管理 todos 数据的获取、添加与删除等功能
5、然后创建 pages 管理 Home 和 Todos 界面
6、在 router 文件夹中的 index.js 添加对 Home 和 Todos 界面的路由
7、记得把 store 添加到 main.js 中
8、做好上面,即可在控制台,输入 npm run dev ,进行编译,编译完浏览器输入对应网址(http://localhost:8080),简单操作,效果如下
六、关键代码
1、store
// index.js
/**
* Created by 12722 on 2022/7/13.
*/
import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters.js'
import actions from './actions.js'
import mutations from './mutations.js'
Vue.use(Vuex)
console.log("store ========== ")
export default new Vuex.Store({
state:{
todos:[{
id:1,
content:'first work'
}]
},
getters,
actions,
mutations
})
// mutation-types.js
export const ADDTODO="ADDTODO"
export const DELTODO='DELTODO'
// getters.js
export default {
todos: state=> state.todos
}
// actions.js
import * as Types from './mutation-types.js'
export default {
addTodo({commit},todo){
commit(Types.ADDTODO,todo)
},
delTodo({commit},todo){
commit(Types.DELTODO,todo)
}
}
// mutations.js
import * as Types from './mutation-types.js'
let idStart = 1
export default {
[Types.ADDTODO](state,todo){
if(todo.id==null){
idStart += 1
todo.id = idStart
console.log('todo = ',todo)
}
state.todos.push(todo)
},
[Types.DELTODO](state,todo){
state.todos.forEach((item,index)=>{
if(item.id===todo.id){
state.todos.splice(index,1)
}
})
}
}
2、pages
// Home.vue
<template>
<div class="hpme">
<router-link to="/">Home</router-link>
<router-link to="todos">Todos</router-link>
<h1>这是 Home 界面</h1>
</div>
</template>
<script>
export default {
name: 'Home',
data: function () {
return {
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
// Todos.vue
<template>
<div class="todo">
<router-link to="/">Home</router-link>
<router-link to="todos">Todos</router-link>
<h1 class="todos-title">这是 Todos 界面</h1>
<input v-model="newTodo.content" type="text"><button @click="createTodo">Add</button>
<ul>
<li v-for="todo in todos" :key="todo.id">{
{todo.content}}
<span @click="delTodo(todo)">delete</span>
</li>
</ul>
</div>
</template>
<script>
import { mapGetters, mapActions } from 'vuex'
export default {
name: 'Todos',
data: function () {
return {
newTodo:{
content:''
}
}
},
computed:{
...mapGetters([
'todos'
])
},
methods:{
...mapActions([
'addTodo',
'delTodo'
]),
createTodo(){
this.addTodo({
...this.newTodo
})
this.newTodo.content = ''
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.todos-title{
font-size: 30px;
color: red;
}
</style>
3、router
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'Home',
component: ()=> import (/*webpackChunkName:'Home'*/'@/pages/Home')
},
{
path: '/todos',
name: 'Todos',
component: ()=> import (/*webpackChunkName:'Todos'*/'@/pages/Todos')
}
]
})
4、main.js
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store/index'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
store,
components: { App },
template: '<App/>'
})
5、package.json
{
"name": "my-vuex-project",
"version": "1.0.0",
"description": "A Vue.js project",
"author": "xan <[email protected]>",
"private": true,
"scripts": {
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"start": "npm run dev",
"lint": "eslint --ext .js,.vue src",
"build": "node build/build.js"
},
"dependencies": {
"vue": "^2.5.2",
"vue-router": "^3.0.1",
"vuex": "^3.6.2"
},
"devDependencies": {
"autoprefixer": "^7.1.2",
"babel-core": "^6.22.1",
"babel-eslint": "^8.2.1",
"babel-helper-vue-jsx-merge-props": "^2.0.3",
"babel-loader": "^7.1.1",
"babel-plugin-syntax-jsx": "^6.18.0",
"babel-plugin-transform-runtime": "^6.22.0",
"babel-plugin-transform-vue-jsx": "^3.5.0",
"babel-preset-env": "^1.3.2",
"babel-preset-stage-2": "^6.22.0",
"chalk": "^2.0.1",
"copy-webpack-plugin": "^4.0.1",
"css-loader": "^0.28.0",
"eslint": "^4.15.0",
"eslint-config-standard": "^10.2.1",
"eslint-friendly-formatter": "^3.0.0",
"eslint-loader": "^1.7.1",
"eslint-plugin-import": "^2.7.0",
"eslint-plugin-node": "^5.2.0",
"eslint-plugin-promise": "^3.4.0",
"eslint-plugin-standard": "^3.0.1",
"eslint-plugin-vue": "^4.0.0",
"extract-text-webpack-plugin": "^3.0.0",
"file-loader": "^1.1.4",
"friendly-errors-webpack-plugin": "^1.6.1",
"html-webpack-plugin": "^2.30.1",
"node-notifier": "^5.1.2",
"optimize-css-assets-webpack-plugin": "^3.2.0",
"ora": "^1.2.0",
"portfinder": "^1.0.13",
"postcss-import": "^11.0.0",
"postcss-loader": "^2.0.8",
"postcss-url": "^7.2.1",
"rimraf": "^2.6.0",
"semver": "^5.3.0",
"shelljs": "^0.7.6",
"uglifyjs-webpack-plugin": "^1.1.1",
"url-loader": "^0.5.8",
"vue-loader": "^13.3.0",
"vue-style-loader": "^3.0.1",
"vue-template-compiler": "^2.5.2",
"webpack": "^3.6.0",
"webpack-bundle-analyzer": "^2.9.0",
"webpack-dev-server": "^2.9.1",
"webpack-merge": "^4.1.0"
},
"engines": {
"node": ">= 6.0.0",
"npm": ">= 3.0.0"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}