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.安装其他依赖
-
安装less less-loader
npm install less less-loader
-
安装axios
npm install axios
-
安装dayjs echarts element-ui
npm install dayjs
npm install echarts
npm install element-ui
4. 梳理项目结构
-
清空App.vue文件
<template> <div id="app"> </div> </template> <script> export default </script> <style lang="less" scoped> </style>
-
清空components和views文件夹
-
清空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
-
将准备好的图片,字体图标等静态资源复制到项目中
-
在src --> assets --> styles中创建全局样式文件 global.css
html, body, #app height: 100%; margin: 0; padding: 0;
-
在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文件
-
在src–> views 文件夹下创建 Login.vue
-
在路由中添加对应的路由规则
const routes = [ path: '/', redirect: '/login' , path: '/login', name: 'login', component: () => import('@/views/Login.vue') ]
2. 完成页面基本结构
-
完成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>
-
添加相应的样式
<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>
-
为输入框添加前置图标,因为这里的图标使用的是图片文件所以我们需要使用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;
-
创建自定义指令,实现为prefix中图片添加边框,显示选中状态
directives: act: update: function (el, binding) if (binding.value) el.style.cssText = 'border:1px dashed #ccc;' else el.style.cssText = 'border:0'
-
给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.添加验证码区域
-
在 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)
-
在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
-
给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>
-
在mounted生命周期中调用utils里的工具方法生成验证码
mounted () // 创建验证码 return new Gcode('#verifybox', 4)
-
自定义校验验证码的校验规则
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.js项目无法启动:sh: 1: vue-cli-service: not found