2020年08月11日 20:44
原创作品,转载时请务必以超链接形式标明文章原始出处,否则将追究法律责任。

上一节大概看了下VUE的入门,本节我们来做一个查询的demo。在写博客前我总是要给大家展示一下风景照。虽然是加载比较慢,但是也是为了让大家大饱眼福。蓝田九间房万亩荷花了解一下。

image.png

其实之前在写Anuglar7实战的时候,我们把饭店会员管理系统的主页进行了搭建,本节我们主要是搭建一个VUE的主页,还是那句话,无图无真相,先看图。

image.png


首先我们要确定我们要使用的组件,对于VUE,我之前项目中用过element,所以本篇文章我们所有控件都使用element。要使用element,得先安装element,在项目目录下面,直接npm install element-ui。

接下来我们先看一下项目结构

image.png

我们将一些css文件,bootstrap,部分图片等放到了static下面。这里的入口文件就是main.js

import Vue from 'vue'
import App from './App'
import router from './router'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import axios from 'axios'
import VueAxios from 'vue-axios'

Vue.config.productionTip = false
Vue.use(ElementUI)
Vue.use(VueAxios, axios)

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>'
})

这里我们主要是引入了element-ui组件,方便我们后面所有的component使用。这里设置了VUE默认加载的组件,即App.vue组件,将其渲染到index.html页面中的id为app的div中。看一下html页面,引入了css文件以及js文件。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
  <title>饭店会员管理系统</title>
  <link rel="stylesheet" href="./static/bootstrap/bootstrap.min.css" />
  <link rel="stylesheet" href="./static/bootstrap/bootstrap-theme.min.css" />
  <link rel="stylesheet" href="./static/messager/css/messenger.css" />
  <link rel="stylesheet" href="./static/messager/css/messenger-theme-flat.css" />
  <link rel="stylesheet" href="./static/css/Site.css" />
  <script type="text/javascript" src="./static/jquery/jquery-3.3.1.min.js"></script>
  <script type="text/javascript" src="./static/bootstrap/bootstrap.min.js"></script>
  <script type="text/javascript" src="./static/jquery/jquery-3.3.1.min.js"></script>
  <script type="text/javascript" src="./static/messager/js/messenger.min.js"></script>
  <script type="text/javascript" src="./static/messager/js/messenger-theme-flat.js"></script>
  <script type="text/javascript" src="./static/messager/js/messagebox.js"></script>
</head>
  <body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

在main.js中也引入了路由配置router,看一下代码

import Vue from 'vue'
import Router from 'vue-router'
import Default from '@/components/default'
import Customer from '@/components/customer';

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'default',
      component: Default
    },
    {
      path: '/customer',
      name: 'customer',
      component: Customer
    }
  ]
})

在这里我们定义了两个路由,一个默认路由,一个展示customer的页面。

image.png

对于default,没什么说的,这里我放了一个空页面。我们主要是是看一下App.vue这个入口component。它的模板部分如下

