Vue项目实战:智慧学成项目

Posted 黑马程序员官方

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue项目实战:智慧学成项目相关的知识,希望对你有一定的参考价值。

智慧学成数据展示项目

该项⽬是基于web的轻量级系统,数据展示平台,解决了数据展示的复杂性。采⽤完全前后端分离的开发模式,使⽤ Vue.js 技术栈构建的PC端 SPA 单⻚⾯应⽤程序,UI ⽅⾯使⽤了ElementUI。

该项目主要功能是统计线上课程的各方面信息,把用户,课程,热门学科,学习频次等数据展示出来,方便运营人员直观的了解用户的学习趋势,热门的产品,是当前web开发中,比较火热的数据展示项目。

项⽬来自黑马程序员前端项目库,

共包含业务模块:9 个,后台接⼝:16个,适合了解Vue基础语法的同学练习。

项目初始化

1. 使用@vue/cli创建项目的基本结构

vue create zhxc_pro

2. 使用交互式命令行选择需要引入的模块,安装项目依赖

zhxc_pro
├─ .browserslistrc
├─ .editorconfig
├─ .eslintrc.js
├─ .gitignore
├─ babel.config.js
├─ package-lock.json
├─ package.json
├─ public
│  ├─ favicon.ico
│  └─ index.html
├─ README.md
└─ src
   ├─ App.vue
   ├─ assets
   │  └─ logo.png
   ├─ components
   │  └─ HelloWorld.vue
   ├─ main.js
   ├─ router
   │  └─ index.js
   └─ views
      ├─ About.vue
      └─ Home.vue

3.安装其他依赖

  1. 安装less less-loader

    npm install less less-loader
    
  2. 安装axios

    npm install axios
    
  3. 安装dayjs echarts element-ui

    npm install dayjs
    
    npm install echarts
    
    npm install element-ui
    

4. 梳理项目结构

  1. 清空App.vue文件

    <template>
      <div id="app">
    
      </div>
    </template>
    
    <script>
    export default 
    
    
    </script>
    
    <style lang="less" scoped>
    
    </style>
    
    
  2. 清空components和views文件夹

  3. 清空router文件夹下 index.js 中的routes 数组里的路由规则

    import Vue from 'vue'
    import VueRouter from 'vue-router'
    
    Vue.use(VueRouter)
    
    const routes = [
    
    ]
    
    const router = new VueRouter(
      routes
    )
    
    export default router
    
  4. 将准备好的图片,字体图标等静态资源复制到项目中

  5. 在src --> assets --> styles中创建全局样式文件 global.css

    html,
    body,
    #app 
        height: 100%;
        margin: 0;
        padding: 0;
    
    
  6. 在main.js中导入element和global.css

    import ElementUI from 'element-ui'
    import 'element-ui/lib/theme-chalk/index.css'
    import './assets/styles/global.css'
    

Login页面

1. 创建Login.vue文件

  1. 在src–> views 文件夹下创建 Login.vue

  2. 在路由中添加对应的路由规则

    const routes = [
       path: '/', redirect: '/login' ,
       path: '/login', name: 'login', component: () => import('@/views/Login.vue') 
    ]
    

