Vuexms项目文档

1.起步

1.1.前言

这篇文档是跟随腾讯课堂课程:前端教程vuex实现管理系统,给自己写的课堂随笔,仅作记录作用。建议先去vuex官网了解一些基本知识再开始。

本文档可能会出现数据对不上的问题,原因是视频中有不断更改数据,所以后面会对之前的数据库或者页面元素作出调整。然后我自己尝试解决了部分工具版本上的问题,很多地方记录的不详尽,推荐看视频。

主要用到的工具/包有:vue, vuex, npm, nodemon, mysql, element-ui, axios

1.2.初始化项目

  1. 打开项目位置文件夹,在地址栏输入cmd打开当前目录的控制台,输入以下代码:

    vue init webpack vuexms
    
    控制台显示图
  2. 继续在控制台输入指令以安装相关包:

    cd vuexms
    npm i
    
    初始完成的文件目录
  3. 试着运行我们的初始项目:

    npm run dev
    
    显示

控制台表明我们的项目运行在了http://localhost:8080,打开就能看到默认的初始界面。

1.3.个性化

  • 打开vuexms\src\App.vue,这是我们项目的路由出口,同时删掉<template>中的img标签和<style>中的所有内容:
<!-- 这是默认的主页面logo图 -->
<img src="./assets/logo.png"> 
  • 打开vuexms\src\components\HelloWorld.vue,这是路由指示的主界面,删除<template>中的标签。同时,将文件名改为我们需要的login.vue,然后更改src\router\index.js中的相关代码。

    import Vue from 'vue'
    import Router from 'vue-router'
    
    // 引入组件
    import login from '@/components/login'
    
    // 注册路由
    Vue.use(Router)
    
    // 导出路由
    export default new Router({
      routes: [
        {
          path: '/login',
          name: 'login',
          component: login
        }
      ]
    })
    

2.实现登录页

2.1.使用Element

官网地址:Element

  1. 切换回控制台,Ctrl+C暂时停止服务器。

    npm i element-ui -S
    
  2. 找到src目录 下的main.js,添加以下代码

    // 引入
    import ElementUI from 'element-ui';
    import 'element-ui/lib/theme-chalk/index.css';
    
    // 注册
    Vue.use(ElementUI);
    
  3. 测试是否注册成功,在login.vue中加入以下代码,重启服务器:npm run dev,如果页面中正常加载出了按钮表示注册成功。

    <el-button>按钮</el-button>
    

2.2.使用组件

  1. element-ui官网找到合适的表单登录组件,分别将里面的HTML代码和Javascript代码放到对应页面,我们这里是login.vue

  2. 我们会加入css代码让页面更加美观,在这之前应该重置样式来避免一些错误。可以在static中新建css文件夹,然后放入合适的reset.css,然后再在index.html中引入:

    <!-- reset.css -->
    <link rel="stylesheet" href="./static/css/reset.css">
    
  3. 自定义数据和样式。


    登陆窗口

2.3.axios

安装:

npm i axios -S

main.js中引入:

// 引入 axios
import axios from 'axios'
// 挂载到 Vue 的原型上
Vue.prototype.axios = axios

login.vue中检测:

submitForm(formName) {
  this.$refs[formName].validate((valid) => {
    if (valid) {
       // 确认是否能打印出信息   
       console.log(this.axios)
     } else {
       console.log('error submit!!');
       return false;
     }
  });
},

向后台发送数据并得到响应:

this.axios.post('/api/checklogin', {
  username: _this.loginForm.username,
  password: _this.loginForm.password
})
.then(response => {
  console.log('接收后端响应的数据')
})

2.4.express搭建服务器