<template>
  <div id="app">
    <div class="main">
      <header>
        <div class="col-md-12">
          <div class="col-md-5 website-title" style="text-align: left">
            <img src="./assets/Images/member.png" width="50" height="50" />
            <a href="" style="color:white">饭店会员管理系统</a>
          </div>
          <div id="logout" class="col-md-7" style="text-align: right; font-size: large">
            <img id="img_UserPhoto" class="round-image" src="./assets/Images/users.jpg" />
            <span style="margin-right: 10px">
              当前用户:{{currentUser}}
              <span style="color: white;margin-right:10px"></span>
            </span>
            <span id="currentTime">{{dateNow}}</span>&nbsp;&nbsp;
            <a href="javascript:void(0)">注销</a>
          </div>
        </div>
      </header>
      <div class="row">
        <div class="col-md-2">
          <div class="panel-group margin-t10" id="accordion">
            <div class="panel panel-primary" id="div_User" runat="server">
              <div class="panel-heading">
                <h4 class="panel-title">
                  <a data-toggle="collapse" data-parent="#accordion"
                     href="#collapseOne">
                    <b>会员信息</b>
                  </a>
                </h4>
              </div>
              <div id="collapseOne" class="panel-collapse collapse in">
                <div class="panel-body">
                  <ul class="navigation-ul">
                    <li class="span-nav">
                      <img src="./assets/Images/menu/member.png" />
                      <a routerLink="/app-customer/create">新增会员</a>
                    </li>
                    <li class="span-nav">
                      <img src="./assets/Images/menu/members.png" />
                      <router-link :to="{path: 'customer', query: {color: 'red' }}">会员管理</router-link>
                    </li>
                  </ul>
                </div>
              </div>
            </div>
            <div class="panel panel-primary" id="div_User" runat="server">
              <div class="panel-heading">
                <h4 class="panel-title">
                  <a data-toggle="collapse" data-parent="#accordion"
                     href="#collapseOne">
                    <b>消费充值</b>
                  </a>
                </h4>
              </div>
              <div id="collapseOne" class="panel-collapse collapse in">
                <div class="panel-body">
                  <ul class="navigation-ul">
                    <li class="span-nav">
                      <img src="./assets/Images/menu/consume.png" />
                      <a href="">消费结算</a>
                    </li>
                    <li class="span-nav">
                      <img src="./assets/Images/menu/money.png" />
                      <a href="">充值记录</a>
                    </li>
                    <li class="span-nav">
                      <img src="./assets/Images/menu/cash.png" />
                      <a href="">消费记录</a>
                    </li>
                  </ul>
                </div>
              </div>
            </div>
          </div>
        </div>
        <div class="col-md-10">
          <router-view></router-view>
        </div>
      </div>
    </div>
  </div>
</template>

上面的部分主要是页头和左侧导航,右边是一个router-view,这个东西其实就是一个插槽,类似于angular的 <router-outlet>。当我们点击导航的时候,会根据路由表找到对应的组件,然后加载到插槽部分。

<script>
  import moment from 'moment'
  export default {
    name: 'HelloWorld',
    data() {
      return {
        dateNow: moment(new Date()).format("YYYY-MM-DD HH:mm:ss"),
        currentUser: "李磊"
      }
    },
    created() {
      setInterval(() => { this.setCurrentTime() }, 1000);
    },
    methods: {
      setCurrentTime: function () {
        this.dateNow = moment(new Date()).format("YYYY-MM-DD HH:mm:ss");
      }
    }
  }
</script>

jsx部分呢,其实很简单,主要是展示一个时间。VUE有一些生命周期钩子,这里我不再赘述,借用网上的一张图。

d0c8a786c9177f3e668177cd4bfcf9c19e3d5676.png

在这里我们使用到了created,在created function中我们每隔1s刷新一下当前页面头部的时间。ok接下来我们再看一下页面customer.vue。

<template>
  <div id="customer" class="margin-t10">
    <div class="panel panel-primary">
      <div class="panel-heading">
        <h3 class="panel-title">
          <label>会员管理</label>
        </h3>
      </div>
      <div class="panel-content padding-5">
        <div class="row">
          <label class="col-md-1">用户名:</label>
          <div class="col-md-3">
            <el-input v-model="query.userNo" size="small" placeholder=""></el-input>
          </div>
          <label class="col-md-1">姓名:</label>
          <div class="col-md-2">
            <el-input v-model="query.userName" size="small" placeholder=""></el-input>
          </div>
          <label class="col-md-1">性别:</label>
          <div class="col-md-2">
            <el-select v-model="query.sex" size="small" placeholder="请选择">
              <el-option v-for="item in sexList"
                         :key="item.value"
                         :label="item.label"
                         :value="item.value">
              </el-option>
            </el-select>
          </div>
          <div class="col-md-1">
            <el-button type="primary" icon="el-icon-search" size="small" :loading="loading" @click="queryCustomer">查询</el-button>
          </div>
          <div class="col-md-12">
            <div id="customerlist" class="margin-t10">
              <el-table :data="customerList.dataList">
                <el-table-column prop="UserNo"
                                 label="用户名"
                                 width="180">
                </el-table-column>
                <el-table-column prop="Name"
                                 label="姓名"
                                 width="180">
                </el-table-column>
                <el-table-column prop="Sex"
                                 label="性别"
                                 width="180">
                  <template slot-scope="scope">
                    <p>{{ scope.row.Sex=='1'? '男':'女' }}</p>
                  </template>
                </el-table-column>
                <el-table-column prop="ParentCustomerName"
                                 label="推荐人"
                                 width="180">
                </el-table-column>
                <el-table-column prop="Amount"
                                 label="余额"
                                 width="90">
                </el-table-column>
                <el-table-column prop="InDate"
                                 label="创建日期">
                </el-table-column>
              </el-table>
              <el-pagination background
                             layout="prev, pager, next"
                             :total="customerList.total"
                             :page-size="pageSize"
                             :page-sizes="[5, 10, 20, 50]"
                             @current-change="pageIndexChanged"
                             :current-page="currentPageIndex">
              </el-pagination>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

