zoukankan      html  css  js  c++  java
  • Vue实战系列(一)

    1. 创建项目骨架

    # 1. 利用Vue-CLI创建项目
    vue create vue-login
    
    #2. 添加依赖框架
    
    # 进入到项目根目录
    cd vue-login
    
    # 添加 element,一个 element 风格的 UI 框架
    vue add element
    
    # 安装 axios,用于网络请求
    npm install axios
    
    # 安装 Vuex,用于管理状态
    npm install vuex --save
    
    # 安装 路由,用于实现两个 Vue 页面的跳转
    npm install vue-router
    2. 创建相应功能的目录结构,进行分层开发

    - api (网络请求接口包)
    - router (路由配置包)
    - store (Vuex 状态管理包)
    - utils (工具包)
    - views (vue 视图包,存放所有 vue 代码,可根据功能模块进行相应分包)
    3. 运行项目
    npm run serve
    
    在浏览器输入:http://localhost:8080/

     4. View 层代码编写

    编写三个 vue 文件:
    login.vue(登录页面)
    success.vue(登录成功页面)
    error.vue(登录失败页面)

    login.vue

    <template>
      <div>
        <el-card class="login-form-layout">
          <el-form
            autocomplete="on"
            :model="loginForm"
            ref="loginForm"
            label-position="left"
          >
            <div style="text-align: center">
              <svg-icon icon-class="login-mall" style=" 56px;height: 56px;color: #409EFF"></svg-icon>
            </div>
            <h2 class="login-title color-main">登录页面</h2>
            <el-form-item prop="username">
              <el-input
                name="username"
                type="text"
                v-model="loginForm.username"
                autocomplete="on"
                placeholder="请输入用户名"
              >
                <span slot="prefix">
                  <svg-icon icon-class="user" class="color-main"></svg-icon>
                </span>
              </el-input>
            </el-form-item>
            <el-form-item prop="password">
              <el-input
                name="password"
                :type="pwdType"
                @keyup.enter.native="handleLogin"
                v-model="loginForm.password"
                autocomplete="on"
                placeholder="请输入密码"
              >
                <span slot="prefix">
                  <svg-icon icon-class="password" class="color-main"></svg-icon>
                </span>
                <span slot="suffix" @click="showPwd">
                  <svg-icon icon-class="eye" class="color-main"></svg-icon>
                </span>
              </el-input>
            </el-form-item>
            <el-form-item style="margin-bottom: 60px">
              <el-button
                style=" 100%"
                type="primary"
                :loading="loading"
                @click.native.prevent="handleLogin"
              >登录</el-button>
            </el-form-item>
          </el-form>
        </el-card>
      </div>
    </template>
    
    <script>
    export default {
      name: "login",
      data() {
        return {
          loginForm: {
            username: "admin",
            password: "123456"
          },
          loading: false,
          pwdType: "password",
        };
      },
      methods: {
        showPwd() {
          if (this.pwdType === "password") {
            this.pwdType = "";
          } else {
            this.pwdType = "password";
          }
        },
        handleLogin() {
          this.$refs.loginForm.validate(valid => {
            if (valid) {
              this.loading = true;
              this.$store
                .dispatch("Login", this.loginForm)
                .then(response => {
                  this.loading = false;
                  let code = response.data.code;
                  if (code == 200) {
                    this.$router.push({
                      path: "/success",
                      query: { data: response.data.data }
                    });
                  } else {
                    this.$router.push({
                      path: "/error",
                      query: { message: response.data.message }
                    });
                  }
                })
                .catch(() => {
                  this.loading = false;
                });
            } else {
              // eslint-disable-next-line no-console
              console.log("参数验证不合法!");
              return false;
            }
          });
        }
      }
    };
    </script>
    
    <style scoped>
    .login-form-layout {
      position: absolute;
      left: 0;
      right: 0;
      width: 360px;
      margin: 140px auto;
      border-top: 10px solid #409eff;
    }
    
    .login-title {
      text-align: center;
    }
    
    .login-center-layout {
      background: #409eff;
      width: auto;
      height: auto;
      max-width: 100%;
      max-height: 100%;
      margin-top: 200px;
    }
    </style>

    success.vue

    <template>
      <div>
        <h1>Welcome!{{msg}}</h1>
      </div>
    </template>
    <script>
    export default {
      data() {
        return {
          msg: this.$route.query.data
        };
      },
    //   data() { //这种方式也可以
    //     return {
    //       msg: null
    //     };
    //   },
      // created() {
      //   this.msg = this.$route.query.data;
      // }
    }
    </script>

    error.vue

    <template>
      <div>
        <h1>登录错误:{{msg}}</h1>
      </div>
    </template>
    <script>
    export default {
      // data() {
      //   return {
      //     msg: this.$route.query.data
      //   };
      // }, //使用这种方式也可以显示 msg
      data() {
        return {
          msg: null
        };
      },
      created() {
        this.msg = this.$route.query.message;
      }
    };
    5. 路由

    页面写好了,我们需要依次显示这三个页面,这里我们统一使用路由来管理显示页面。

         5-1) 创建路由配置文件

         在router 文件夹下创建一个 index.js 文件,内容如下:

    import Vue from 'vue' //引入 Vue
    import VueRouter from 'vue-router' //引入 Vue 路由
    
    Vue.use(VueRouter); //安装插件
    
    export const constantRouterMap = [
        //配置默认的路径,默认显示登录页
        { path: '/', component: () => import('@/views/login')},
    
        //配置登录成功页面,使用时需要使用 path 路径来实现跳转
        { path: '/success', component: () => import('@/views/success')},
    
        //配置登录失败页面,使用时需要使用 path 路径来实现跳转
        { path: '/error', component: () => import('@/views/error'), hidden: true }
    ]
    
    export default new VueRouter({
        // mode: 'history', //后端支持可开
        scrollBehavior: () => ({ y: 0 }),
        routes: constantRouterMap //指定路由列表
    5-2) 将路由添加到程序入口

    路由配置文件写好,我们需要把他引入到 main.js 中。
    在项目的 src 目录根节点下,找到 main.js。

    import Vue from 'vue'
    import App from './App.vue'
    import './plugins/element.js'
    import router from './router' //引入路由配置
     
    Vue.config.productionTip = false
     
    new Vue({
      render: h => h(App),
      router, //使用路由配置
    }).$mount('#app')
    5-3) 配置路由的出入口

    现在路由已经完全引入到项目了,但是路由还需要一个出入口,
    这个出入口用来告诉路由将路由的内容显示在这里。

    修改 App.vue 内容如下:
    <template>
      <div id="app">
        <!-- 路由的出入口,路由的内容将被显示在这里 -->
        <router-view/>
      </div>
    </template>
     
    <script>
      export default {
        name: 'App'
      }
    </script>
    现在运行程序, 界面如下:

    5-4) 路由跳转

    this.$router.push({path: "路径"})
    在 login.vue 中可以使用 this.$router.push({path: "路径"}) 来跳转到指定路径的路由组件中,
    
    路由跳转核心代码如下:
    this.$router.push({path: "/success"}); //跳转到成功页
    
    this.$router.push({path: "/error"}); //跳转到失败页

    完整代码如下
    login.vue

    handleLogin() {
      this.$refs.loginForm.validate(valid => {
        if (valid) {
          this.loading = true;
          this.$store
            .dispatch("Login", this.loginForm)
            .then(response => {
              this.loading = false;
              let code = response.data.code;
              if (code == 200) {
                this.$router.push({
                  path: "/success",
                  query: { data: response.data.data }
                });
              } else {
                this.$router.push({
                  path: "/error",
                  query: { message: response.data.message }
                });
              }
            })
            .catch(() => {
              this.loading = false;
            });
        } else {
          // eslint-disable-next-line no-console
          console.log("参数验证不合法!");
          return false;
        }
      });
    }

    6. 使用 Vuex + Axios 方式进行网络请求

    6-1) 利用Axios封装请求

    axios 是一个网络请求构架,官方推荐使用这种方式进行 http 的请求。

    a) 在 utils 包下封装一个请求工具类 request.js
    import axios from 'axios' //引入 axios
    import baseUrl from '../api/baseUrl' //使用环境变量 + 模式的方式定义基础URL
     
    // 创建 axios 实例
    const service = axios.create({
      baseURL: baseUrl, // api 的 base_url
      timeout: 15000, // 请求超时时间
    })
     
    export default service

     注: 这里的 baseUrl 涉及 Vue CLI3 的环境变量与模式的概念,见:Vue 环境变量和模式(设置通用baseUrl)

    b) 登录请求接口 API

    在 api 文件夹下,创建一个登录API文件
    login.js
    import request from '@/utils/request' //引入封装好的 axios 请求
     
    export function login(username, password) { //登录接口
      return request({ //使用封装好的 axios 进行网络请求
        url: '/admin/login',
        method: 'post',
        data: { //提交的数据
          username,
          password
        }
      })
    }
    
    
    6-2) 使用 Vuex 封装 axios

    Vuex 是一个状态管理构架。

    a)封装 Vuex 中的 module

    在 store 文件夹下创建一个 modules 文件夹,然后在此文件夹下创建一个 user.js 文件
    import { login } from '@/api/login'//引入登录 api 接口
     
    const user = {
      actions: {
        // 登录
        Login({ commit }, userInfo) { //定义 Login 方法,在组件中使用 this.$store.dispatch("Login") 调用
          const username = userInfo.username.trim()
          return new Promise((resolve, reject) => { //封装一个 Promise
            login(username, userInfo.password).then(response => { //使用 login 接口进行网络请求
              commit('') //提交一个 mutation,通知状态改变
              resolve(response) //将结果封装进 Promise
            }).catch(error => {
              reject(error)
            })
          })
        },
      }
    }
    export default user

    上面的代码值得解释一下:

    1. 引接口 
    引入 login 接口,之后使用登录接口进行网络请求。
    
    2. 定义action 
    定义一个 名为 Login 的 action 方法,方便Vue 组件通过 this.$store.dispatch("Login") 调用。
    
    3. 封装Promise
    Promise,这个类很有意思,官方的解释是“store.dispatch 可以处理被触发的 action 的处理函数返回的 Promise,
    并且 store.dispatch 仍旧返回 Promise”。
    这话的意思组件中的 dispatch 返回的仍是一个 Promise 类。
    因此Promise 中的两个方法 resolve() 与 reject() 分别对应 dispatch 中的 then 与 catch
    b) 创建 Vuex

    在 store 文件夹下创建一个 index.js 文件
    import Vue from 'vue' //引入 Vue
    import Vuex from 'vuex' //引入 Vuex
    import user from './modules/user' //引入 user module
     
    Vue.use(Vuex)
     
    const store = new Vuex.Store({
      modules: {
        user //使用 user.js 中的 action
      }
    })
     
    export default store

    c) 将 Vuex 添加到 main.js 文件

    修改之前的 main.js 文件如下:

    import Vue from 'vue'
    import App from './App.vue'
    import './plugins/element.js'
    import router from './router' //引入路由配置
    import store from './store' //引入 Vuex 状态管理
     
    Vue.config.productionTip = false
     
    new Vue({
      render: h => h(App),
      router, //使用路由配置
      store //使用 Vuex 进行状态管理
    }).$mount('#app')

    7. 服务端接口

    由于这是一篇主要讲Vue的文章, 所以服务端接口这里我就一笔带过了。

    可以写一个简易的不带数据库的登录接口(Java)如下:

    @RestController
    public class LoginController {
     
        @RequestMapping(value = "/admin/login", method = RequestMethod.POST)
        public CommonResult login(@RequestBody User user) {
            if (user.getUsername().equals("admin") && user.getPassword().equals("123456"))
                return CommonResult.success("admin");
            else
                return CommonResult.validateFailed();
        }
    }

    再次访问页面, 效果如下:

    登录成功

    登录失败

    技术改变世界
  • 相关阅读:
    为什么使用CWinApp类编译以后的文件会比CWinAppEx类小呢?
    遇到问题——IntelliSense: #error directive: Please use the /MD switch for _AFXDLL builds
    理解C++中复杂的指针声明
    运行没有错,但是窗口没有显示出来——Windows编程中的CreateWindow返回值为空?
    错误argument of type "char *" is incompatible with parameter of type "LPCWSTR"的解决方法
    游戏坐标和窗口坐标的变换公式
    一路风雨走过来:那些我亲密接触过的项目
    10 Fun Things to do with Tessellation
    irrlicht引擎:中文支持
    魔兽世界客户端数据研究(一)
  • 原文地址:https://www.cnblogs.com/davidgu/p/14652544.html
Copyright © 2011-2022 走看看