实现登录,需要从服务器获取数据,所以我用 express 搭建了一个。

  1. 确保全局安装了 express,4.X 后的版本需要安装 express-generator。

    npm install -g express
    npm install -g express-generator
    

    在环境变量中添加 path: <u>C:\Users\admin\AppData\Roaming\npm</u>。

  2. 项目同级目录打开cmd工具:

    express server -e
    cd server
    npm install
    
  3. 打开 server 中的 app.js 添加:

    // 监听端口
    app.listen(888, () => {
      console.log('888端口的服务器已经启动...')
    })
    

    在 server\routes\index.js 中设置:

    // 接收请求
    router.post('/checklogin', (req, res) => {
      // 接收用户名和密码
      let { username, password} = req.body;
      console.log(username, password)
      // 发送响应
      res.send('服务器数据')
    })
    

    因为是跨域请求,在 vuexms\config\index.js 中设置:

    proxyTable: {
      '/api': {
        target: 'http://localhost:888', // 接口的域名
        changeOrigin: true, // 如果是跨域请求,需要配置此项
        pathRewrite: {
          '/api': ''
        }
      }
    }
    
    • 项目控制台重启项目npm run dev

    • 服务器控制台启动服务器node app

    • 打开项目页面,输入帐号密码提交后检查服务器控制台和网页响应数据:

      服务端收到数据
      服务器数据

    至此说明项目和服务器已经联通了,接下来需要比对数据库进行登录验证。

2.5.连接数据库

首先我们需要创建一个数据库,在 计算机 -> 管理 -> 服务 中启动 mysql,新开一个 cmd 控制台窗口:

  1. 连接mysql

    mysql -hlocalhost -uroot -proot
    
  2. 新建数据库

    show databases;
    create database vuexms;
    use vuexms;
    
  3. 新建表

    create table users (
      id int primary key auto_increment,
      username varchar(50),
      password varchar(50),
      realname varchar(50),
      age int,
      idType varchar(50)
    );
    desc users;
    
  4. 插入数据

    insert into users(username, password, realname, age, idType) value('xiaoyao', '123456', '李逍遥', '20', '00001');
    insert into users(username, password, realname, age, idType) value('linger', '123456', '赵灵儿', '18', '00002');
    select * from users;
    

然后通过 node 连接数据库:

  1. 在服务器控制台安装mysql包

    npm i mysql -S
    
  2. 在 server\routes 路径下新建 conn.js 文件:

    // 引入mysql
    var mysql = require('mysql')
    
    // 创建连接
    var connection = mysql.createConnection({
      host     : 'localhost',
      user     : 'root',
      password : '123456',
      database : 'vuexms'
    });
    
    // 暴露出去
    module.exports = connection
    
  3. 在同路径的 index.js 中:

    // 引入连接数据库模块
    const connection = require('./conn')
    
    // 连接数据
    connection.connect(() => {
      console.log('数据库连接成功!')
    })
    
    router.post('/checklogin', (req, res) => {
      ...  
      // 执行sql查询
      const sqlStr = `select * from users where username='${username}' and password='${password}'`
      connection.query(sqlStr, (err, data) => {
        if(err) {
          console.log(err)
        }else {
          res.send(data)
        }
      })
    })
    
  4. 重启服务器,会显示数据库连接成功。提交表单,在 Response 中可以看到发送回来的 data:

    数据库连接成功
    得到数据
  1. 渲染页面,在 login.vue 中

    .then(response => {
      if(response.data.length) {
        console.log('接收后端响应的数据', response.data[0].username)
        _this.$message({
          message: '恭喜你,登录成功!',
          type: 'success'
        })
      }else {
        _this.$message.error('请检查用户名或密码')
      }
    })
    

3.保存登录数据

3.1.vue异步加载组件

继续在 login.vue 中

.then(response => {
  if(...){
    ...
    // 跳转到首页
    _this.$router.push('/index')
  }
  ...
})

那么我们需要在 vuexms\src\components 增加一个页面组件 index.vue

<template>
  <h1>index</h1>
</template>
...

在路由中配置,并将引入的方式改为异步加载

// 引入组件
// import login from '@/components/login'
// import index from '@/components/index'

// 异步加载
const login = () => import('@/components/login')
const index = () => import('@/components/index')