2. 完成页面基本结构

  1. 完成template区域的结构

    <template>
      <div class="login-container">
        <div class="login-box">
          <h3>智慧学成统计系统</h3>
          <el-form ref="form">
            <el-form-item>
              <el-input></el-input>
            </el-form-item>
            <el-form-item>
              <el-input></el-input>
            </el-form-item>
            <el-form-item>
              <el-input></el-input>
            </el-form-item>
            <el-form-item>
              <el-button type="primary">登录</el-button>
            </el-form-item>
          </el-form>
        </div>
      </div>
    </template>
    
  2. 添加相应的样式

    <style lang="less" scoped>
    .login-container 
      height: 100%;
      background: url("../assets/images/background.png") no-repeat;
      .login-box 
        width: 650px;
        height: 600px;
        position: absolute;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
        background-color: rgba(255, 255, 255, 0.89);
        border-radius: 10px;
        .el-form 
          margin: 0 auto;
          width: 385px;
          height: 40px;
          .el-form-item 
            margin-bottom: 22px;
            /deep/ .el-input__inner 
              background-color: transparent;
              border: 0;
              border-bottom: 1px solid #cdcdcd;
            
          
          .el-button 
            margin-top: 50px;
            width: 100%;
            height: 60px;
            background: linear-gradient(270deg, #5efce8, #736efe);
          
        
        > h3 
          text-align: center;
          margin: 90px 0;
          font-size: 36px;
          color: #1b7bef;
        
      
    
    </style>
    
  3. 为输入框添加前置图标,因为这里的图标使用的是图片文件所以我们需要使用el-input组件提供的具名插槽prefix

    <el-form ref="form">
      <el-form-item>
        <el-input placeholder="用户名">
            <img class="prefix" slot="prefix" src="@/assets/images/username.png" alt="">
        </el-input>
      </el-form-item>
      <el-form-item>
        <el-input placeholder="密码">
            <img class="prefix" slot="prefix" src="@/assets/images/pwd.png" alt="">
        </el-input>
      </el-form-item>
      <el-form-item>
        <el-input placeholder="验证码">
            <img class="prefix" slot="prefix" src="@/assets/images/yzm.png" alt="">
        </el-input>
    </el-form-item>
    

    设置图片大小为30px

          .el-form-item 
            margin-bottom: 22px;
            .prefix 
                width: 30px;
            	
    		
    
  4. 创建自定义指令,实现为prefix中图片添加边框,显示选中状态

      directives: 
        act: 
          update: function (el, binding) 
            if (binding.value) 
              el.style.cssText = 'border:1px dashed #ccc;'
             else 
              el.style.cssText = 'border:0'
            
          
        
      
    
  5. 给el-input输入框绑定focus事件 修改v-act指令的值

            <el-form-item>
              <el-input @focus="focusHandle('username')" placeholder="用户名">
                <img
                  v-act="activeStr == 'username'"
                  class="prefix"
                  slot="prefix"
                  src="@/assets/images/username.png"
                  alt
                />
              </el-input>
            </el-form-item>
    
    
    
    	<script>
    		export default 
                  data () 
                        return 
                          activeStr: ''
                        
                      ,
                      methods: 
                        focusHandle (val) 
                          this.activeStr = val
                        
                      ,
    			
    	</script>
    

3. 为login表单绑定数据,并添加表单验证

      <el-form ref="form" :model="loginForm" :rules="loginFormRules">
        <el-form-item prop="username">
          <el-input @focus="focusHandle('username')" v-model="loginForm.username" placeholder="用户名">
            <img
              v-act="activeStr == 'username'"
              class="prefix"
              slot="prefix"
              src="@/assets/images/username.png"
              alt
            />
          </el-input>
        </el-form-item>
        <el-form-item prop="password">
          <el-input @focus="focusHandle('pwd')" v-model="loginForm.password" placeholder="密码">
            <img
              v-act="activeStr == 'pwd'"
              class="prefix"
              slot="prefix"
              src="@/assets/images/pwd.png"
              alt
            />
          </el-input>
        </el-form-item>
        <el-form-item prop="verifycode">
          <el-input @focus="focusHandle('yzm')" v-model="loginForm.verifycode" placeholder="验证码">
            <img
              v-act="activeStr == 'yzm'"
              class="prefix"
              slot="prefix"
              src="@/assets/images/yzm.png"
              alt
            />
          </el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="primary">登录</el-button>
        </el-form-item>
      </el-form>
<script>
export default 
  data () 
    return 
      activeStr: '',
      loginForm: 
        username: '',
        password: '',
        verifycode: ''
      ,
      loginFormRules: 
        username: [
           required: true, message: '请输入用户名称', trigger: 'blur' 
        ],
        password: [
           required: true, message: '请输入用户密码', trigger: 'blur' 
        ],
        verifycode: [
           required: true, message: '请输入验证码', trigger: 'blur' 
        ]
      
    
  

</script>

4.添加验证码区域

  1. 在 src–> utils 目录下创建操作本地存储的工具函数 storage.js

    /**
     * 封装本地存储操作模块
     */
    
    /**
     * 存储数据
     */
    export const setItem = (key, value) => 
        // 将数组、对象类型的数据转换为 JSON 格式字符串进行存储
        if (typeof value === 'object') 
          value = JSON.stringify(value)
        
        window.sessionStorage.setItem(key, value)
      
      
      /**
       * 获取数据
       */
      export const getItem = key => 
        const data = window.sessionStorage.getItem(key)
        try 
          return JSON.parse(data)
         catch (err) 
          return data
        
      
      
      /**
       * 删除数据
       */
      export const removeItem = key => 
        window.sessionStorage.removeItem(key)
      
      
    
  2. 在src–>utils 目录下创建用于生成验证码的工具函数 verify.js

    import  setItem  from './storage'
    /**
     *
     * @param String el 选择器
     * @param * option 配置对象  lineNum:干扰线数量 ,textLen:验证码长度 ,width:画布宽 ,height:画布高 
     */
    function Gcode(el, option) 
    
        this.el = typeof el === "string" ? document.querySelector(el) : el;
    
        this.option = option || ;
    
        this.text = ""
    
        this.init();
    
    
    
    
    Gcode.prototype = 
    
        constructor: Gcode,
    
        init: function () 
    
            if (this.el.getContext) 
                var ctx = this.el.getContext("2d"),
    
                    // 设置画布宽高
    
                    cw = this.el.width = this.option.width || 90,
    
                    ch = this.el.height = this.option.height || 30,
    
                    textLen = this.option.textLen || 4,
    
                    lineNum = this.option.lineNum || 2;
    
                this.randomText(textLen);
    
                this.onClick(ctx, textLen, lineNum, cw, ch);
    
                this.drawLine(ctx, lineNum, cw, ch);
    
                this.drawText(ctx, this.text, ch);
    
            
    
        ,
    
        onClick: function (ctx, textLen, lineNum, cw, ch) 
    
            var _ = this;
    
            this.el.addEventListener("click", function () 
    
                _.randomText(textLen);
    
                _.drawLine(ctx, lineNum, cw, ch);
    
                _.drawText(ctx, _.text, ch);
    
            , false)
    
        ,
    
        // 画干扰线
    
        drawLine: function (ctx, lineNum, maxW, maxH) 
    
            ctx.clearRect(0, 0, maxW, maxH);
    
            for (var i = 0; i < lineNum; i++) 
    
                var dx1 = Math.random() * maxW,
    
                    dy1 = Math.random() * maxH,
    
                    dx2 = Math.random() * maxW,
    
                    dy2 = Math.random() * maxH;
    
                ctx.strokeStyle = " rgb(" + 255 * Math.random() + "," + 255 * Math.random() + "," + 255 * Math.random() + ")";
    
                ctx.beginPath();
    
                ctx.moveTo(dx1, dy1);
    
                ctx.lineTo(dx2, dy2);
    
                ctx.stroke();
    
            
    
        ,
    
        // 画文字
    
        drawText: function (ctx, text, maxH) 
    
            var len = text.length;
    
            for (var i = 0; i < len; i++) 
    
                var dx = 20 * Math.random() + 20 * i,
    
                    dy = Math.random() * 5 + maxH / 2;
    
                ctx.fillStyle = " rgb(" + 255 * Math.random() + "," + 255 * Math.random() + "," + 255 * Math.random() + ")";
    
                ctx.font = " 22px Helvetica";
    
                ctx.textBaseline = " middle";
    
                ctx.fillText(text[i], dx, dy);
    
            
    
        ,
    
        // 生成指定个数的随机文字
    
        randomText: function (len) 
    
            var source = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
    
            var result = [];
    
            var sourceLen = source.length;
    
            for (var i = 0; i < len; i++) 
    
                var text = this.generateUniqueText(source, result, sourceLen);
    
                result.push(text)
    
            
            this.text = result.join("")
            setItem('verify_code', this.text)
        ,
    
        // 生成唯一文字
    
        generateUniqueText: function (source, hasList, limit) 
    
            var text = source[Math.floor(Math.random() * limit)];
    
            if (hasList.indexOf(text) > -1) 
    
                return this.generateUniqueText(source, hasList, limit)
    
             else 
    
                return text
    
            
    
        
    
    
    
    export default Gcode
    
  3. 给el-input添加后缀图标 suffix

            <el-form-item prop="verifycode">
              <el-input @focus="focusHandle('yzm')" v-model="loginForm.verifycode" placeholder="验证码">
                <img
                  v-act="activeStr == 'yzm'"
                  class="prefix"
                  slot="prefix"
                  src="@/assets/images/yzm.png"
                  alt
                />
                <canvas slot="suffix" id="verifybox"></canvas>
              </el-input>
            </el-form-item>
    
  4. 在mounted生命周期中调用utils里的工具方法生成验证码

      mounted () 
        // 创建验证码
        return new Gcode('#verifybox', 4)
      
    
  5. 自定义校验验证码的校验规则

      data () 
        // 自定义校验规则
        const checkVerify = (rule, value, callback) => 
          const vfCode = getItem('verify_code')
          if (vfCode !== value) 
            return callback(new Error('请填写正确的验证码'))
          
          callback()
        
        return 
          activeStr: '',
          loginForm: 
            username: '',
            password: '',
            verifycode: ''
          ,
          loginFormRules: 
            username: [
               required: true, message: '请输入用户名称', trigger: 'blur' 
            ],
            password: [
               required: true, message: '请输入用户密码', trigger: 'blur' 以上是关于Vue项目实战:智慧学成项目的主要内容,如果未能解决你的问题,请参考以下文章

    Vue基础入门到项目实战教程 —— Vue.js下载与安装

    Vue.js高级实战项目(不能错过的高级实战项目教程)

    Vue.js项目无法启动:sh: 1: vue-cli-service: not found

    前端实战项目:Vue.js实现外卖平台webapp,饿了么项目的翻版

    Vue.js 实战总结

    vue.js项目实战运用篇之抖音视频APP-第一节:项目环境搭建