三个查询条件,用户名,姓名,性别,分别双向绑定。button和table我们均采用element-ui组件。element-ui组件非常丰富,也非常好用,不管你是开发angular,react,还是vue都是一个很好的选择,说明文档很详细 https://element.eleme.cn/#/zh-CN/component/table

ok,就这样一个简单的查询页面就写完了,接下来我们再看一下jsx部分。

<script>
  import axios from 'axios'
  export default {
    name: 'customer',
    data() {
      return {
        query: {
          userNo: '',
          userName: '',
          sex: null
        },
        client_id: 'XXXXXX',
        tokenUrl: '/token',
        baseUrl: 'http://localhost:8008',
        customerList: {
          dataList: [],
          total: 0
        },
        currentPageIndex: 0,
        pageSize: 5,
        accessToken: '',
        sexList: [{
          label: '男',
          value: '1'
        }, {
          label: '女',
          value: '0'
        }],
        loading: false
      }
    },
    created() {
      if (!this.accessToken) {
        let request = {
          username: "190xxxxxx",
          password: '111333'
        };
        this.getOAuthToken(request);
      }
    },
    methods: {
      pageIndexChanged: function ($event) {
        this.currentPageIndex = $event;
        this.queryCustomer();
      },
      queryCustomer: function () {
        this.loading = true;
        var queryUrl = this.baseUrl.concat('/api/customer/list?pageindex=' + this.currentPageIndex + '&pageSize=' + this.pageSize);
        if (this.query.userNo) {
          queryUrl += '&userno=' + this.query.userNo;
        }

        if (this.query.userName) {
          queryUrl += '&userno=' + this.query.userName;
        }

        if (this.query.sex) {
          queryUrl += '&sex=' + this.query.sex;
        }

        axios.get(queryUrl,
          { headers: { 'Authorization': `bearer ${this.accessToken}` } }).then((response) => {
            this.customerList.dataList = response.data.CustomerList;
            this.customerList.total = response.data.TotalCount;
            this.loading = false;
          });
      },
      getOAuthToken(request) {
        let body = `username=${request.username}&password=${request.password}&grant_type=password&client_id=${this.client_id}`;
        var requestUrl = this.baseUrl.concat(this.tokenUrl);
        axios.post(requestUrl, body, {
          headers: {
            'content-type': 'application/x-www-form-urlencoded'
          }
        }).then((response) => {
          this.accessToken = response.data.access_token;
          console.log(this.accessToken);
        });
      }
    }
  }</script>

在这里我们要请求api,就必须要使用异步ajax请求的组件,在这里我们选择了axios,这个组件有什么特点呢

  • 支持浏览器和node.js

  • 支持promise

  • 拦截请求和响应

  • 能转换请求和响应数据

  • 取消请求

  • 自动转换JSON数据

  • 浏览器端支持防止CSRF(跨站请求伪造)

文档:http://www.axios-js.com/docs/

看起来还是很不错的,因为我们的api是需要oauth权限认证的,所以需要先请求一下token api,得到access_token,然后拿着token再去请求api。

然后是支持一下分页,

image.png

ok,今天就到这里,感谢每一位关注本站的同志。



发表评论
匿名  
用户评论
暂无评论