export default new Router({
  routes: [
    ...
    {
      path: '/',
      name: 'index',
      component: index
    }
  ]
})

3.2存入登录用户数据

  1. 安装 vuex 包,在项目控制台:

    npm i vuex -S
    
  2. 在 src 目录下新建 vuex 文件夹然后新建 store.js 文件:

    // 引入 vuex
    import Vue from 'vue'
    import Vuex from 'vuex'
    
    // 注册 vue
    Vue.use(Vuex)
    
    // 状态
    const state = {
      userinfo: JSON.parse(localStorage.getItem('userinfo'))
    }
    // mutations 用于操作 state
    const mutations = {
      // 保存用户数据
      SAVE_USERINFO (state, userinfo) {
    
        // 把用户数据放到本地存储实现持久化
        localStorage.setItem('userinfo', JSON.stringify(userinfo))
    
        state.userinfo = userinfo
        console.log('赋值后的用户信息:' , state.userinfo)
      }
    }
    
    // 创建 store 仓库暴露出去
    export default new Vuex.Store({
      state,
      mutations
    })
    
  3. 在 src\main.js 中

    ...
    import store from './vuex/store'
    ...
    new Vue({
      ...
      store,
    })
    
  4. login.vue

    .then(response => {
      if(...){
        ...
        // 把当前用户数据存入 state
        _this.$store.commit('SAVE_USERINFO', response.data[0])
        ...
        _this.$router.push('/')
      }
      ...
    })
    
  5. index.vue 主页调用

    <template>
      ...
        <p>用户信息:{{ $store.state.userinfo }}</p>
      ...
    </template>
    
得到数据

4.主页

4.1.样式

在 element 中选个喜欢的 container 组件样式粘贴到 components\index.vue 组件中,进行修改调整

主页样式

4.2.路由跳转

简单添加几个其余的页面组件,例如:userlist.vue, useradd.vue, passwordedit.vue。重要的是实现路由跳转,而在 element-ui 中有 router 属性可以帮助我们节省步骤。

首先,确定需要进行跳转的样式模块,也就是页面左侧的导航栏,在元素中加入 router 属性:

<el-menu :default-openeds="['1']" router>

然后试着点击导航栏目录,网页地址会加上 el-menu-item 元素的 index 属性的值。

然后,在 router\index.js 中:

// 引入
const home = () => import('@/components/home')
const userlist = () => import('@/components/userlist')
const useradd = () => import('@/components/useradd')
const passwordedit = () => import('@/components/passwordedit')
...
routes: [
  ...
  {
    path: '/',
    redirect: '/home',
    name: 'index',
    component: index,
    children: [
      {
        path: '/home',
        name: 'home',
        component: home
      },        
      {
        path: '/userlist',
        name: 'userlist',
        component: userlist
      },
      {
        path: '/useradd',
        name: 'useradd',
        component: useradd
      },
      {
        path: '/passwordedit',
        name: 'passwordedit',
        component: passwordedit
      },
]

4.3.获取state数据

想要在默认页面得到展示当前用户的一些数据,就要从 state 中获取,vuex 提供了一种更加简单的方式来帮助我们获取到数据,在 components\home.vue 中:

// 引入 mapState
import {mapState} from 'vuex'

export default {
  computed: {
    // 辅助函数 获取 state 数据
    ...mapState({
      // userinfo: this.$store.state.userinfo
      userinfo: state => state.userinfo
    })
  }
}

5.用户列表页

5.1.触发actions异步获取数据

在 vuexms\src\vuex\store.js 中发起请求:

// 引入 axios
import axios from 'axios'
...
const state = {
  ...
  userList: []
}
const mutations = {
  ...
  // 获取全局的用户数据
  GET_USERLIST (state, userList) {
    state.userList = userList
  }
}
// 定义 actions 异步的主要是 commit mutations,由 mutations 来改变状态
const actions = {
  GET_USERLIST({ commit }) {
    // 使用 Promise,其他页面可以通过 .then 的方式来保证页面渲染前得到数据
    return new Promise((resolve, reject) => { 
      axios.get('/api/getuserlist').then(response => {
        // console.log('获取用户数据列表', response.data)
        commit('GET_USERLIST', response.data)
        resolve()
      })
    })
  }
}
export default new Vuex.Store({
  state,
  mutations,
  actions
})

在服务端 server\routes\index.js 响应:

// 接收获取用户列表的请求
router.get('/getuserlist', (req, res) => {
  // 查询数据库 把当前素有用户数据返回给前端
  const sqlStr = 'select * from users'
  connection.query(sqlStr, (err, data) => {
    if(err) {
      throw err
    }else {
      res.send(data)
    }
  })
}) 

检查是否传回数据,在 vuexms\src\components\userlist.vue 中:

created() {
    this.$store.dispatch('GET_USERLIST').then(() => {
    console.log(this.$store.state.userList)
  })
}
拿到数据

5.2.渲染页面

继续操作 userlist.vue 文件:

// 引入辅助函数
import {mapState, mapActions} from 'vuex'

// 删除之前的假数据
data() {
  return {
    tableData: []
  }
},
created() {
  // 以下方式冗长不擅于管理
  // this.$store.dispatch('GET_USERLIST').then(() => {
  //   // console.log(this.$store.state.userList)
  //   // 把全局的 userlist 赋值给 tableData
  //   // this.tableData = this.$store.state.userList
  // })
  this.getUserList().then(() => {
    this.tableData = this.userList
  })
},
methods: {
  ...mapActions({
    getUserList: 'GET_USERLIST'
  }),
},
computed: {
  ...mapState({
    userList: state => state.userList
  })
}
渲染用户列表

5.3.过滤

为了使用 getters 属性,在复制本页面用户列表添加到下方,并改为目标用户表,我们做过滤出年龄大于20岁的用户列表这个操作:

data() {
  return {
    tableData: [],
    newtableData: []
  };
},
created() {
  this.getUserList().then(() => {
    ...
    this.newtableData = this.userList.filter(v => v.age > 20)
  });
}

把需要获取的数据定义成全局的,但是效果不变,在 vuex\store.js 中:

// 定义全局共享属性 getter
const getters = {
  vipUsers: state => state.userList.filter(v => v.age > 20)
}

export default new Vuex.Store({
  ...
  getters
})

回到 userlist.vue 文件:

created() {
  this.getUserList().then(() => {
    ...
    // this.newtableData = this.userList.filter(v => v.age > 20)
    this.newtableData = this.$store.getters.vipUsers
  });
}

使用 mapGetters 辅助函数使编写更简洁:

import { mapState, mapActions, mapGetters} from "vuex";
...
created() {
  this.getUserList().then(() => {
    ...
    this.newtableData = this.vipUsers
  });
}
...
computed: {
  ...mapGetters(['vipUsers']),
  ...
}
目标用户

到此,对 vuex 的重要属性就基本都使用了,也搭好了一个简单的管理系统模板。

我有意将它具化成较详尽的资产管理系统,等完成以后发布出来。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容

  • vue-cli搭建项目 确保安装了node与npm 再目标文件夹下打开终端 执行cnpm i vue-cli -g...
    Akiko_秋子阅读 3,212评论 1 22
  • 封面© / 花瓣网@猴哥MONKI 1 盛夏远去,秋天不知不觉就来了。 都说秋冬是恋爱的季节,很奇怪,西安的秋天今...
    入世新鲜人阅读 270评论 0 0
  • 写一个人物可以用以下几种方法进行选材和构思。 一、一事反映一品质。例如《背影》需要注意:选材,要典型,内容要具体,...
    荷塘恋雨阅读 212评论 0 0
  • 盘古破开蛋壳,分开天地之后,过了大约九万年。天地万物慢慢熟悉了彼此的存在,进入了一个和谐的状态。 这一天,大地之上...
    寻找大蝴蝶阅读 563评论 0 1