# vue-adonis-todo **Repository Path**: CC3688/vue-adonis-todo ## Basic Information - **Project Name**: vue-adonis-todo - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2018-12-03 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # vue-adonis-todo ## 项目介绍 使用 node adonis框架(与php laravel框架比较相似) 做后台api开发 使用 vue 做spa 的一个 todo小demo ## 项目 运行效果图 ![](./iamges/vuetodo01.png) ![](./iamges/vuetodo02.png) ![](./iamges/vueto03.png) ![](./iamges/vueto04.png) ![](./iamges/vueto05.png) ## 项目收获 小结 ### VUEX #### 1 Vuex 是采用集中式状态管理的解决方案,让我们能够规范且高效的管理和调试应用的状态 #### 2 store 是Vuex 的核心元素,是一个特殊的对象, 它包含如下信息 > - state: 存储应用状态的响应式数据对象 > - getter: 等价于store的计算属性 > - mutation: 用于改变应用的状态的函数 > - action: 通常用来调试异步api的函数,然后mutation改变的数据 #### 3 使用 安装 npm i -S vuex 创建 一个store 文件夹,并在里面创建 index.js 一般应用 都会启用模块化, 一个模块一个文件,然后再一起导入到index.js ``` //index.js import Vue from 'vue' import Vuex from 'vuex' import tasks from './tasks' //.js后缀可省略 Vue.use(Vuex) const store = new Vuex.Store({ strict: true //严格模式, 不要在生产环境中使用,是为了防止mutation中使用异步调用 modules: { tasks, }, }) export default store ``` ``` //tasks.js export default { namespaced: true, state(){ //Vuex的一个重要的原则,就是state是只读的,不能直接修改,只能通过mutation改 return { //像vue实例里的data:{} 一般也写成一个函数 data(){return {}} tasks: [], //在各组件中,很少直接使用state数据, 而是使用getters } }, //action并不直接修改状态.它不仅可以提交mutation,还能异步操作 //action的处理函数,不能直接调用,需要使用dispath //dispath('action-type', palyloadObject) //所以每个action 都接收两个参数, context(store对象内的各个属性都有),payload //通过对象的解构来获取需要的实参 actions: { fetchTasksForProject({ commit }, project) { return HTTP().get(`projects/${project.id}/tasks`) .then(({ data }) => { commit('setTasks', data); }); }, }, getters: { //建议总是使用getter,它可以让你在修改获取数据的方式时无须修改使用此 tasks: state => state.tasks //数据的组件 (你改变了state的结构和相应的getter,同时不对组件产生任何 }, //影响) mutations: { setTasks(state, tasks) { state.tasks = tasks; }, }; ``` ``` //main.js import store from './sotre' //它会自己找到index.js ,这个名字的文件,会被默认找到. new Vue({ ...App, el:'#app', router, store, //像router 一样需要注入,后才能使用 (this.$router) }) // 在组件中,可以使用this.$store 访问 ``` **辅助函数** Vuex提供了一系列辅助函数供添加state, getter, mutation及action, 出于将组件中的状态和逻辑分离的考虑,可以只使用getter 和 action 使用辅助函数,可以不用每次都使用 this.$store.getters this.\$store.dispatch 注意到,我们上文是开启了命名空间: 应该这样写 this.$store.getters['tasks/tasks'] 辅助函数的参数类型,可以是数组 或 对象 ``` mapGetters(['a','b']) //它等价于 { a(){ return this.$store.getters.a}, b(){ return this.$store.getters.b} } mapGetter({x: 'a', 'y':b}) //等价于 { x(){ return this.$store.getters.a}, y(){ return this.$store.getters.b}, } 在组件中, 注意, 可以在 参数前加多一个字符串参数, 传入命名空间. computed:mapGetters(['a,b]), methods:mapActions({x:'a',y:'b'}) 一般很少这样,应该可能还有其它需要加入 都是 computed:{ ...mapGetters(...), //... 是es6的新语法, 把它对像展开,合并进去. 其它的... } ``` ``` //在tasks.vue 组件 //和getter类似,在组件中我们应该部是使用action,而不是mutation //因为当需要更新迭代时,修改action中的代码比修改组件中的代码来得更好 //第一种: import {mapGetter, mapActions} from 'vuex' { ... computed:{ ...mapGetter([命名空间字符串,没起用可以不传],[ 'tasks', ]), ... //要重起拿就用{}参数 }, methods:{ ...mapActions([命名空间字符串,没起用可以不传],[ 'tasks', ]), } } //第二种: import { createNamespacedHelpers } from 'vuex' // const { mapGetters, mapActions} = createNamespacedHelpers('tasks') 这种实践并不好, 多模块就重名 const { mapGetters: tasksGetter, mapActions: tasksActions, } = createNamespacedHelpers('tasks') //重命带命名空间的辅助函数是个好实践,可避免将来与其它模块重名 { ... computed:{ ...tasksGetter([ 'tasks' ]), }, methods:{ ...tasksActions([ 'tasks', ]), } } ``` #### 4 vuex持久化插件 -- 解决刷新数据消失的问题 > vuex可以进行全局的状态管理,但刷新后刷新后数据会消失,也可以通过插件-**vuex-persistedstate**解决 > > 你也可以自己结合本地存储做到数据持久化, 使用 - 安装 npm i -S vuex-persistedstate - 在store下的index.js 引入 - ``` import createPersistedState from "vuex-persistedstate" const store = new Vuex.Store({ // ... plugins: [createPersistedState()] }) ``` - 默认是存储到localStorage,如果想存储到sessionStorage, 需要传入参数 ``` import createPersistedState from "vuex-persistedstate" const store = new Vuex.Store({ // ... plugins: [createPersistedState({ storage: window.sessionStorage, })] }) ``` #### 5 **vuex-router-sync** 这是一个把 store和router连接起来的工具, 可以在vuex中的action中处理路由的跳转. 它将当前路由暴露到state(state.route)中, 同时在每次路由改变时都提交一个mutation ``` //main.js import { sync } from 'vuex-router-sync' import store from './vuex/store' // vuex store instance import router from './router' // vue-router instance const unsync = sync(store, router) // 反回一个 卸载函数, 存在常量unsync里 // sync(store, router, { moduleName: 'RouteModule' } ) 上面也可以这样,传入模块名 // bootstrap your app... unsync() // 取消store router 的同步 ``` ``` //在你的 store 就可以使用 route相关了 store.state.route.path // current path (string) store.state.route.params // current params (object) store.state.route.query // current query (object) 注意不能直接赋值 更改路由 便可以, $rotuer.push() $router.go() $router.push({query:{...}}) ``` #### 6 axois 支持Promise 可以先创建一个实例, 把一些公共的东西先设置好 ``` //http.js //把公共的配置写在 vuex 里 import axios from 'axios'; import store from './store/'; export default () => { return axios.create({ baseURL: store.state.baseURL, //基础路径 timeout: 5000, //设置超时 headers: { //设置权限认证的方式, 采用模板字符串 Authorization: `Bearer ${store.state.authentication.token}`, }, }); }; ``` ``` //使用, 先导入 //tasks.js import HTTP from '../http'; //get HTTP().get(`project/${project.id}/tasks`) .then(({data})=>{ }) .catch(()=>{ }) //delete HTTP().delete(`....`) .then(()=>{ }) .catch(()=>{ }) //pathch HTTP().patch(`....`) .then(()=>{ }) .catch(()=>{ }) //post HTTP().post('url', { 字段名:值 }).then(({data})=>{ }) .catch(()=>{ }) ``` #### 访问全局元素 可以在全名空间模块的getter中访问到根状态 和 根 getter(即所有的getter) ``` someGetter:(state, getters, rootState, rootGetters) => { } ``` 在action中, 你可以访问下下文的 rootGetters, 同进, 还可以在 commit 和 dispatch 调用中使用{ root: true } ``` myAction({ dispathc, commit, getters, rootGetters}){ getters.a //store.getters['当前模块'/a] rootGetters.a //store.getters['a'] 根下的a commit('someMutation') //当前模块下的/someMutation commit(''someMutation', null, {root: true}) //根的 'someMutation' dispatch('someAction') //当前模块下的someAction dispatch('someAction', null, {root: true}) //根的 'someAction' } ``` --- ## 运行 指南 1. 把代码克隆 到本地 2. cd 进入 client 运行 npm install , 完成安装后 , npm run serve 3. cd 进入server 运行 npm install 4. 复制 .env.example 一份(相同目录下), 并改名为.env, 然后,打开,填入你的数据信息 5. npm start