导航:
【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析
目录
1.3.1 双向绑定,v-bind & v-model 指令
1,VUE
1.1 Vue概述,MVVM设计模式
Vue 是一套前端框架,免除原生JavaScript中的DOM操作,简化书写。
回顾DOM:Document Object Model 文档对象模型。也就是 JavaScript 将 HTML 文档的各个组成部分封装为对象。作用:使javascript有能力操作HTML文档(获取HTML标记元素,添加HTML标记元素,删除HTML标记元素等)
类似Mybatis
框架是用来简化 jdbc
代码编写的。而 VUE
是前端的框架,是用来简化 JavaScript
代码编写的。
上节axios时候有一个案例,里面进行了大量的DOM操作,如下
学习了
VUE
后,这部分代码我们就不需要再写了。那么VUE
是如何简化 DOM 书写呢?
vue基于MVVM(Model-View-ViewModel)思想,实现数据的双向绑定,将编程的关注点放在数据上。
之前我们是将关注点放在了 DOM 操作上。
MVVM设计模式:
它本质上就是MVC 的改进版。MVVM 就是将其中的View 的状态和行为抽象化,让我们将视图 UI 和业务逻辑分开。
MVC回顾:
MVC
思想图解C 就是咱们 js 代码,M 就是数据,而 V 是页面上展示的内容,如下图是我们之前写的代码
MVC
思想只能模型到视图的单向展示,是没法进行双向绑定的。
MVVC可以实现模型和视图双向绑定:
双向绑定是指当模型发生变化时,视图的会随之发生变化;而如果视图发生变化,绑定的模型数据也随之发生变化。
双向绑定作用
从界面的操作能实时反映到数据,数据的变更能实时展现到界面
MVVM
思想三个组件图解
图中的 Model
是数据,View
是视图,也就是页面标签,用户可以通过浏览器看到的内容;
Model
和 View
是通过 ViewModel
对象进行双向绑定的,而 ViewModel
对象是 Vue
提供的。
双向绑定的效果,下图输入框绑定了 username
模型数据,而在页面上也使用 {
{}}
绑定了 username
模型数据
示例:
通过浏览器打开该页面可以看到如下页面
当我们在输入框中输入内容,而输入框后面随之实时的展示我们输入的内容,这就是双向绑定的效果。
1.2 快速入门
Vue 使用分为如下三步:
v-model | 在表单元素上创建双向数据绑定 |
vue里data()设置username值并展示在输入框,反过来又可以手动修改输入框内容设置vue里username值
- 新建 HTML 页面,引入 Vue.js文件。这里vue.js版本v2.7.8,下载地址Installation — Vue.js
<script src="js/vue.js"></script>
- 在JS代码区域,创建Vue核心对象,传入JSON对象进行数据绑定
new Vue({ el: "#app", // data() 是 ECMAScript 6 版本的新的写法,旧写法data:function(){} data() { return { username: "" } } //methods不是method,并且后面没括号 methods:{ } mounted(){} });
- 创建 Vue 对象时,需要传递一个 js 对象,而该对象中需要如下属性:
-
el
: 用来指定哪些id的标签受 Vue 管理。 该属性取值#app
中的app
需要是受管理的标签的id属性值data
:用来定义数据模型methods
:用来定义函数。
- 编写视图
<div id="app"> <input v-model="username" > { {username}} </div>
-
{ {}}
是 Vue 中定义的插值表达式
,在里面写数据模型,到时候会将该模型的数据值展示在这个位置。
整体代码如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <input v-model="username"><br> <!--插值表达式--> input里的值是:{ {username}} </div> <script src="js/vue.js"></script> <script> //1. 创建Vue核心对象 new Vue({ el:"#app", data(){ // data() 是 ECMAScript 6 版本的新的写法 return { username:"默认值" } } /*data: function () { return { username:"" } }*/ }); </script> </body> </html>
1.3 Vue 指令
指令:HTML 标签上带有 v- 前缀的特殊属性,不同指令具有不同含义。例如:v-if,v-for…
常用的指令有:
指令 | 作用 |
v-bind | 为HTML标签绑定属性值,如设置 href , css样式等,bind译为捆绑。v-bind:href="url" |
v-model | 在表单元素上创建双向数据绑定。v-model="username" { {username}} |
v-on | 为HTML标签绑定事件。v-on:click="show()" |
v-if | 条件性的渲染某元素,判定为true时渲染,否则不渲染。v-if="count==3" |
v-else | |
v-else-if | |
v-show | 根据条件展示某元素,区别在于切换的是display属性的值。v-show="count==3" |
v-for | 列表渲染,遍历容器的元素或者对象的属性。v-for="(str,i) in strs" |
只有v-bind,v-on中间有冒号,因为属性和事件都有多种。
1.3.1 双向绑定,v-bind & v-model 指令
- v-bind
该指令可以给标签原有属性绑定模型数据。这样vue的data()里模型数据发生变化,标签属性值也随之发生变化
例如:
<a v-bind:href="url">百度一下</a>
- 上面的
v-bind:"
可以简化写成:
,如下:
<!-- v-bind 可以省略 --> <a :href="url">百度一下</a>
- v-model
该指令可以给表单项标签绑定模型数据。这样就能实现双向绑定效果(vue里data()设置username值并展示在输入框,反过来又可以手动修改输入框内容设置vue里username值)。例如:
<input name="username" v-model="username">
代码演示:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <a v-bind:href="url">点击一下</a> <a :href="url">点击一下</a> <input v-model="url"> </div> <script src="js/vue.js"></script> <script> //1. 创建Vue核心对象 new Vue({ el:"#app", data(){ return { username:"", url:"https://www.baidu.com" } } }); </script> </body> </html>
通过浏览器打开上面页面,并且使用检查查看超链接的路径,该路径会根据输入框输入的路径变化而变化,这是因为超链接和输入框绑定的是同一个模型数据
1.3.2 绑定事件,v-on 指令
我们在页面定义一个按钮,并给该按钮使用 v-on
指令绑定单击事件,html代码如下
<input type="button" value="一个按钮" v-on:click="show()">
而使用 v-on
时还可以使用简化的写法,将 v-on:
替换成 @
,html代码如下
<input type="button" value="一个按钮" @click="show()">
上面代码绑定的 show()
需要在 Vue 对象中的 methods
属性中定义出来
new Vue({ el: "#app", methods: { show(){ alert("我被点了"); } } });
注意:
v-on:
后面的事件名称是之前原生事件属性名去掉on。例如:
- 单击事件 : 事件属性名是 onclick,而在vue中使用是
v-on:click
- 失去焦点事件:事件属性名是 onblur,而在vue中使用时
v-on:blur
整体页面代码如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <input type="button" value="一个按钮" v-on:click="show()"><br> <input type="button" value="一个按钮" @click="show()"> </div> <script src="js/vue.js"></script> <script> //1. 创建Vue核心对象 new Vue({ el:"#app", data(){ return { username:"", } }, methods:{ show(){ alert("我被点了..."); } } }); </script> </body> </html>
1.3.3 条件判断指令,v-if和v-show
接下来通过代码演示一下。在 Vue中定义一个 count
的数据模型,如下
//1. 创建Vue核心对象 new Vue({ el:"#app", data(){ return { count:3 } } });
现在要实现,当 count
模型的数据是3时,在页面上展示 div1
内容;当 count
模型的数据是4时,在页面上展示 div2
内容;count
模型数据是其他值时,在页面上展示 div3
。这里为了动态改变模型数据 count
的值,再定义一个输入框绑定 count
模型数据。html 代码如下:
<div id="app"> <div v-if="count == 3">div1</div> <div v-else-if="count == 4">div2</div> <div v-else>div3</div> <hr> <input v-model="count"> </div>
整体页面代码如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <div v-if="count == 1">div1</div> <div v-else-if="count == 2">div2</div> <div v-else>div3</div> <hr> 设置count的值:<input v-model="count"><br> 目前count的值:{ {count}} </div> <script src="js/vue.js"></script> <script> //1. 创建Vue核心对象 new Vue({ el:"#app", data(){ return { count:3 } } }); </script> </body> </html>
通过浏览器打开页面并在输入框输入不同的值,效果如下
v-show
然后我们在看看 v-show
指令的效果,如果模型数据 count
的值是3时,展示 div v-show
内容,否则不展示,html页面代码如下
<div v-show="count == 3">div v-show</div> <br> <input v-model="count">
浏览器打开效果如下:
v-if和v-show区别
通过下图可以看出 v-show
不展示的原理是给对应的标签添加 display
css属性,并将该属性值设置为 none
,这样就达到了隐藏的效果。而 v-if
指令是条件不满足时根本就不会渲染。在网页源码只能看见v-show的标签,看不见不满足判断条件的v-if标签。
1.3.4 列表渲染,v-for 指令
这个指令看到名字就知道是用来遍历的,该指令使用的格式如下:
<标签 v-for="变量名 in 集合模型数据"> { {变量名}} </标签>
<div v-for="addr in addrs"> { {addr}} <br> </div>
注意:需要循环哪个标签,
v-for
指令就写在哪个标签上。
如果在页面需要使用到集合模型数据的索引,就需要使用如下格式:
<标签 v-for="(变量名,索引变量) in 集合模型数据"> <!--索引变量是从0开始,所以要表示序号的话,需要手动的加1--> { {索引变量 + 1}} { {变量名}} </标签>
<div v-for="(addr,i) in addrs"> { {i+1}}--{ {addr}} <br> </div>
代码演示:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <div v-for="addr in addrs"> { {addr}} <br> </div> <hr> <div v-for="(addr,i) in addrs"> { {i+1}}--{ {addr}} <br> </div> </div> <script src="js/vue.js"></script> <script> //1. 创建Vue核心对象 new Vue({ el:"#app", data(){ return { //注意:Java中的数组静态初始化使用的是{}定义,而 JavaScript 中使用的是 [] 定义 addrs:["北京","上海","西安"] } } }); </script> </body> </html>
通过浏览器打开效果如下
1.4 生命周期
1.4.1 概述
生命周期的八个阶段:每触发一个生命周期事件,会自动执行一个生命周期方法,这些生命周期方法也被称为钩子方法。
其他了解即可,最常用的是created和mounted,类似于window.onload
下图是 Vue 官网提供的从创建 Vue 到效果 Vue 对象的整个过程及各个阶段对应的钩子函数
看到上面的图,大家无需过多的关注这张图。这些钩子方法我们只关注 mounted
就行了。
mounted
:挂载完成,Vue初始化成功,HTML页面渲染成功。而以后我们会在该方法中发送异步请求,加载数据。
new Vue({ el:"#app", data(){ return { addrs:["北京","上海","西安"] } }, mounted(){ //跟data类似,是简化后的版本 alert("加载完成"); } });
1.4.2 created和mounted的区别
created:在模板渲染成html前调用,即通常初始化某些属性值,然后再渲染成识图。
mounted:在模板渲染成html后调用,通常初始化页面完成后,再对html的dom节点进行一些需要的操作。
created()
和 mounted()
之间的根本区别在于访问DOM,如果尝试引用 this.$el
,在 created()
中返回 null
,在 mounted()
中返回 DOM 元素:
1 2 3 4 5 6 7 8 9 10 |
|
因此,任何 DOM 操作,甚至使用诸如 querySelector
之类的方法获取 DOM 元素结构将无法在 created()
中使用。因此根据这点区别 created()
非常适合调用 API,而 mounted()
非常适合在 DOM 元素完全加载后执行任何操作。
1.5 this和$
this:
Vue中生命周期钩子、自定义方法,axios和axios中then(箭头函数)的this指向当前的 Vue 实例。
方法内方法或axios的then(非箭头函数)中this指向window。
注意:普通函数和箭头函数内this指向不同。axios内的this:
selectAll(){ //这里this指向vue axios({ 这里this指向vue }).then(function (response){ 这里this指向window }) },
selectAll(){ //这里this指向vue axios({ 这里this指向vue }).then(response=>{ //箭头函数 这里this指向vue }) },
- this指向vue:可以通过this.xxx和this.xxx()调用vue中的数据和方法。
- $:挂载在this上的vue内部属性,一个特殊标记。增强区分的,来说明这是内置的实例方法属性。
1.6 案例,vue展示品牌列表
1.6.1 需求
使用 Vue 简化我们在前一天ajax学完后做的品牌列表数据查询和添加功能
JavaWeb基础9——Filter&Listener&Ajax_vincewm的博客-CSDN博客
此案例只是使用 Vue 对前端代码进行优化,后端代码无需修改。
1.6.2 查询所有功能
- 在 brand.html 页面引入 vue 的js文件
<script src="js/vue.js"></script>
- 创建 Vue 对象
-
- 在 Vue 对象中定义模型数据
- 在钩子函数中发送异步请求,并将响应的数据赋值给数据模型
- 在 Vue 对象中定义模型数据
new Vue({ el: "#app", data(){ return{ brands:[] } }, mounted(){ // 页面加载完成后,发送异步请求,查询数据 //this指代当前vue对象,要用this才能取出vue对象中的数据 var _this = this; axios({ method:"get", url:"http://localhost:8080/brand-demo/selectAllServlet" }).then(function (resp) { //这里如果直接this.brands,则this指代当前axios对象 _this.brands = resp.data; }) } })
- 修改视图
-
- 定义
<div id="app"></div>
,指定该div
标签受 Vue 管理 - 将
body
标签中所有的内容拷贝作为上面div
标签中 - 删除表格的多余数据行,只留下一个
- 在表格中的数据行上使用
v-for
指令遍历
- 定义
<tr v-for="(brand,i) in brands"> <td>{ {i+1}}</td> <td>{ {brand.brandName}}</td> <td>{ {brand.companyName}}</td> <td>{ {brand.ordered}}</td> <td>{ {brand.description}}</td> <td v-if="brand.status==1">启用</td> <td v-else>禁用</td> <td><a href="#">修改</a> <a href="#">删除</a></td> </tr>
整体页面代码如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <a href="addBrand.html"><input type="button" value="新增"></a><br> <hr> <table id="brandTable" border="1" cellspacing="0" width="100%"> <tr> <th>序号</th> <th>品牌名称</th> <th>企业名称</th> <th>排序</th> <th>品牌介绍</th> <th>状态</th> <th>操作</th> </tr> <!-- 使用v-for遍历tr --> <tr v-for="(brand,i) in brands"> <td>{ {i+1}}</td> <td>{ {brand.brandName}}</td> <td>{ {brand.companyName}}</td> <td>{ {brand.ordered}}</td> <td>{ {brand.description}}</td> <td v-if="brand.status==1">启用</td> <td v-else>禁用</td> <td><a href="#">修改</a> <a href="#">删除</a></td> </tr> </table> </div> <script src="js/axios-0.18.0.js"></script> <script src="js/vue.js"></script> <script> new Vue({ el: "#app", data(){ return{ brands:[] } }, mounted(){ // 页面加载完成后,发送异步请求,查询数据 var _this = this; axios({ method:"get", url:"http://localhost:8080/brand-demo/selectAllServlet" }).then(function (resp) { _this.brands = resp.data; }) } }) </script> </body> </html>
1.6.3 添加功能
页面操作效果如下:
整体流程如下
注意:前端代码的关键点在于使用
v-model
指令给标签项绑定模型数据,利用双向绑定特性,在发送异步请求时提交数据。
- 在 addBrand.html 页面引入 vue 的js文件
<script src="js/vue.js"></script>
- 创建 Vue 对象
-
- 在 Vue 对象中定义模型数据
brand
- 定义一个
submitForm()
函数,用于给提交
按钮提供绑定的函数 - 在
submitForm()
函数中发送 ajax 请求,并将模型数据brand
作为参数进行传递
- 在 Vue 对象中定义模型数据
new Vue({ el: "#app", data(){ return { brand:{} } }, methods:{ submitForm(){ // 发送ajax请求,添加 var _this = this; axios({ method:"post", url:"http://localhost:8080/brand-demo/addServlet", data:_this.brand }).then(function (resp) { // 判断响应数据是否为 success if(resp.data == "success"){ location.href = "http://localhost:8080/brand-demo/brand.html"; } }) } } })
- 修改视图
-
- 定义
<div id="app"></div>
,指定该div
标签受 Vue 管理 - 将
body
标签中所有的内容拷贝作为上面div
标签中 - 给每一个表单项标签绑定模型数据。最后这些数据要被封装到
brand
对象中
- 定义
<div id="app"> <h3>添加品牌</h3> <form action="" method="post"> 品牌名称:<input id="brandName" v-model="brand.brandName" name="brandName"><br> 企业名称:<input id="companyName" v-model="brand.companyName" name="companyName"><br> 排序:<input id="ordered" v-model="brand.ordered" name="ordered"><br> 描述信息:<textarea rows="5" cols="20" id="description" v-model="brand.description" name="description"></textarea><br> 状态: <input type="radio" name="status" v-model="brand.status" value="0">禁用 <input type="radio" name="status" v-model="brand.status" value="1">启用<br> <input type="button" id="btn" @click="submitForm" value="提交"> </form> </div>
整体页面代码如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>添加品牌</title> </head> <body> <div id="app"> <h3>添加品牌</h3> <form action="" method="post"> 品牌名称:<input id="brandName" v-model="brand.brandName" name="brandName"><br> 企业名称:<input id="companyName" v-model="brand.companyName" name="companyName"><br> 排序:<input id="ordered" v-model="brand.ordered" name="ordered"><br> 描述信息:<textarea rows="5" cols="20" id="description" v-model="brand.description" name="description"></textarea><br> 状态: <input type="radio" name="status" v-model="brand.status" value="0">禁用 <input type="radio" name="status" v-model="brand.status" value="1">启用<br> <input type="button" id="btn" @click="submitForm" value="提交"> </form> </div> <script src="js/axios-0.18.0.js"></script> <script src="js/vue.js"></script> <script> new Vue({ el: "#app", data(){ return { brand:{} } }, methods:{ submitForm(){ // 发送ajax请求,添加 var _this = this; axios({ method:"post", url:"http://localhost:8080/brand-demo/addServlet", data:_this.brand }).then(function (resp) { // 判断响应数据是否为 success if(resp.data == "success"){ location.href = "http://localhost:8080/brand-demo/brand.html"; } }) } } }) </script> </body> </html>
通过上面的优化,前端代码确实简化了不少。但是页面依旧是不怎么好看,那么接下来我们学习 Element,它可以美化页面。
1.7 vue脚手架进行模块化开发
1.7.1 全局安装webpack
在任意目录下cmd,注意命令尾部“-g” 是全局安装的意思。
npm install webpack -g
默认安装到目录:
1.7.2 全局安装vue脚手架
npm install -g @vue/cli@4.0.3
注意:脚手架版本和node版本要匹配,我node版本10.16.3,匹配脚手架4.0.3
1.7.3 初始化vue项目
在工程文件夹下cmd,输入以下命令初始化vue项目。建议工程名与文件夹名一致
vue init webpack 想要起的工程名 #vue init webpack vue-demo
standalone单例是选择运行+编译:
ESLint是检查代码规范的,这里不选否。
test是否使用单元测试,这里也是否
如果一直卡在downloading template,配置淘宝镜像
npm config set chromedriver_cdnurl https://npm.taobao.org/mirrors/chromedriver
初始化成功,运行项目
cd vue-demo
npm run dev
为什么运行命令是npm run dev?
在项目目录下,我们可以看到一个名为package.json的文件,该文件是对项目、模块包的描述,在package.json文件中,有一个scripts的字段:
"scripts": { "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", "start": "npm run dev", "build": "node build/build.js" },
修改后运行命令就是npm run serve:
// 运行npm run serve的scripts字段 "scripts": { "serve": "vue-cli-service serve", "build": "vue-cli-service build", "lint": "vue-cli-service lint" },
启动成功
访问默认端口http://localhost:8080/#/。
关闭cmd窗口,在vscode打开项目,重新启动:
npm run dev
1.7.4 vue项目目录结构
目录/文件 |
说明 |
build |
项目构建(webpack)相关代码 |
config |
配置目录,包括端口号等。我们初学可以使用默认的。 |
node_modules |
npm 加载的项目依赖模块。类似于maven的本地仓库 |
src |
这里是我们要开发的目录,基本上要做的事情都在这个目录里。里面包含了几个目录及文件: |
static |
静态资源目录,如图片、字体等。 |
test |
初始测试目录,可删除 |
.xxxx文件 |
这些是一些配置文件,包括语法配置,git配置等。例如.env配置端口 |
index.html |
首页入口文件。 |
package.json |
项目配置文件。类似于maven的pom |
README.md |
项目的说明文档,markdown 格式 |
1.7.5 分析主页展示逻辑
/config/index.js配置端口:
/index.html主页
其中只有一个div,内容由src/main.js主程序决定。
<body> <div id="app"></div> <!-- built files will be auto injected --> </body>
src/main.js主程序,里面有vue实例挂载id为“app”元素:
import Vue from 'vue' import App from './App' import router from './router' Vue.config.productionTip = false /* eslint-disable no-new */ //创建vue实例挂载“app”元素 new Vue({ el: '#app', router, //采用router路由,导入位置./router。这里是简写,完整是router:router components: { App },//绑定App组件。完整是App:App template: '<App/>' //元素渲染模板 })
主组件/src/App.vue,显示页面并引入路由规则
- 首先显示一张图片,图片路径为
"./assets/logo.png
- 其中的
<router-view/>
是根据url要决定访问的vue,在main.js中提及了使用的是./router
规则
<!--模板标签,编写页面展示内容--> <template> <div id="app"> <!--这里引进了一个图片--> <img src="./assets/logo.png"> <!--路由视图,/src/router/index.js路由规则配置访问的模块--> <router-view/> </div> </template> <!--vue实例代码--> <script> export default { name: 'App' } </script> <!--当前模板样式--> <style> ... </style>
配置路由规则/src/router/index.js
routes表示路由规则
当访问/
时, 显示组件Helloword
import Vue from 'vue' import Router from 'vue-router' import HelloWorld from '@/components/HelloWorld' Vue.use(Router) export default new Router({ routes: [ //访问跟路径时,路由到helloworld模块 { path: '/', name: 'HelloWorld', component: HelloWorld } ] })
/src/components/HelloWorld.vue组件
<!--模板,设置内容--> <template> <div class="hello"> <h1>{ { msg }}</h1> <h2>Essential Links</h2> <ul> <li> <a href="https://vuejs.org" target="_blank" > Core Docs </a> </li> <li> <a href="https://forum.vuejs.org" target="_blank" > Forum </a> </li> <li> <a href="https://chat.vuejs.org" target="_blank" > Community Chat </a> </li> <li> <a href="https://twitter.com/vuejs" target="_blank" > Twitter </a> </li> <br> <li> <a href="http://vuejs-templates.github.io/webpack/" target="_blank" > Docs for This Template </a> </li> </ul> <h2>Ecosystem</h2> <ul> <li> <a href="http://router.vuejs.org/" target="_blank" > vue-router </a> </li> <li> <a href="http://vuex.vuejs.org/" target="_blank" > vuex </a> </li> <li> <a href="http://vue-loader.vuejs.org/" target="_blank" > vue-loader </a> </li> <li> <a href="https://github.com/vuejs/awesome-vue" target="_blank" > awesome-vue </a> </li> </ul> </div> </template> <!--script,vue实例代码。--> <script> <!--这里导出组件,名为“HelloWorld”,在路由文件/src/router/index.js会进行导入--> export default { name: 'HelloWorld', data () { return { msg: 'Welcome to Your Vue.js App' } } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <!--style ,设置样式--> <style scoped> h1, h2 { font-weight: normal; } ul { list-style-type: none; padding: 0; } li { display: inline-block; margin: 0 10px; } a { color: #42b983; } </style>
1.7.6 新建Hello组件,负责/hello路径
/src/components创建hello.vue组件,编写组件三标签:
<template> <div> <h1>你好,hello,{ {name}}</h1> </div> </template> <script> <!--导出组件,在路由文件/src/router/index.js会导入--> export default { data(){ return { name: "张三" } } } </script> <style> </style>
编写路由文件,修改/src/router/index.js
import Vue from 'vue' import Router from 'vue-router' import HelloWorld from '@/components/HelloWorld' import Hello from '@/components/hello' //导入自定义的组件 Vue.use(Router) export default new Router({ routes: [ { path: '/', name: 'HelloWorld', component: HelloWorld }, //新增路由 { path: '/hello', name: "Hello", component: Hello } ] })
此时访问http://localhost:8080/#/hello
添加App.vue点击跳转,修改/src/App.vue的template标签:
<template> <div id="app"> <img src="./assets/logo.png"> <router-link to="/hello">去hello</router-link> <!--新增去hello--> <router-link to="/">去首页</router-link><!--新增去首页--> <router-view/> </div> </template>
运行测试效果
1.7.7 快速生成组件模板
1、文件->首选项->用户代码 新建全局代码片段
2、把下面代码粘贴进去
{ "Print to console": { "prefix": "vue", "body": [ "<!-- $1 -->", "<template>", "<div class='$2'>$5</div>", "</template>", "", "<script>", "//这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)", "//例如:import 《组件名称》 from '《组件路径》';", "", "export default {", "//import引入的组件需要注入到对象中才能使用", "components: {},", "data() {", "//这里存放数据", "return {", "", "};", "},", "//监听属性 类似于data概念", "computed: {},", "//监控data中的数据变化", "watch: {},", "//方法集合", "methods: {", "", "},", "//生命周期 - 创建完成(可以访问当前this实例)", "created() {", "", "},", "//生命周期 - 挂载完成(可以访问DOM元素)", "mounted() {", "", "},", "beforeCreate() {}, //生命周期 - 创建之前", "beforeMount() {}, //生命周期 - 挂载之前", "beforeUpdate() {}, //生命周期 - 更新之前", "updated() {}, //生命周期 - 更新之后", "beforeDestroy() {}, //生命周期 - 销毁之前", "destroyed() {}, //生命周期 - 销毁完成", "activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发", "}", "</script>", "<style scoped>", "$4", "</style>" ], "description": "生成vue模板" } }
3、在创建组件时直接输入vue
点击回车就可生成模板
2,Element
Element:是饿了么公司前端开发团队提供的一套基于 Vue 的网站组件库,用于快速构建网页。
Element 提供了很多组件(组成网页的部件)供我们使用。例如 超链接、按钮、图片、表格等等~
如下图左边的是我们编写页面看到的按钮,上图右边的是 Element 提供的页面效果,效果一目了然。
我们学习 Element 其实就是学习怎么从官网拷贝组件到我们自己的页面并进行修改。
官网网址(基于vue2)
https://element.eleme.cn/#/zh-CN
进入官网能看到如下页面
接下来直接点击 组件
,页面如下
2.1 快速入门,使用el-button组件
- 将资源
element-ui
文件夹直接拷贝到项目的webapp
下。目录结构如下 - 创建页面,并在页面引入Element 的css、js文件 和 Vue.js
<script src="js/vue.js"></script> <script src="element-ui/lib/index.js"></script> <link rel="stylesheet" href="element-ui/lib/theme-chalk/index.css">
- .创建Vue核心对象
Element 是基于 Vue 的,所以使用Element时必须要创建 Vue 对象
<script> new Vue({ el:"#app" }) </script>
- 官网复制Element组件代码
在左菜单栏找到Button 按钮
,然后找到自己喜欢的按钮样式,点击显示代码
,在下面就会展示出对应的代码,将这些代码拷贝到我们自己的页面即可。
整体页面代码如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <el-row> <el-button>默认按钮</el-button> <el-button type="primary">主要按钮</el-button> <el-button type="success">成功按钮</el-button> <el-button type="info">信息按钮</el-button> <el-button type="warning">警告按钮</el-button> <el-button type="danger">删除</el-button> </el-row> </div> <script src="js/vue.js"></script> <script src="element-ui/lib/index.js"></script> <link rel="stylesheet" href="element-ui/lib/theme-chalk/index.css"> <script> new Vue({ el:"#app" }) </script> </body> </html>
2.2 Element 布局
网站:
Element - The world's most popular Vue UI framework
Element 提供了两种布局方式,分别是:
- Layout 布局
- Container 布局容器
2.2.1 Layout 局部
通过基础的 24 分栏,迅速简便地创建布局。也就是默认将一行分为 24 栏,根据页面要求给每一列设置所占的栏数。
在左菜单栏找到 Layout 布局
,点击 显示代码
,在下面就会展示出对应的代码,显示出的代码中有样式,有html标签。
将样式<style>拷贝我们自己页面的 head
标签内,将html标签拷贝到 <div id="app"></div>
标签内。
整体页面代码如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .el-row { margin-bottom: 20px; } .el-col { border-radius: 4px; } .bg-purple-dark { background: #99a9bf; } .bg-purple { background: #d3dce6; } .bg-purple-light { background: #e5e9f2; } .grid-content { border-radius: 4px; min-height: 36px; } .row-bg { padding: 10px 0; background-color: #f9fafc; } </style> </head> <body> <div id="app"> <el-row> <el-col :span="24"><div class="grid-content bg-purple-dark"></div></el-col> </el-row> <el-row> <el-col :span="12"><div class="grid-content bg-purple"></div></el-col> <el-col :span="12"><div class="grid-content bg-purple-light"></div></el-col> </el-row> <el-row> <el-col :span="8"><div class="grid-content bg-purple"></div></el-col> <el-col :span="8"><div class="grid-content bg-purple-light"></div></el-col> <el-col :span="8"><div class="grid-content bg-purple"></div></el-col> </el-row> <el-row> <el-col :span="6"><div class="grid-content bg-purple"></div></el-col> <el-col :span="6"><div class="grid-content bg-purple-light"></div></el-col> <el-col :span="6"><div class="grid-content bg-purple"></div></el-col> <el-col :span="6"><div class="grid-content bg-purple-light"></div></el-col> </el-row> <el-row> <el-col :span="4"><div class="grid-content bg-purple"></div></el-col> <el-col :span="4"><div class="grid-content bg-purple-light"></div></el-col> <el-col :span="4"><div class="grid-content bg-purple"></div></el-col> <el-col :span="4"><div class="grid-content bg-purple-light"></div></el-col> <el-col :span="4"><div class="grid-content bg-purple"></div></el-col> <el-col :span="4"><div class="grid-content bg-purple-light"></div></el-col> </el-row> </div> <script src="js/vue.js"></script> <script src="element-ui/lib/index.js"></script> <link rel="stylesheet" href="element-ui/lib/theme-chalk/index.css"> <script> new Vue({ el:"#app" }) </script> </body> </html>
现在需要添加一行,要求该行显示8个格子,通过计算每个格子占 3 栏,具体的html 代码如下
<!-- 添加一行,8个格子 24/8 = 3 --> <el-row> <el-col :span="3"><div class="grid-content bg-purple"></div></el-col> <el-col :span="3"><div class="grid-content bg-purple-light"></div></el-col> <el-col :span="3"><div class="grid-content bg-purple"></div></el-col> <el-col :span="3"><div class="grid-content bg-purple-light"></div></el-col> <el-col :span="3"><div class="grid-content bg-purple"></div></el-col> <el-col :span="3"><div class="grid-content bg-purple-light"></div></el-col> <el-col :span="3"><div class="grid-content bg-purple"></div></el-col> <el-col :span="3"><div class="grid-content bg-purple-light"></div></el-col> </el-row>
2.2.2 Container 布局容器
用于布局的容器组件,方便快速搭建页面的基本结构。如下图就是布局容器效果。
如下图是官网提供的 Container 布局容器实例:
该效果代码中包含了样式、页面标签、模型数据。将里面的样式 <style>
拷贝到我们自己页面的 head
标签中;将html标签拷贝到 <div id="app"></div>
标签中,再将数据模型拷贝到 vue
对象的 data()
中。
整体页面代码如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .el-header { background-color: #B3C0D1; color: #333; line-height: 60px; } .el-aside { color: #333; } </style> </head> <body> <div id="app"> <el-container style="height: 500px; border: 1px solid #eee"> <el-aside width="200px" style="background-color: rgb(238, 241, 246)"> <el-menu :default-openeds="['1', '3']"> <el-submenu index="1"> <template slot="title"><i class="el-icon-message"></i>导航一</template> <el-menu-item-group> <template slot="title">分组一</template> <el-menu-item index="1-1">选项1</el-menu-item> <el-menu-item index="1-2">选项2</el-menu-item> </el-menu-item-group> <el-menu-item-group title="分组2"> <el-menu-item index="1-3">选项3</el-menu-item> </el-menu-item-group> <el-submenu index="1-4"> <template slot="title">选项4</template> <el-menu-item index="1-4-1">选项4-1</el-menu-item> </el-submenu> </el-submenu> <el-submenu index="2"> <template slot="title"><i class="el-icon-menu"></i>导航二</template> <el-submenu index="2-1"> <template slot="title">选项1</template> <el-menu-item index="2-1-1">选项1-1</el-menu-item> </el-submenu> </el-submenu> <el-submenu index="3"> <template slot="title"><i class="el-icon-setting"></i>导航三</template> <el-menu-item-group> <template slot="title">分组一</template> <el-menu-item index="3-1">选项1</el-menu-item> <el-menu-item index="3-2">选项2</el-menu-item> </el-menu-item-group> <el-menu-item-group title="分组2"> <el-menu-item index="3-3">选项3</el-menu-item> </el-menu-item-group> <el-submenu index="3-4"> <template slot="title">选项4</template> <el-menu-item index="3-4-1">选项4-1</el-menu-item> </el-submenu> </el-submenu> </el-menu> </el-aside> <el-container> <el-header style="text-align: right; font-size: 12px"> <el-dropdown> <i class="el-icon-setting" style="margin-right: 15px"></i> <el-dropdown-menu slot="dropdown"> <el-dropdown-item>查看</el-dropdown-item> <el-dropdown-item>新增</el-dropdown-item> <el-dropdown-item>删除</el-dropdown-item> </el-dropdown-menu> </el-dropdown> <span>王小虎</span> </el-header> <el-main> <el-table :data="tableData"> <el-table-column prop="date" label="日期" width="140"> </el-table-column> <el-table-column prop="name" label="姓名" width="120"> </el-table-column> <el-table-column prop="address" label="地址"> </el-table-column> </el-table> </el-main> </el-container> </el-container> </div> <script src="js/vue.js"></script> <script src="element-ui/lib/index.js"></script> <link rel="stylesheet" href="element-ui/lib/theme-chalk/index.css"> <script> new Vue({ el:"#app", data() { const item = { date: '2016-05-02', name: '王小虎', address: '上海市普陀区金沙江路 1518 弄' }; return { tableData: Array(20).fill(item) } } }) </script> </body> </html>
2.3 案例,element商品列表展示
其他的组件我们通过完成一个页面来学习。
我们要完成如下页面效果
要完成该页面,我们需要先对这个页面进行分析,看页面由哪儿几部分组成,然后到官网进行拷贝并修改。页面总共有如下组成部分
还有一个是当我们点击 新增
按钮,会在页面正中间弹出一个对话框,如下
2.3.1 准备基本页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> </div> <script src="js/vue.js"></script> <script src="element-ui/lib/index.js"></script> <link rel="stylesheet" href="element-ui/lib/theme-chalk/index.css"> <script> new Vue({ el: "#app" }) </script> </body> </html>
2.3.2 完成表格展示商品
使用 Element 整体的思路就是 拷贝 + 修改。
拷贝
在左菜单栏找到 Table 表格
并点击,右边主体就会定位到表格这一块,找到我们需要的表格效果带状态表格(主要样式,像按钮、复选框等都后面自定义),点击 显示代码
就可以看到这个表格的代码了,拷贝并修改:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .el-table .warning-row { background: oldlace; } .el-table .success-row { background: #f0f9eb; } </style> </head> <body> <div id="app"> <template> <el-table :data="tableData" style="width: 100%" :row-class-name="tableRowClassName"> <el-table-column prop="date" label="日期" width="180"> </el-table-column> <el-table-column prop="name" label="姓名" width="180"> </el-table-column> <el-table-column prop="address" label="地址"> </el-table-column> </el-table> </template> </div> <script src="js/vue.js"></script> <script src="element-ui/lib/index.js"></script> <link rel="stylesheet" href="element-ui/lib/theme-chalk/index.css"> <script> new Vue({ el:"#app", methods: { tableRowClassName({row, rowIndex}) { if (rowIndex === 1) { return 'warning-row'; } else if (rowIndex === 3) { return 'success-row'; } return ''; } }, data() { return { tableData: [{ date: '2016-05-02', name: '王小虎', address: '上海市普陀区金沙江路 1518 弄', }, { date: '2016-05-04', name: '王小虎', address: '上海市普陀区金沙江路 1518 弄' }, { date: '2016-05-01', name: '王小虎', address: '上海市普陀区金沙江路 1518 弄', }, { date: '2016-05-03', name: '王小虎', address: '上海市普陀区金沙江路 1518 弄' }] } } }) </script> </body> </html>
拷贝完成后通过浏览器打开可以看到表格的效果
表格效果出来了,但是显示的表头和数据并不是我们想要的,所以接下来就需要对页面代码进行修改了。
修改
- 修改表头和数据
下面是对表格代码进行分析的图解。根据下图说明修改自己的列数和列名
修改完页面后,还需要对绑定的模型数据进行修改,下图是对模型数据进行分析的图解 - 给表格添加操作列
从之前的表格拷贝一列出来并对其进行修改。按钮是从官网的Button 按钮
组件中拷贝并修改的 - 给表格添加复选框列和标号列
给表格添加复选框和标号列,效果如下
此效果也是从 Element 官网进行拷贝,先找到对应的表格效果,然后将其对应代码拷贝到我们的代码中,如下是复选框列官网效果图和代码
这里需要注意在<el-table>
标签上有一个事件@selection-change="handleSelectionChange"
,这里绑定的函数也需要从官网拷贝到我们自己的页面代码中,函数代码如下:
从该函数中又发现还需要一个模型数据multipleSelection
,所以还需要定义出该模型数据
标号列也用同样的方式进行拷贝并修改。
2.3.3 完成搜索表单展示
在 Element 官网找到横排的表单效果,然后拷贝代码并进行修改
点击上面的 显示代码
后,就会展示出对应的代码,下面是对这部分代码进行分析的图解
inline是行内表单模式
然后根据我们要的效果修改代码。
2.3.4 完成批量删除和新增按钮展示
从 Element 官网找具有着色效果的按钮,并将代码拷贝到我们自己的页面上
2.3.5 完成对话框展示
在 Element 官网找对话框,如下:
下面对官网提供的代码进行分析
上图分析出来的模型数据需要在 Vue 对象中进行定义。
2.3.6 完成分页条展示
在 Element 官网找到 Pagination 分页
,在页面主体部分找到我们需要的效果,如下
点击 显示代码
,找到 完整功能
对应的代码,接下来对该代码进行分析
上面代码属性说明:
page-size
:每页显示的条目数page-sizes
: 每页显示个数选择器的选项设置。:page-sizes="[100,200,300,400]"
对应的页面效果如下:currentPage
:当前页码。我们点击那个页码,此属性值就是几。total
:总记录数。用来设置总的数据条目数,该属性设置后, Element 会自动计算出需分多少页并给我们展示对应的页码。
事件说明:
size-change
:pageSize 改变时会触发。也就是当我们改变了每页显示的条目数后,该事件会触发。current-change
:currentPage 改变时会触发。也就是当我们点击了其他的页码后,该事件会触发。
2.3.7 完整页面代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .el-table .warning-row { background: oldlace; } .el-table .success-row { background: #f0f9eb; } </style> </head> <body> <div id="app"> <!--搜索表单--> <!--inline是行内表单模式--> <el-form :inline="true" :model="brand" class="demo-form-inline"> <el-form-item label="当前状态"> <el-select v-model="brand.status" placeholder="当前状态"> <el-option label="启用" value="1"></el-option> <el-option label="禁用" value="0"></el-option> </el-select> </el-form-item> <el-form-item label="企业名称"> <el-input v-model="brand.companyName" placeholder="企业名称"></el-input> </el-form-item> <el-form-item label="品牌名称"> <el-input v-model="brand.brandName" placeholder="品牌名称"></el-input> </el-form-item> <el-form-item> <el-button type="primary" @click="onSubmit">查询</el-button> </el-form-item> </el-form> <!--按钮--> <el-row> <el-button type="danger" plain>批量删除</el-button> <el-button type="primary" plain @click="dialogVisible = true">新增</el-button> </el-row> <!--添加数据对话框表单--> <el-dialog title="编辑品牌" :visible.sync="dialogVisible" width="30%"> <el-form ref="form" :model="brand" label-width="80px"> <el-form-item label="品牌名称"> <el-input v-model="brand.brandName"></el-input> </el-form-item> <el-form-item label="企业名称"> <el-input v-model="brand.companyName"></el-input> </el-form-item> <el-form-item label="排序"> <el-input v-model="brand.ordered"></el-input> </el-form-item> <el-form-item label="备注"> <el-input type="textarea" v-model="brand.description"></el-input> </el-form-item> <el-form-item label="状态"> <el-switch v-model="brand.status" active-value="1" inactive-value="0" ></el-switch> </el-form-item> <el-form-item> <el-button type="primary" @click="addBrand">提交</el-button> <el-button @click="dialogVisible = false">取消</el-button> </el-form-item> </el-form> </el-dialog> <!--表格--> <template> <!--row-class-name设置行颜色。通过指定 Table 组件的 row-class-name 属性来为 Table 中的某一行添加 class,表明该行处于某种状态。--> <!-- @selection-change="handleSelectionChange"复选框方法--> <el-table :data="tableData" style="width: 100%" :row-class-name="tableRowClassName" @selection-change="handleSelectionChange"> <el-table-column type="selection" width="55"> </el-table-column> <el-table-column type="index" width="50"> </el-table-column> <el-table-column prop="brandName" label="品牌名称" align="center"> </el-table-column> <el-table-column prop="companyName" label="企业名称" align="center"> </el-table-column> <el-table-column prop="ordered" align="center" label="排序"> </el-table-column> <el-table-column prop="status" align="center" label="当前状态"> </el-table-column> <el-table-column align="center" label="操作"> <el-row> <el-button type="primary">修改</el-button> <el-button type="danger">删除</el-button> </el-row> </el-table-column> </el-table> </template> <!--分页工具条--> <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currentPage" :page-sizes="[5, 10, 15, 20]" :page-size="5" layout="total, sizes, prev, pager, next, jumper" :total="400"> </el-pagination> </div> <script src="js/vue.js"></script> <script src="element-ui/lib/index.js"></script> <link rel="stylesheet" href="element-ui/lib/theme-chalk/index.css"> <script> new Vue({ el: "#app", methods: { // row-class-name="tableRowClassName",设置行颜色 tableRowClassName({row, rowIndex}) { if (rowIndex %4== 1) { return 'warning-row'; } else if (rowIndex%4 === 3) { return 'success-row'; } return ''; }, // 复选框选中后执行的方法 handleSelectionChange(val) { this.multipleSelection = val; console.log(this.multipleSelection) }, // 查询方法 onSubmit() { console.log(this.brand); }, // 添加数据 addBrand(){ console.log(this.brand); }, //分页 handleSizeChange(val) { console.log(`每页 ${val} 条`); }, handleCurrentChange(val) { console.log(`当前页: ${val}`); } }, data() { return { // 当前页码 currentPage: 4, // 添加数据对话框是否展示的标记 dialogVisible: false, // 品牌模型数据 brand: { status: '', brandName: '', companyName: '', id:"", ordered:"", description:"" }, // 复选框选中数据集合 multipleSelection: [], // 表格数据 tableData: [{ brandName: '华为', companyName: '华为科技有限公司', ordered: '100', status: "1" }, { brandName: '华为', companyName: '华为科技有限公司', ordered: '100', status: "1" }, { brandName: '华为', companyName: '华为科技有限公司', ordered: '100', status: "1" }, { brandName: '华为', companyName: '华为科技有限公司', ordered: '100', status: "1" }, { brandName: '华为', companyName: '华为科技有限公司', ordered: '100', status: "1" }, { brandName: '华为', companyName: '华为科技有限公司', ordered: '100', status: "1"