# vue-web模板 **Repository Path**: lzmkfc/vue-web-template ## Basic Information - **Project Name**: vue-web模板 - **Description**: vue web页面的模板库 - **Primary Language**: Unknown - **License**: Zlib - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2021-08-16 - **Last Updated**: 2021-12-08 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README

GRP UE模板库使用说明

# 一、 首次使用 ## 1. 获取代码 本系统为纯前端项目,可以使用Sublime、Notepad++、vscode等常见的文本编辑器进行开发,也可以使用idea进行开发。不同的编辑器的使用大同小异,本文将以vscode为例,简单介绍如何用这套系统模板进一步开发。 将工程克隆到本地,然后将文件夹导入到编辑器中。本工程的基本目录如下。 ![](http://10.10.4.88:4999/Public/Uploads/2019-12-10/5def60b6b0913.png) **根目录文件/文件夹说明** 文件/文件夹名|说明 --|-- public|工程入口文件index.html的所在的文件夹。 src|源代码文件夹,存放着工程主体的源代码。 .gitignore|git忽略提交文件列表。 babel.config.js|babel转码插件配置文件。
babel是一款能将高级语法转换成普通js语法的转码器。用户使用了ES6、vue、react等框架后,经过babel转码后的代码可以在绝大多数浏览器中正常运行,也包括IE。 package.json|模块的描述文件,记录着工程所使用的包和npm脚本,由npm产生。npm run运行的脚本就来自该文件。该文件是由命令自动填写的,一般不要手动更改该文件。 README .md|每一个工程的说明书,使用markdown语法,显示在GitHub的首页。 vue.config.js|vue配置文件,用来配置vue的根路径、静态文件夹和开发服务器代理等选项。 **src文件夹说明** 文件/文件夹名|说明 --|-- assets|静态资源文件,一般用来存放一些图片、css文件。 router|vue路由配置文件router.js的存放目录 store|vuex配置文件store.js的存放目录 views|存放页面文件,是开发的主体 App.vue|根组件,由main.js直接渲染在index.html上。 main.js|整个工程的入口,用来配置一些全局配置,比如router、store。全局配置后,所有的vue组件都可以使用这些配置。比如vuex。 siderbarItem.js|用来配置侧边栏项的文件。 ## 2. 安装依赖 由于工程使用了越来越多的包,本工程使用npm管理包。npm是一款基于NodeJS的一款包管理工具,能够方便快捷的对工程依赖进行管理。第一次使用npm需要安装自行安装NodeJS,安装非常简单,网上的教程大同小异,这里不再赘述。 安装NodeJS完毕后,第一次运行本工程,需要先安装工程所依赖的所有的包。打开cmd或者编辑器自带的终端,输入npm install。此时,npm将会读取package.json,并开始自动安装本工程所需要的所有依赖,此过程一般需要3~10分钟,文件目录中会多出一个叫做node_modules的文件夹。开发者无需了解文件夹内的文件,也不推荐更改该文件夹里的文件。 国内使用npm下载速度较慢,容易下载失败。如果安装时间过长,请删除node_modules文件夹,并改用cnpm进行安包。cnpm是淘宝npm镜像,服务器来自国内,下载速度更快。安装cnpm的方法也非常简单,使用方法和npm基本一致,这里不再赘述。 如果安装过程中出现warning字样,一般不需要处理。如果出现error等红色字样,可以根据相关提示进行处理,也可以将node_modules文件夹删除,重新运行cnpm install来重新安包。如果多次出现module not found、error等字样,请联系开发者处理。 ## 3. 运行前端 安装完毕后,在终端输入npm run dev即可运行。如果运行时出现error等字样,请返回第二步。 等待构建完成之后,会出现如下图所示的提示。在浏览器中访问http://localhost:9600即可查看。 运行npm run dev实际上是开启了vue自带的webpack dev server(webpack开发服务器,类似于Tomcat),同一局域网中的设备,还可以访问Network后面的URL。webpack是一个前端打包工具,能将前端文件打包成浏览器能识别的代码并压缩体积。推荐将打包文件部署到服务器上。 ![](http://10.10.4.88:4999/server/../Public/Uploads/2019-12-10/5def61434a0f8.png) ## 4. 停止运行 在终端输入Ctrl+C,再输入y即可停止运行。直接关闭控制台也可以关闭工程。关闭工程不会导致文件损坏,请放心关闭。 # 二、 使用说明 ## 1. 界面介绍 ![](http://10.10.4.88:4999/server/../Public/Uploads/2019-12-10/5def6194d0a10.png) **概览** 本系统的界面分为四部分:头部、侧边栏、标签栏和主体。头部可以显示系统名称、搜索、控制界面和使用用户选项。侧边栏可以切换主体内容。标签栏记录着浏览过的功能,切换方便。主体部分是业务逻辑的主体,功能由用户自行开发。 **头部** 对应文件/src/views/common/Header.vue。左侧按钮可以控制侧边栏折叠和展开。点击搜索按钮可以打开搜索框,此项暂时没有具体功能。点击“选项”可以切换侧边栏样式、页面主题等。点击头像可以注销登录,该项暂时没有具体功能。 **侧边栏** 对应文件/src/views/common/Siderbar.vue或SiderbarPlus.vue。通过头部右上角的选项下拉框可以切换侧边栏样式。侧边栏的菜单项并不是固定的,需要配置/src/siderbarItem.js即可自定义菜单内容。配置方法如下: ~~~ js const siderbaritem = [ { icon: 'el-icon-lx-home', to: 'dashboard', title: '系统首页', }, { icon: 'el-icon-lx-apps', to: 'toolbox', title: '工具箱', subs: [ { icon: 'el-icon-lx-calendar', title: '表单相关', to: 'formElement', subs: [ { to: 'upload', title: '文件上传', } ] }, …… ~~~ 其中,最外层的数组是一级菜单,subs里的数组是二级菜单,依次类推。目前只支持到三级菜单。 每一个数组项都由icon、to、title组成。其中icon是菜单项图标,使用element ui的icon。to为要跳转的路径,由路由器决定,使用前必须先配置路由。title是菜单项的名称。如果该项有下级菜单,请添加subs属性。 **标签栏** 对应文件`/src/views/common/Tags.vue`。每点击一次侧边栏,标签栏都会记录下一个新的标签,并且保留之前打开的标签,切换更方便。 **主体** 对应目录`/src/views`。主体部分存放具体的业务界面,点击侧边栏、标签栏或直接输入地址可以切换此处的内容。 # 三、 开发第一个页面 ## 1. 前驱知识 Vue在不少教程网站中,已经属于前端的高级课程,故阅读本教程前,你必须了解HTML、CSS、JS,达到中级水平。可以了解jQuery、NodeJS、ES6和其他前端框架或技术,并能熟练使用一款自己心仪的编辑器,简单了解前后端分离开发模式。 ## 2. 新建vue文件(vue语法简述) 在编辑器中,新建一个vue文件。推荐在`/src/views/views`文件新建,方便管理。 一个vue文件的基本结构: ~~~ html ~~~ 其中,template称为模板字符串,用来书写html代码。script标签用来书写js代码。style标签用来书写css代码。经过一定配置后,也可以书写scss、less等css预处理代码。 一个较完整的vue文件的结构: ~~~ html ~~~ **template** 模板字符串内,只能有一个标签。`template`标签是虚拟元素,我们不能够从浏览器中查看到叫做template的元素。一般我们将`template`里面第一个元素命名为`***-container`。 **vue常用指令:v-bind, v-model** v-bind用来绑定标签上的参数,不管是原生的参数还是自定义参数均可。为了方便使用,可以简写为“:”。例如,为了能够控制h1标签的style属性,我们可以把它写成`:style=””`。其中,双引号内写合法的js语句,可以写常量,也可以写变量。由于style的本质是字符串,所以要写成字符串,用单引号引起来。比如要将h1标签的大小设置30px,就可以写成 `:style="'font-size:'+size+'px'"` ,其中size来自data。 v-model被称为双向数据绑定,只能用于表单元素(input、select等)。所谓双向数据绑定, 无非就是数据层和视图层中的数据同步, 在写入数据时视图层实时地跟着更新。使用v-model后,我们可以非常方便地将数据渲染到表单元素上,也可以非常方便地将表单元素输入的值存为变量,进行进一步处理。 **vue常用指令:v-on** 在原生的js中,有像onclick、onkeyup这样的事件。在Vue中,我们将这些事件书写为`v-on:click`。为了书写方便,还可以将`v-on:clic`k缩写为`@click`。`@click=””`后面,要书写合法的js语句。比如`@click=”size++”`的意思是,点击“放大标题”button,就将data里的size自增1。vue检测到data里的size有改变,就开始重新渲染受到影响的Dom元素。在本例中,就是会使标题变大。`v-on`可以绑定函数,点击“重置”按钮,就会去执行methods中的clear()方法。 **Vue变量** 在一个Vue组件,要定义一个“全局变量”,要将它定义在`data(){return{}}`里面,写成对象的形式。 在`template`中,在标签中调用时,用“`{{}}`”括起来;在`v-on、v-bind`等指令中调用时,直接使用即可。在`script`中调用时,使用this调用。 **Vue循环:v-for** 使用`v-for`可以根据变量对Dom元素进行重复渲染。为了能够在页面上分别渲染出“三国英雄”,在data中定义一个数组之后,在p标签上书写`v-for=”item in hero” :key=”item”`,其中,item为hero中每一个数组项。为了保证Vue能够正确渲染每一个p标签,我们为每一个p标签绑定一个key属性,key是每一个p标签的标识符,key属性不可以重复。 我们可以进一步使用v-for来循环渲染数据。v-for还有另一个参数,index,它是数组的下标。 **条件判断:v-if** 在v-if中,如果值为true则渲染,值为false则不渲染。 **Vue函数** 在script中的methods里面可以定义函数,可以写成`foo: function(){}`这样的形式,还可以写成`bar(){}`这样的形式。 函数定义好后,在template中可以直接调用,在script中,使用this调用。 **Vue生命周期函数** 在Vue中有一些生命周期函数,是Vue在运行到一定时机时执行的函数,比如`created()`、`mounted()`。其中`created()`执行时,模板字符串还没有被编译,而`data`、`methods`已经可以使用一般来说,数据初始化函数放在这里执行。`mounted()`执行时,template已经被编译,此时可以进行Dom元素操作,比如一些操作Dom元素的插件就可以放在这里初始化,本例使用的jQuery就是在这里加载的。 **Vue样式** css代码要求写在style内。style标签有一个lang属性,在这里定义使用的css种类。常见的css种类有css、scss、less、stylus等等。style还有一个scoped的属性,这个属性说明此样式只在本页生效,不会影响其他页面的样式。 综合应用将上述的Vue特性整合成了一个简单的标签高亮切换,供参考。 ## 3. 配置路由 经过上一步,我们建立了一个比较完整的Vue文件,但此时我们还不能将其像普通的HTML页面一样,显示在在页面上。这里我们使用了`Vue router`(路由器)。路由器是用来切换页面的Vue插件,是构建单页面应用(SPA)的必需品。 什么是单页面应用?简单说就是只有一张Web页面的应用。如果我们查看整个工程,我们只能找到一个HTML文件,在public中。没错,整个工程只有这一个HTML,然后由路由器控制页面动态切换页面的不同位置(`router-view`),使人看起来像浏览了多个页面或`iframe`一样。实际上浏览器只访问了一个页面,并且没有调用一个`iframe`标签。 单页面应用最大的好处就是切换快,不会出现“白屏”现象。内容的改变,无需加载整个页面,用户体验好,多用于电脑端,适合开发管理系统。 在本例中,已经配置好的路由器、路由表和router-view,开发者无需深刻了解路由的原理,就可以进一步开发。 **配置为一级路由** 首先打开路由配置文件,/src/router/router.js。将登录所在的对象复制一份,平级放在下面,然后改成如下格式: ~~~ js { path: '/first', component: () => import('../components/page/First.vue'), meta: { title: '第一个页面' } } ~~~ path是路由的路径,component是跳转到该路径要显示的组件(Vue文件),这两项为必填项。meta是一些附加项,不填写将影响浏览器标签和标签栏显示。 此时,在地址栏内输入`http://localhost:9600/#/first`,即可看到如下效果: ![](http://10.10.4.88:4999/server/../Public/Uploads/2019-12-10/5def5a348b999.png) 如果需要开发像404页、登录页这样的页面,可以将组件配置到一级路由中,这样的页面是不带头部和侧边栏的。此时我们发现,头部和侧边栏“消失”了。那如何将他们“显示”出来呢? **配置为二级路由** 还是在路由表中配置,将刚才加入的对象剪切到57行下面,与“本地储存”平级。这时候,再一次访问`http://localhost:9600/#/first`,效果如下: ![](http://10.10.4.88:4999/server/../Public/Uploads/2019-12-10/5def5a4df0a48.png) 一般来说,开发者不需要继续配置三级以上的路由,更深层次的路由会导致路由难以管理,页面逻辑混乱,无法将精力投入到业务逻辑的开发中。的确需要更深层次的分级的话,可以用弹框、链接、切换标签等方式开发更深层次的逻辑。 虽然已经实现了“全屏显示”和“显示在框架内”,但是仅仅如此还是不够的,接下来将介绍如何自定义各级路由所对应的元素。 **router-view** router-view是Vue用来展示和切换组件的元素。一般来说,一级路由显示在根组件/src/App.vue中。 二级路由显示在如下代码所示的组件中: ~~~ js { path: '/', component: () => import('../views/common/Home'), children: [ { path: '/dashboard', component: () => import('../views/Dashboard'), meta: { title: '主页' } }, …… ~~~ ## 4. 配置侧边栏 本项目的侧边栏是动态生成的,配置文件在src/siderbarItem.js中,组件文件在`src/views/common/Siderbar.vue`中。组件文件会根据配置文件动态展示侧边栏项。 ~~~ js { icon: 'el-icon-menu', // elementUI的图标类名 to: 'dashboard', // 跳转的路径,该属性不可以重复 title: '主页', // 侧边栏项的文字,同级侧边栏项的名字不要重复 }, { icon: 'el-icon-menu', to: '1', title: '二级菜单', // 二级菜单。最多支持三级菜单 subs: [ { to: 'menu-level-2', title: '二级菜单项' } ] }, ~~~ 其中,icon是侧边栏项的图标,to为要跳转的路由地址,title为侧边栏项的标题,subs为子菜单,如果没有子菜单请勿写此项。注意:icon是基于element ui的图标,to不可以重复。 ## 5. ES6简介 ES6是JS的一个新规范,提供了比ES5更方便的语法和特性。目前,除IE浏览器外,大部分浏览器都支持ES6语法。本例安装的Babel转码器就是兼容IE的,所以可以放心在本例中使用ES6特性。 本说明仅仅将用到的ES6特性进行简介。 **import和export** import用来导入变量,export用来导出变量。比如siderbarItem.js就是一个典型的export。它会在siderbar.vue中导入,并作为变量展示在页面上。 export有两种用法,一种是直接将变量导出。 ~~~ js var a = 6 var b = 7 export { a, b } ~~~ 在另一个文件导入的时候,需要: ~~~ js import { a, b } from '***' ~~~ 一种是默认导出。每一个js文件只能有一个默认导出。导入变量时,可以随意命名导出的变量。 ~~~ js let c = 0 export default c ~~~ ~~~ js import ccc from '***' ~~~ **箭头函数** 箭头函数`()=>`不仅仅是对普通函数`function()`的简写。箭头函数内的`this`指向的是它的外部的`this`,无需考虑`this`指向问题,所以特别适合作为回调函数,尤其是在vue中。 ~~~ js axios({ url: '/v1/****', method: 'get' }).then((result)=>{ this.foo = result.data // 此时this代表vue示例,无需担心this指向问题 }) ~~~ 如果箭头函数的参数只有一个,则可以省略括号。 ~~~ js axios({ url: '/v1/****', method: 'get' }).then(result=>{ this.foo = result.data }) ~~~ **简写函数** 在js的对象中,定义一个函数属性需要如下语法: ~~~ js var a = { name: '张三', speak: function(){ alert('我是'+this.name) } } ~~~ 使用ES6可以简写成如下格式: ~~~ js var a = { name: '张三', speak(){ alert('我是'+this.name) } } ~~~ 在vue中,定义函数就可以写成这样。 **对象简写** 如果对象内key值和变量名一样,可以写成如下格式。 ~~~ js let a = 5 var b = { a } ~~~ 应用: ~~~ js let params = { name: '张三', age: 33, sex: '男' } axios({ method: 'get', url: '/v1/****', params }) ~~~ **let 和 const 关键字** 相比于var,let定义的变量作用域只限制在大括号内。 ~~~ js { let a = 5 var b = 6 } console.log(a) // undefined console.log(b) // 6 ~~~ const是js中的常量,给常量赋值会报错。 ~~~ js const a = 6 a = 7 // Uncaught TypeError: Assignment to constant variable. ~~~ ## 6. Vuex简介 vue工程大都是由一个个单独的组件构成的。跨组件的数据访问如果比较频繁,可以考虑使用vuex。vuex有点类似于全局变量,所有vue组件甚至是引入了`store.js`的js文件都可以享用公共数据。 由于vuex已经属于vue的高级应用,本例不再赘述,请访问[官网参考](https://vuex.vuejs.org/zh/)。 # 四、 打包 我们的工程文件是不能直接在客户端或服务端运行的,所以vue(webpack)给我们提供了打包功能,将vue文件打包成浏览器可以识别的HTML、CSS和JS代码。结合babel转码器后,很多ES6语法会被转换成ES5语法,可以运行在IE浏览器中。 打包还可以缩小工程大小,减小客户端压力。 ## 1. 使用npm脚本打包 在终端输入`npm run build`,vue开始打包。 ![](http://10.10.4.88:4999/server/../Public/Uploads/2019-12-10/5def823978a19.png) 随着打包的结束,出现了一份文件大小的列表,列出了打包出的文件的文件名和大小。 ![](http://10.10.4.88:4999/server/../Public/Uploads/2019-12-10/5def8259ecf62.png) 这些文件就可以正常使用了。 ## 2. 运行打包文件 可以直接打开`index.html`文件。如果需要连接后端数据,则要在nginx中进行相关配置后才能运行。在服务器上运行也是如此。 # 五、 常见问题 ## 1. 终端报module not found。 这是由于第一次安装依赖的时候出现了问题。可以根据提示,单独安装相应的包。如果频繁提示此错误,请将node_module文件夹删除后,重新运行npm install。国内推荐使用cnpm进行安装,稳定,速度快。 ## 2. 浏览器报NavigationDuplicated 这是由于重复点击同一个侧边栏项,导致路由导航至当前路径,这是不允许的。 ## 3. 终端报Local package.json exists, but node_modules missing, did you mean to install 没有安包,请运行`cnpm i`进行安装。 ## 4. [Vue warn]: data functions should return an object: data属性必须是一个函数。 ~~~ js data(){ return{ msg: '111' } } ~~~ ## 5. TypeError: Cannot read property 'name' of undefined 请检查"name"属性的所在的对象是不是undefined。