Vue 之 Vuex 使用 vuex 实现一个todo 列表的简单实例

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"
  ]
}

猜你喜欢

转载自blog.csdn.net/u014361280/article/details/125773678