十年河东,十年河西,莫欺少年穷
学无止境,精益求精
之所以写这篇博客,主要是巩固下vue搭建过程。
我们最终的目的是搭建一个类似于这种效果的后台管理系统。
项目源码中有引入vue公交车及axios
npm install vue-bus
npm install axios --save
项目源码地址:https://download.csdn.net/download/wolongbb/14028534
下面内容比较琐碎,可以通过下载项目结合着看,也可以不看,直接使用项目。
1、查看本机环境是否可以使用vue脚手架
chenwolong@LAPTOP-P5GVS4UM MINGW64 /d/Project/Vue/vueTest $ node -v v12.18.4 chenwolong@LAPTOP-P5GVS4UM MINGW64 /d/Project/Vue/vueTest $ npm -v 6.14.9 chenwolong@LAPTOP-P5GVS4UM MINGW64 /d/Project/Vue/vueTest $ webpack -v webpack-cli 4.2.0 webpack 5.9.0 chenwolong@LAPTOP-P5GVS4UM MINGW64 /d/Project/Vue/vueTest $ vue -V 2.9.6
node -v 用于查看本机 node 环境,如果没有 node 环境,需要安装 nodejs,具体可参考:https://www.runoob.com/nodejs/nodejs-install-setup.html
那么如何安装 npm 呢?其实不用安装。
首先我们了解下,npm是什么东东?npm其实是Node.js的包管理工具(package manager)。
其实npm已经在Node.js安装的时候顺带安装好了。我们在命令提示符或者终端输入npm -v
,应该看到上述类似的输出。
如果你想升级Npm,则可以使用如下指令安装
【升级npm(可选操作)】
npm install -g npm
webpack 是一个打包工具,如果你的电脑没有安装 webpack,则需要通过如下指令安装
【全局安装 webpack】
npm install webpack -g
【webpack 4.X 开始,需要安装 webpack-cli 依赖】
npm install webpack webpack-cli -g
vue -V 用于查看vue-cli脚手架的版本号,如果你的电脑没有安装,请执行如下指令安装
npm install -g vue-cli
安装好了环境依赖,我们就可以通过脚手架来搭建我们的项目了。
2、通过vue脚手架搭建快速搭建vue项目
执行如下指令:
vue init webpack vue-test
在执行过程中,vue会让用户做出相关的配置选择,如下:
chenwolong@LAPTOP-P5GVS4UM MINGW64 /d/Project/Vue/vueTest $ vue init webpack vue-test ? Project name (vue-test) --项目名称是否叫vue-test 直接回车,进行下一步 ? Project name vue-test ? Project description (A Vue.js project) --项目描述是否是 A Vue.js project 直接回车,进行下一步 ? Project description A Vue.js project ? Author (chenwolong <chenwolong@163.com>) --作者 直接回车,进入下一步 ? Author chenwolong <chenwolong@163.com> ? Vue build (Use arrow keys) ? Vue build standalone ? Install vue-router? (Y/n) y --是否安装Vue路由,输入 y 然后回车,进行下一步 ? Install vue-router? Yes ? Use ESLint to lint your code? (Y/n) y --是否安装EsLine代码规范 输入 y 然后回车,进行下一步 ? Use ESLint to lint your code? Yes ? Pick an ESLint preset (Use arrow keys) ? Pick an ESLint preset Standard ? Set up unit tests (Y/n) n --是都建立单元测试 输入 n 不安装单元测试,进入下一步 ? Set up unit tests No ? Setup e2e tests with Nightwatch? (Y/n) --是否安装e2e测试 输入 n 不安装 进入下一步,这时所有配置项执行完毕,脚手架开始下载项目模板 ? Setup e2e tests with Nightwatch? Yes ? Should we run `npm install` for you after the project has been created? (recom ? Should we run `npm install` for you after the project has been created? (recom mended) npm vue-cli · Generated "vue-test". # Installing project dependencies ...
待上述指令执行完毕后,我们进入 d/Project/Vue/vueTest 目录,执行
npm run dev
浏览器中输入:http://localhost:8082/
如果可以正常运行,说明你的vue项目搭建成功。那么下一步,我们就可以结合antd进行大刀阔斧的改革了。
3、vue结合antd
引入antd,执行如下指令
npm install ant-design-vue --save
执行完毕后,在项目main.js中全局引入antd,并在初始项目中的HelloWorld.vue 中引入一个button 按钮,测试下是否引入成功。
main.js变更如下:
// The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. import Vue from 'vue' import App from './App' import router from './router' import Antd from 'ant-design-vue';/* 全局引入ant */ import 'ant-design-vue/dist/antd.css'; /* 全局引入ant样式文件*/ Vue.config.productionTip = false Vue.use(Antd); /* 使用antd */ /* eslint-disable no-new */ new Vue({ el: '#app', router, components: { App }, template: '<App/>' })
HelloWorld.vue 变更如下,引入了antd 的button 按钮:
<template>
<div>
<a-button type="danger">
Danger
</a-button>
</div>
</template>
执行
npm run dev
发现报错了,eslint 校验出错,我们使用简单粗暴的办法,直接关闭eslint格式校验。
在config/index.js 中找到 :useEslint: true, 将true 改为 false即可。继续执行 npm run dev
看到如下界面,则意味着ant引入成功
成功引入ant后,我们来修改我们的路由,找到 src/route/index.js 修改index.js,变更如下:
import Vue from 'vue' import Router from 'vue-router' import index from '../view/index' import system from '../view/system/system' import product from '../view/product/product' Vue.use(Router) const originalPush = Router.prototype.push Router.prototype.push = function push(location) { return originalPush.call(this, location).catch(err => err) } export default new Router({ routes: [ { path: '/', name: 'index', component: index }, { path: '/index', name: 'index', component: index, children: [ { path: '', component: system }, { path: '/system', component: system }, { path: '/product', component: product } ] }, { path: '*', name: '404', component: () => import('@/view/404.vue'), } ] })
通过路由的代码可知,我们需要在src下面建一个名称为view的文件夹,而后在view中分别建立如下文件夹/文件,如下:
下面逐个进行分析,入口路由为 view/index.vue,下面来看index.vue的代码
<template> <a-layout id="components-layout-demo-top-side"> <!--头部--> <site-header v-bind:topmenu="topmenu"></site-header> <a-layout-content style="padding: 0 3px"> <a-layout style="padding: 24px 0; background: #fff"> <!--左侧菜单--> <site-menu></site-menu> <a-layout-content :style="{ padding: '0 24px', minHeight: '680px' }"> <!--内容填充--> <router-view /> </a-layout-content> </a-layout> </a-layout-content> </a-layout> </template> <script> export default { name: "index", data() { return { topmenu:{system:'系统管理',diangui:'商品管理',dianchi:'订单管理',dianzhuang:'图表管理'} } } }; </script> <style> #components-layout-demo-top-side .logo { width: 120px; height: 31px; background: rgba(255, 255, 255, 0.2); margin: 16px 28px 16px 0; float: left; } .footer{ text-align: center; height: 35px; padding: 8px 40px; } </style>
在index.vue中,我们使用了自定义组件 site-header 和 site-menu,我们需要在components文件夹中创建相关组件,如下:
文件 components/header.vue 代码如下:
<template> <div> <a-layout-header class="header"> <div class="logo"> <!-- 这里放你公司的logo图标--> <!-- <img src=" ../../static/pic/logo5.png" style="margin-bottom: 35px" /> --> </div> <a-menu theme="dark" mode="horizontal" :default-selected-keys="['0']" :style="{ lineHeight: '64px' }" > <a-menu-item style="font-size: 17px" disabled="true"> </a-menu-item> <a-menu-item style="font-size: 17px" disabled="true"> </a-menu-item> <a-menu-item style="font-size: 17px" disabled="true"> </a-menu-item> <a-menu-item style="font-size: 17px" disabled="true"> </a-menu-item> <a-menu-item style="font-size: 17px" disabled="true"> </a-menu-item> <a-menu-item style="font-size: 17px" disabled="true"> </a-menu-item> <a-menu-item style="font-size: 17px" disabled="true"> </a-menu-item> <a-menu-item style="font-size: 17px" disabled="true"> </a-menu-item> <a-menu-item style="font-size: 17px" disabled="true"> </a-menu-item> <a-menu-item key="0" @click="clickEve(0)" style="font-size: 17px"> {{ this.topmenu.system }} </a-menu-item> <a-menu-item key="1" @click="clickEve(1)" style="font-size: 17px"> {{ this.topmenu.dianchi }} </a-menu-item> <a-menu-item key="2" @click="clickEve(2)" style="font-size: 17px" disabled="true" > {{ this.topmenu.diangui }} </a-menu-item> <a-menu-item key="3" @click="clickEve(3)" style="font-size: 17px" disabled="true" > {{ this.topmenu.dianzhuang }} </a-menu-item> <a-menu-item style="font-size: 17px" disabled="true"> </a-menu-item> <a-menu-item style="font-size: 17px" disabled="true"> </a-menu-item> <a-menu-item style="font-size: 17px" disabled="true"> </a-menu-item> <a-menu-item style="font-size: 17px" disabled="true"> </a-menu-item> <a-menu-item style="font-size: 17px" disabled="true"> </a-menu-item> <a-menu-item style="font-size: 17px" disabled="true"> </a-menu-item> <a-menu-item style="font-size: 17px" disabled="true"> </a-menu-item> <a-menu-item style="font-size: 17px" disabled="true"> </a-menu-item> <a-menu-item style="font-size: 17px" disabled="true"> <a-tooltip> <template slot="title"> 点我退出登录 </template> <div class="custom-icons-list" @click="loginout"> <panda-icon :style="{ fontSize: '32px' }" /> </div> </a-tooltip> </a-menu-item> </a-menu> </a-layout-header> </div> </template> <script> const HeartSvg = { template: ` <svg width="1em" height="1em" fill="currentColor" viewBox="0 0 1024 1024"> <path d="M923 283.6c-13.4-31.1-32.6-58.9-56.9-82.8-24.3-23.8-52.5-42.4-84-55.5-32.5-13.5-66.9-20.3-102.4-20.3-49.3 0-97.4 13.5-139.2 39-10 6.1-19.5 12.8-28.5 20.1-9-7.3-18.5-14-28.5-20.1-41.8-25.5-89.9-39-139.2-39-35.5 0-69.9 6.8-102.4 20.3-31.4 13-59.7 31.7-84 55.5-24.4 23.9-43.5 51.7-56.9 82.8-13.9 32.3-21 66.6-21 101.9 0 33.3 6.8 68 20.3 103.3 11.3 29.5 27.5 60.1 48.2 91 32.8 48.9 77.9 99.9 133.9 151.6 92.8 85.7 184.7 144.9 188.6 147.3l23.7 15.2c10.5 6.7 24 6.7 34.5 0l23.7-15.2c3.9-2.5 95.7-61.6 188.6-147.3 56-51.7 101.1-102.7 133.9-151.6 20.7-30.9 37-61.5 48.2-91 13.5-35.3 20.3-70 20.3-103.3 0.1-35.3-7-69.6-20.9-101.9z" /> </svg> `, }; const PandaSvg = { template: ` <svg viewBox="0 0 1024 1024" width="1em" height="1em" fill="currentColor"> <path d="M99.096 315.634s-82.58-64.032-82.58-132.13c0-66.064 33.032-165.162 148.646-148.646 83.37 11.91 99.096 165.162 99.096 165.162l-165.162 115.614zM924.906 315.634s82.58-64.032 82.58-132.13c0-66.064-33.032-165.162-148.646-148.646-83.37 11.91-99.096 165.162-99.096 165.162l165.162 115.614z" fill="#6B676E" p-id="1143" /> <path d="M1024 561.548c0 264.526-229.23 429.42-512.002 429.42S0 826.076 0 561.548 283.96 66.064 512.002 66.064 1024 297.022 1024 561.548z" fill="#FFEBD2" p-id="1144" /> <path d="M330.324 842.126c0 82.096 81.34 148.646 181.678 148.646s181.678-66.55 181.678-148.646H330.324z" fill="#E9D7C3" p-id="1145" /> <path d="M644.13 611.098C594.582 528.516 561.55 512 512.002 512c-49.548 0-82.58 16.516-132.13 99.096-42.488 70.814-78.73 211.264-49.548 247.742 66.064 82.58 165.162 33.032 181.678 33.032 16.516 0 115.614 49.548 181.678-33.032 29.18-36.476-7.064-176.93-49.55-247.74z" fill="#FFFFFF" p-id="1146" /> <path d="M611.098 495.484c0-45.608 36.974-82.58 82.58-82.58 49.548 0 198.194 99.098 198.194 165.162s-79.934 144.904-148.646 99.096c-49.548-33.032-132.128-148.646-132.128-181.678zM412.904 495.484c0-45.608-36.974-82.58-82.58-82.58-49.548 0-198.194 99.098-198.194 165.162s79.934 144.904 148.646 99.096c49.548-33.032 132.128-148.646 132.128-181.678z" fill="#6B676E" p-id="1147" /> <path d="M512.002 726.622c-30.06 0-115.614 5.668-115.614 33.032 0 49.638 105.484 85.24 115.614 82.58 10.128 2.66 115.614-32.944 115.614-82.58-0.002-27.366-85.556-33.032-115.614-33.032z" fill="#464655" p-id="1148" /> <path d="M330.324 495.484m-33.032 0a33.032 33.032 0 1 0 66.064 0 33.032 33.032 0 1 0-66.064 0Z" fill="#464655" p-id="1149" /> <path d="M693.678 495.484m-33.032 0a33.032 33.032 0 1 0 66.064 0 33.032 33.032 0 1 0-66.064 0Z" fill="#464655" p-id="1150" /> </svg> `, }; const HeartIcon = { template: ` <a-icon :component="HeartSvg" /> `, data() { return { HeartSvg, }; }, }; const PandaIcon = { template: ` <a-icon :component="PandaSvg" /> `, data() { return { PandaSvg, }; }, }; export default { components: { HeartIcon, PandaIcon, }, props: ["topmenu"], created() { console.log(this.topmenu); }, data: { index: "234", }, methods: { clickEve(params) { console.log("params"); }, loginout() { this.$router.push({ path: "/", query: {} }); }, }, }; </script> <style scoped> .custom-icons-list >>> .anticon { margin-right: 6px; margin-top: 10px; padding-top: 18x; } </style>
文件 components/leftmenu.vue 代码如下:
<template> <div> <a-layout-sider width="200" style="background: #fff; height: 100vh" v-if="menuparams == 0" > <a-menu mode="inline" :default-selected-keys="selectedkeys" :default-open-keys="openkeys" :selectedKeys="NowSelectedKeys" style="height: 100%" @click="menuClick" > <a-sub-menu key="admin" > <span slot="title"><a-icon type="user" />系统设置</span> <a-menu-item key="main" @click="Redireact()" >管理员列表 </a-menu-item> <a-menu-item key="rolelst" @click="Redireact" >角色管理</a-menu-item > </a-sub-menu> <a-sub-menu key="main1"> <span slot="title"><a-icon type="setting" />电池OTA升级</span> <a-menu-item key="dianchiota" @click="Redireact" > OTA固件列表 </a-menu-item> <a-menu-item key="dianchiotalst" @click="Redireact" > OTA升级日志 </a-menu-item> </a-sub-menu> </a-menu> </a-layout-sider> <a-layout-sider width="200" style="background: #fff; height: 100vh" v-if="menuparams == 1" > <a-menu mode="inline" :default-selected-keys="selectedkeys" :default-open-keys="openkeys" :selectedKeys="NowSelectedKeys" :openKeys="NowopenKeys" style="height: 100%" > <a-sub-menu key="dianchi"> <span slot="title"><a-icon type="user" />充放电图表</span> <a-menu-item key="cdsigvol" @click="Redireact" >单体电压</a-menu-item > <a-menu-item key="elcsoc" @click="Redireact" >电流电量</a-menu-item > <a-menu-item key="batteryheart" @click="Redireact" title="充放电图表模块" >电池心跳</a-menu-item > </a-sub-menu> </a-menu> </a-layout-sider> </div> </template> <script> export default { data() { return { menuparams: 0, selectedkeys: ["cdsigvol", "main"], openkeys: ["dianchi", "admin"], NowSelectedKeys: ["cdsigvol", "main"], }; }, created() { var that = this; this.$bus.on("pasdddrameterName", function (params) { that.menuparams = params; that.NowSelectedKeys = ["cdsigvol", "main"]; //console.log(that.selectedkeys); if (that.menuparams == 0) { that.$router.push({ path: "/main" }); } if (that.menuparams == 1) { that.$router.push({ path: "/cdsigvol" }); } }); }, methods: { Redireact(item) { this.NowSelectedKeys = []; this.NowSelectedKeys.push(item.key); this.$router.push({ path: "/" + item.key }); }, }, }; </script>
写完了组件,在components文件夹中增加一个js,componentsRegist.js的代码如下,
// 组件註冊
import siteheader from './header'
import sitemenu from './leftmenu'
export default {
install (Vue) {
Vue.component('site-header', siteheader); // 顶部
Vue.component('site-menu', sitemenu); // 顶部
}
}
然后在main.js中全局注册
// The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. import Vue from 'vue' import App from './App' import router from './router' import Antd from 'ant-design-vue';/* 全局引入ant */ import 'ant-design-vue/dist/antd.css'; /* 全局引入ant样式文件*/ import components from './components/componentsRegist.js' /* 全局引入组件注册JS*/ Vue.config.productionTip = false Vue.use(Antd); /* 使用antd */ Vue.use(components); /* 使用自定义组件 */ new Vue({ el: '#app', router, components: { App }, template: '<App/>' })
view/404.vue代码如下:
<template> <div> <h1> 访问的页面未找到... </h1> </div> </template>
view/system/system代码如下:
<template> <div> <a-card hoverable="true" title="" headStyle="text-align:left;color:#606266;font-size:14px" bodyStyle="border:none" > <a slot="extra" href="#" style="float: left"> <a-breadcrumb separator=">"> <a-breadcrumb-item>系统设置</a-breadcrumb-item> <a-breadcrumb-item>管理员列表 </a-breadcrumb-item> </a-breadcrumb> </a> <div> <a-row align="middle" class="arow"> <a-col :span="6"> <a-checkable-tag v-model="checked" @change="handleChange"> 姓名 </a-checkable-tag> <a-input placeholder="请输入用户名" style=" 180px" /> </a-col> <a-col :span="6"> <a-checkable-tag v-model="checked" @change="handleChange"> 性别 </a-checkable-tag> <a-select default-value="0" style=" 180px"> <a-select-option value="0">请选择</a-select-option> <a-select-option value="1"> 男 </a-select-option> <a-select-option value="2"> 女 </a-select-option> </a-select> </a-col> <a-col :span="6"> <a-checkable-tag v-model="checked" @change="handleChange"> 年龄 </a-checkable-tag> <a-input-number :min="1" :max="100" style=" 180px" placeholder="请输入年龄" /> </a-col> <a-col :span="6"> <a-button type="primary"> 查询 </a-button> <a-button type="danger"> 新增 </a-button> </a-col> </a-row> <a-table :columns="columns" :data-source="data" :scroll="{ x: 1300 }" style="margin-top:20px;"> <a slot="action" href="javascript:;">编辑</a> </a-table> </div> </a-card> </div> </template> <script> import moment from "moment"; import "moment/locale/zh-cn"; import locale from "ant-design-vue/es/date-picker/locale/zh_CN"; const columns = [ { title: "姓名", 100, dataIndex: "name", key: "name", fixed: "left", }, { title: "性别", 100, dataIndex: "sex", key: "sex", fixed: "left" }, { title: "年龄", dataIndex: "age", key: "1" }, { title: "职称", dataIndex: "staff", key: "2" }, { title: "联系方式", dataIndex: "tel", key: "3" }, { title: "联系地址", dataIndex: "address", key: "4" }, { title: "邮箱", dataIndex: "email", key: "5" }, { title: "角色", dataIndex: "role", key: "6" }, { title: "状态", dataIndex: "status", key: "7" }, { title: "创建日期", dataIndex: "createdate", key: "8" }, { title: "操作", key: "operation", fixed: "right", 100, scopedSlots: { customRender: "action" }, }, ]; const data = [ { key: "1", sex:"男", name: "陈工", age: 30, staff:"程序猿", tel:"18137070152", address:"中国苏州", email: "163.com", role:"超级管理员", status:"正常", createdate:"2020-08-08" }, { key: "2", sex:"男", name: "邱工", age: 30, staff:"程序猿", tel:"18852585698", address:"中国苏州", email: "163.com", role:"超级管理员", status:"正常", createdate:"2020-08-08" }, { key: "3", sex:"男", name: "刘工", age: 30, staff:"前端", tel:"18565985236", address:"中国苏州", email: "163.com", role:"超级管理员", status:"正常", createdate:"2020-08-08" }, { key: "4", sex:"男", name: "姚工", age: 30, staff:"测试", tel:"15225285869", address:"中国苏州", email: "163.com", role:"超级管理员", status:"正常", createdate:"2020-08-08" }, { key: "5", sex:"女", name: "李工", age: 30, staff:"程序猿", tel:"18137070152", address:"中国苏州", email: "163.com", role:"超级管理员", status:"正常", createdate:"2020-08-08" }, { key: "6", sex:"女", name: "黄工", age: 30, staff:"程序猿", tel:"18137070152", address:"中国苏州", email: "163.com", role:"超级管理员", status:"正常", createdate:"2020-08-08" }, { key: "7", sex:"女", name: "张工", age: 30, staff:"程序猿", tel:"18137070152", address:"中国苏州", email: "163.com", role:"超级管理员", status:"正常", createdate:"2020-08-08" }, { key: "8", sex:"女", name: "诸葛工", age: 30, staff:"程序猿", tel:"18137070152", address:"中国苏州", email: "163.com", role:"超级管理员", status:"正常", createdate:"2020-08-08" }, { key: "9", sex:"女", name: "司马工", age: 30, staff:"程序猿", tel:"18137070152", address:"中国苏州", email: "163.com", role:"超级管理员", status:"正常", createdate:"2020-08-08" }, { key: "10", sex:"男", name: "欧阳工", age: 30, staff:"程序猿", tel:"18137070152", address:"中国苏州", email: "163.com", role:"超级管理员", status:"正常", createdate:"2020-08-08" }, { key: "11", sex:"男", name: "陈工", age: 30, staff:"程序猿", tel:"18137070152", address:"中国苏州", email: "163.com", role:"超级管理员", status:"正常", createdate:"2020-08-08" }, ]; export default { name: "Echarts", data() { return { locale, checked: false, dateFormat: "YYYY/MM/DD", monthFormat: "YYYY/MM", data, columns, }; }, methods: { moment, onChange(dates, dateStrings) { console.log("From: ", dates[0], ", to: ", dates[1]); console.log("From: ", dateStrings[0], ", to: ", dateStrings[1]); }, handleChange(checked) { console.log(checked); }, }, mounted() {}, }; </script> <style scoped> .img { width: 100%; height: auto; } .arow { text-align: left; } .arowLat { text-align: left; margin-top: 25px; } </style>
截止到现在,我们的站点就构造完成了。
运行下站点,看下效果
主要就是记录一下,没啥太大的意义。
@天才卧龙的博客