浅学vue
概述
-
Soc原则:关注点分离原则
-
Vue 的核心库只关注视图层,方便与第三方库或既有项目整合。
-
HTML + CSS + JS : 视图 : 给用户看,刷新后台给的数据
-
网络通信 : axios
-
页面跳转 : vue-router
-
Vue-UI : ICE , Element UI
1.1、Vue.js是什么?
Vue (读音 /vjuː/,类似于
view
) 是一套用于构建用户界面的
渐进式框架
。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与
现代化的工具链
以及各种
支持类库
结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。
-
MVVM模式的实现者
-
Model:模型层, 在这里表示JavaScript对象
-
View:视图层, 在这里表示DOM(HTML操作的元素)
-
ViewModel:连接视图和数据的中间件, Vue.js就是MVVM中的View Model层的实现者
-
在MVVM架构中, 是不允许数据和视图直接通信的, 只能通过ViewModel来通信, 而View Model就是定义了一个Observer观察者
-
ViewModel能够观察到数据的变化, 并对视图对应的内容进行更新
-
ViewModel能够监听到视图的变化, 并能够通知数据发生改变
至此, 我们就明白了, Vue.js就是一个MV VM的实现者, 他的核心就是实现了DOM监听与数据绑定
1.2、为什么要使用Vue.js
-
轻量级, 体积小是一个重要指标。
Vue.js压缩后有只有20多kb(Angular压缩后56kb+,React压缩后44kb+) -
移动优先
。更适合移动端, 比如移动端的Touch事件 -
易上手,学习曲线平稳,文档齐全
-
吸取了Angular(模块化) 和React(虚拟DOM) 的长处
, 并拥有自己独特的功能,如:计算属性 -
开源,社区活跃度高
1.3、前端三要素
-
HTML(结构):超文本标记语言(Hyper Text Markup Language),决定网页的结构和内容
-
CSS(表现):层叠样式表(Cascading Style Sheets),设定网页的表现样式。
-
JavaScript(行为):是一种弱类型脚本语言,其源码不需经过编译,而是由浏览器解释运行,用于控制网页的行为
2.1、第一个Vue程序
2.2、什么是MVVM?
MVVM(Model-View-ViewModel)是一种软件设计模式,由微软WPF(用于替代WinForm,以前就是用这个技术开发桌面应用程序的)和Silverlight(类似于Java Applet,简单点说就是在浏览器上运行WPF)的架构师Ken Cooper和Ted Peters开发,是一种简化用户界面的事件驱动编程方式。由John Gossman(同样也是WPF和Sliverlight的架构师)与2005年在他的博客上发表。
MVVM源自于经典的MVC(Model-View-Controller)模式。MVVM的核心是ViewModel层,负责转换Model中的数据对象来让数据变得更容易管理和使用。其作用如下:
-
该层向上与视图层进行双向数据绑定
-
向下与Model层通过接口请求进行数据交互
MVVM已经相当成熟了,主要运用但不仅仅在网络应用程序开发中。当下流行的MVVM框架有
Vue.js
,
Anfular JS
2.3、为什么要使用MVVM?
MVVM模式和MVC模式一样,主要目的是分离视图(View)和模型(Model),有几大好处?
-
低耦合:
视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的View上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。 -
可复用:
你可以把一些视图逻辑放在一个ViewModel里面,让很多View重用这段视图逻辑。 -
独立开发:
开发人员可以专注于业务逻辑和数据的开发(ViewMode),设计人员可以专注于页面设计。 -
可测试:
界面素来是比较难以测试的,而现在测试可以针对ViewModel来写。
-
View
View是视图层, 也就是用户界面。前端主要由HTH L和csS来构建, 为了更方便地展现vi eu to del或者Hodel层的数据, 已经产生了各种各样的前后端模板语言, 比如FreeMarker,Thyme leaf等等, 各大MV VM框架如Vue.js.Angular JS, EJS等也都有自己用来构建用户界面的内置模板语言。
-
Model
Model是指数据模型, 泛指后端进行的各种业务逻辑处理和数据操控, 主要围绕数据库系统展开。这里的难点主要在于需要和前端约定统一的接口规则
-
ViewModel
ViewModel是由前端开发人员组织生成和维护的视图数据层。在这一层, 前端开发者对从后端获取的Model数据进行转换处理, 做二次封装, 以生成符合View层使用预期的视图数据模型。
需要注意的是View Model所封装出来的数据模型包括视图的状态和行为两部分, 而Model层的数据模型是只包含状态的
▷ 比如页面的这一块展示什么,那一块展示什么这些都属于视图状态(展示)
-
页面加载进来时发生什么,点击这一块发生什么,这一块滚动时发生什么这些都属于视图行为(交互)
视图状态和行为都封装在了View Model里。这样的封装使得View Model可以完整地去描述View层。由于实现了双向绑定, View Model的内容会实时展现在View层, 这是激动人心的, 因为前端开发者再也不必低效又麻烦地通过操纵DOM去更新视图。
MVVM框架已经把最脏最累的一块做好了, 我们开发者只需要处理和维护View Model, 更新数据视图就会自动得到相应更新,真正实现
事件驱动编程
。
View层展现的不是
Model
层的数据, 而是
ViewModel
的数据, 由
ViewModel
负责与
Model
层交互, 这就
完全解耦了View层和Model层, 这个解耦是至关重要的, 它是前后端分离方案实施的重要一环。
2.4、第一个Vue程序
【说明】IDEA可以安装Vue的插件! 注意:Vue不支持IE 8及以下版本, 因为Vue使用了IE 8无法模拟的ECMAScript 5特性。但它支持所有兼容ECMAScript 5的浏览器。 可以使用HBuilder编写,效果一样!
-
下载地址
-
开发版本
-
包含完整的警告和调试模式:https://yuejs.org/js/vue.js
-
删除了警告, 30.96KB min+gzip:https://vuejs.org/js/vue.min.js
-
-
CDN
-
<script src=“https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js”></script>
-
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
-
-
-
代码编写
Vue.js的核心是实现了MVVM模式, 她扮演的角色就是View Model层, 那么所谓的第一个应用程序就是展示她的数据绑定功能,操作流程如下:
-
创建一个HTML文件
-
引入Vue.js
-
创建一个Vue实例
-
将数据绑定到页面元素
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!-- 第四步:将数据绑定到页面元素 -->
<!--view层,模板-->
<div id="app">
{{message}}
</div>
<!-- 第二步:引入Vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script type="text/javascript">
<!-- 第三步:创建一个Vue实例 -->
var vm = new Vue({
el:"#app",
/*Model:数据*/
data:{
message:"hello,vue!"
}
});
</script>
</body>
</html>
说明:
-
el:#app
:绑定的是元素的ID -
data:{message:'Hello Vue!'}
:数据对象中有一个名为message的属性,并设置了初始值 Hello Vue! -
只需要在绑定的元素中使用双花括号将Vue创建的名为message属性包裹起来, 即可实现数据绑定功能, 也就实现了View Model层所需的效果, 是不是和EL表达式非常像?
测试:
为了能够更直观的体验Vue带来的数据绑定功能, 我们需要在浏览器测试一番, 操作流程如下:
1、在浏览器上运行第一个Vue应用程序, 进入开发者工具
2、在控制台输入vm.message=‘HelloWorld’, 然后回车, 你会发现浏览器中显示的内容会直接变成HelloWorld
此时就可以在控制台直接输入vm.message来修改值, 中间是可以省略data的, 在这个操作中, 我并没有主动操作DOM, 就让页面的内容发生了变化, 这就是借助了Vue的数据绑定功能实现的; MV VM模式中要求View Model层就是使用观察者模式来实现数据的监听与绑定, 以做到数据与视图的快速响应。
2.5、基础语法命令
以下所有基础语法代码均省略HTML代码
v-if-else
判断,多重判断
<!--view层,模板-->
<div id="app">
<span v-if="number === 1">時間学vue 难</span>
<span v-else-if="number === 2">時間学vue 一般</span>
<span v-else-if="number === 3">時間学vue 简单</span>
<span v-else>時間学vue 保持沉默</span>
</div>
<!-- 引入vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
<script>
<!-- 创建一个vue实例-->
var vm = new Vue({
el : "#app",
data : {
number : 2
}
});
</script>
v-for
循环
<!--view层,模板-->
<div id="app">
<h1 v-for="it in items">
{{it.message}}
</h1>
</div>
<!-- 引入vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
<script>
<!-- 创建一个vue实例-->
var vm = new Vue({
el : "#app",
data : {
items :[
{message : "時間学Java1"},
{message : "時間学前端2"},
{message : "時間学运维3"},
]
}
});
</script>
v-on
监听事件
如
v-on:click="hello"
给hello函数绑定一个单击事件
<button id="btn" v-on:click="sayHi">Click Me</button>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
<script>
var vm = new Vue({
el : "#btn",
data: {},
methods : {
sayHi : function () {
alert("hello vue !");
}
}
});
</script>
v-model
双向数据绑定
v-model
会忽略所有表单元素的
value
、
checked
、
selected
attribute 的初始值而总是将 Vue 实例的数据作为数据来源。你应该通过 JavaScript 在组件的
data
选项中声明初始值。
v-model
在内部为不同的输入元素使用不同的 property 并抛出不同的事件:
-
text 和 textarea 元素使用
value
property 和
input
事件; -
checkbox 和 radio 使用
checked
property 和
change
事件; -
select 字段将
value
作为 prop 并将
change
作为事件。
<div id="text">
文本框:<input type="text" v-model="message"> {{message}}
<p />
单选框:
<input type="radio" name="gender" value="男" v-model="radioMessage">男
<input type="radio" name="gender" value="女" v-model="radioMessage">女
我的性别是:{{radioMessage}}
<p />
复选框:
<input type="checkbox" value="西瓜" v-model="checkFlag">西瓜
<input type="checkbox" value="苹果" v-model="checkFlag">苹果
<input type="checkbox" value="哈密瓜" v-model="checkFlag">哈密瓜
<input type="checkbox" value="桃子" v-model="checkFlag">桃子
我喜欢的水果是:{{checkFlag}}
<p />
下拉框:
<select v-model="selectMessage">
<option value="" disabled>--请选择--</option>
<option value="中国">中国</option>
<option value="美国">美国</option>
</select>
我所在的国度是:{{selectMessage}}
<p />
文本域:<textarea v-model="textareaMessage"></textarea>
我输入的内容是:<textarea>{{textareaMessage}}</textarea>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
<script>
var vm = new Vue({
el : "#text",
data : {
message : "hello vue !",
radioMessage : "",
checkFlag : [],
selectMessage : "",
textareaMessage : ""
}
});
</script>
v-component
组件
什么是组件?
组件是可复用的
Vue
实例, 说白了就是一组可以重复使用的模板, 跟
JSTL
的自定义标签、
Thymeleal
的
th:fragment
等框架有着异曲同工之妙,通常一个应用会以一棵嵌套的组件树的形式来组织:
注意:在实际开发中,我们并不会用以下方式开发组件,而是采用
vue-cli
创建,
vue
模板文件的方式开发,以下方法只是为了让大家理解什么是组件。
<div id="text">
<zfc v-for="item in items" v-bind:message="item"></zfc>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
<script>
Vue.component("zfc",{
props:['message'],
template:"<li>{{message}}</li>",
});
new Vue({
el : "#text",
data : {
items : ["時間学vue","時間学前端","時間学后端"]
}
});
</script>
说明:
-
Vue.component()
:注册组件 -
zfc
:自定义组件的名字 -
template
:组件的模板 -
默认规则下props属性里的值不能为大写
-
v-for="item in items"
:遍历
Vue
实例中定义的名为
items
的数组,并创建同等数量的组件
-
v-bind:message="item"
:将遍历的
item
项绑定到组件中
props
定义名为
item
属性上;= 号左边的
message
为
props
定义的属性名,右边的为
item in items
中遍历的item项的值
3.1、Axios异步通信
3.2、什么是Axios?
Axios是一个开源的可以在浏览器端和
Node Js
的异步通信框架,它的主要作用就是实现Ajax异步通信。
3.3、特性
-
从浏览器中创建
XMLHttpRequests
-
从 node.js 创建
http
请求 -
支持
Promise
API -
拦截请求和响应
-
转换请求数据和响应数据
-
取消请求
-
自动转换 JSON 数据
-
客户端支持防御
XSRF
GitHub:
GitHub – axios/axios: Promise based HTTP client for the browser and node.js
中文文档:
axios中文网|axios API 中文文档 | axios
3.4 为什么要用Axios?
由于
vue.js
是一个视图层的框架并且作者(尤雨溪)严格遵守
SoC(关注度分离原则)
所以
vue.js
并不包含Ajax的通信功能,为了解决通信问题,作者单独开发了一个名为
vue-resource
的插件,不过在2.0版本后停止了对该插件的维护并推荐了
Axios
框架。少用jQuery,因为他操作DOM太繁琐了!
3.5、第一个Axiox程序
咱们开发的接口大部分都是采用JSON格式, 可以先在项目里模拟一段JSON数据, 数据内容如下:创建一个名为data.json的文件并填入上面的内容, 放在项目的根目录下。
{
"name": "時間学Java",
"url": "https://blog.csdn.net/qq_54027065",
"address": {
"country": "中国"
"city": "湖南益阳"
},
"links": [
{
"name": "時間学Java",
"url": "https://blog.csdn.net/qq_54027065"
},
{
"name": "bilibili",
"url": "https://space.bilibili.com/95256449"
},
{
"name": "百度",
"url": "https://www.baidu.com/"
}
]
}
测试代码
<div id="vue">
<div>姓名:{{info.name}}</div>
<div>地址:{{info.address.country}} - {{info.address.city}} - {{info.address.street}}</div>
<div>
<a v-bind:href="info.url">{{info.url}}</a>
</div>
<div>
<li v-for="link in info.links">{{link.name}}
<font color="red">-</font>
<a v-bind:href="link.url">{{link.url}}</a>
</li>
</div>
</div>
<!--引入js文件-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
var vm = new Vue({
el : "#vue",
data(){
return{
info : {
name : null,
address:{
city: null,
country: null
},
url : null,
links : [
{
name : null,
url : null,
},
]
}
}
},
mounted(){//钩子函数
axios
.get("./data.json")
.then((response) => (this.info = response.data));
}
});
</script>
说明:
-
在这里使用了v-bind将a:href的属性值与Vue实例中的数据进行绑定
-
使用axios框架的get方法请求AJAX并自动将数据封装进了Vue实例的数据对象中
-
我们在data中的数据结构必须和
Ajax
响应回来的数据格式匹配!
3.4、Vue的声明周期
官方文档:
生命周期图示
Vue实例有一个完整的生命周期,也就是从开始创建初女台化数据、编译模板、挂载DOM、渲染一更新一渲染、卸载等一系列过程,我们称这是Vue的生命周期。通俗说就是Vue实例从创建到销毁的过程,就是生命周期。
在Vue的整个生命周期中,它提供了一系列的事件,可以让我们在事件触发时注册JS方法,可以让我们用自己注册的JS方法控制整个大局,在这些事件响应方法中的this直接指向的是Vue的实例。
4.1、计算属性、内容分发、自定义事件
4.2、什么是计算属性?
计算属性的重点突出在
属性
两个字上(属性是名词),首先它是个
属性
其次这个属性有
计算
的能力(计算是动词),这里的
计算
就是个函数:简单点说,它就是一个能够将计算结果缓存起来的属性(将行为转化成了静态的属性),仅此而已;可以想象为缓存!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--view层,模板-->
<div id="app">
<p>currentTime1:{{currentTime1()}}</p>
<p>currentTime2:{{currentTime2}}</p>
</div>
<!--1.导入Vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script type="text/javascript">
var vm = new Vue({
el:"#app",
data:{
message:"me"
},
methods:{
currentTime1:function(){
return Date.now();//返回一个时间戳
}
},
computed:{
currentTime2:function(){
//计算属性:methods,computed方法名不能重名,重名之后,只会调用methods的方法
this.message;
return Date.now();//返回一个时间戳
}
}
});
</script>
</body>
</html>
注意:methods和computed里的东西不能重名
说明:
-
methods:定义方法, 调用方法使用currentTime1(), 需要带括号
-
computed:定义计算属性, 调用属性使用currentTime2, 不需要带括号:this.message是为了能够让currentTime2观察到数据变化而变化
结论:
调用方法时,每次都需要讲行计算,既然有计算过程则必定产生系统开销,那如果这个结果是不经常变化的呢?此时就可以考虑将这个结果缓存起来,采用计算属性可以很方便的做到这点,
计算属性的主要特性就是为了将不经常变化的计算结果进行缓存,以节约我们的系统开销。
4.3、内容分发
在
Vue.js
中我们使用
<slot>
元素作为承载分发内容的出口,作者称其为
插槽
,可以应用在组合组件的场景中;
第一步:定义一个待办事项的组件(todo)
第二步 我们需要让,代办事项的标题和值实现动态绑定,怎么做呢?我们可以留一个插槽!
-
接着定义一个名为todo-title的待办标题组件 和 todo-content的待办内容组件
-
实例化Vue并初始化数据
-
将值,通过插槽插入
<!--view层,模板-->
<div id="vue">
<doto>
<doto-title slot="doto-title" v-bind:title="title"></doto-title>
<doto-content slot="doto-content" v-for="(c,index) in all"
v-bind:content="c,index"></doto-content>
</doto>
</div>
<!--引入js文件-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
Vue.component("doto",{
template : "<div>\
<slot name='doto-title'></slot>\
<ul>\
<slot name='doto-content'></slot>\
</ul>\
</div>"
});
Vue.component("doto-title",{
props:["title"],
template: "<h1>{{title}}</h1>"
});
//这里的index,就是数组的下标,使用for循环遍历的时候,可以循环出来!
Vue.component("doto-content",{
props:["content","index"],
template: "<li>{{content}} -- {{index}}</li>"
})
new Vue({
el : "#vue",
data:{
title:"時間学习路线",
all:["時間学后端","時間学前端","時間学Linux"]
}
});
</script>
4.4、自定义事件
不同于组件和 prop,事件名不存在任何自动化的大小写转换。而是触发的事件名需要完全匹配监听这个事件所用的名称
this.$emit(‘自定义事件名’, 参数)
对上一个代码进行修改,实现删除功能
-
在vue的实例中增加了methods对象并定义了一个名为byIndexRemove的方法
-
修改todo-content待办内容组件的代码,增加一个删除按钮,并且绑定单击事件!
-
修改todo-content待办内容组件的HTML代码,增加一个自定义事件,比如叫remove,可以和组件的方法绑定,然后绑定到vue的方法!
<!--view层,模板-->
<div id="vue">
<doto>
<doto-title slot="doto-title" v-bind:title="title"></doto-title>
<doto-content slot="doto-content" v-for="(c,index) in all"
v-bind:content="c,index"></doto-content>
</doto>
</div>
<!--引入js文件-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
Vue.component("doto",{
template : "<div>\
<slot name='doto-title'></slot>\
<ul>\
<slot name='doto-content'></slot>\
</ul>\
</div>"
});
Vue.component("doto-title",{
props:["title"],
template: "<h1>{{title}}</h1>"
});
//这里的index,就是数组的下标,使用for循环遍历的时候,可以循环出来!
Vue.component("doto-content",{
props:["content","index"],
template: "<li>{{content}} -- {{index}}</li>"
})
new Vue({
el : "#vue",
data:{
title:"時間学习路线",
all:["時間学后端","時間学前端","時間学Linux"]
}
});
</script>
5.1、vue小结
核心:数据驱动,组件化
优点:借鉴了AngularJS的模块化开发和React的虚拟Dom,虚拟Dom就是把Demo操作放到内存中执行;
常用的属性:
-
v-if
-
v-else-if
-
v-else
-
v-for
-
v-on绑定事件,简写@
-
v-model数据双向绑定
-
v-bind给组件绑定参数,简写 :
组件化:
-
组合组件slot插槽
-
组件内部绑定事件需要使用到
this.$emit("事件名",参数);
-
计算属性的特色,缓存计算数据
遵循SoC关注度分离原则,Vue是纯粹的视图框架,并不包含,比如Ajax之类的通信功能,为了解决通信问题,我们需要使用Axios框架做异步通信;
说明
Vue的开发都是要基于NodeJS,实际开发采用Vue-cli脚手架开发,vue-router路由,vuex做状态管理;Vue UI,界面我们一般使用ElementUI(饿了么出品),或者ICE(阿里巴巴出品)来快速搭建前端项目~
官网:
Element – The world’s most popular Vue UI framework
飞冰-基于 React 的研发解决方案 | 飞冰
6.1、第一个vue-cli项目
6.2、什么是vue-cli?
vue-cli官方提供的一个脚手架,用于快速生成一个vue的项目模板;
预先定义好的目录结构及基础代码,就好比咱们在创建Maven项目时可以选择创建一个骨架项目,这个估计项目就是脚手架,我们的开发更加的快速;
项目的功能
-
统一的目录结构
-
本地调试
-
热部署
-
单元测试
-
集成打包上线
6.3、需要的环境
Node.js:
下载 | Node.js 中文网
安装就是无脑的下一步就好,安装在自己的环境目录下
确认nodejs安装成功:
-
cmd下输入
node -v
,查看是否能够正确打印出版本号即可! -
cmd下输入
npm -v
,查看是否能够正确打印出版本号即可!
安装Node.js淘宝镜像加速器(cnpm)— 这样的话,下载会快很多~
# -g 就是全局安装
npm install cnpm -g
# 或使用如下语句解决npm速度慢的问题
npm install --registry=https://registry.npm.taobao.org
安装的位置:
C:\Users\administrator\AppData\Roaming\npm
安装vue-cli
cnpm instal1 vue-cli-g
#测试是否安装成功#查看可以基于哪些模板创建vue应用程序,通常我们选择webpack
vue list
6.4、第一个vue-cli程序
-
创建一个Vue项目,随便建立一个空的文件夹在电脑上。
-
创建一个基于webpack模板的vue应用程序
#1、首先需要进入到对应的目录 cd D:\Project\vue-study #2、这里的myvue是顶日名称,可以根据自己的需求起名 vue init webpack myvue
一路都选择no即可;
说明:
-
Project name:项目名称,默认回车即可
-
Project description:项目描述,默认回车即可
-
Author:项目作者,默认回车即可
-
Install vue-router:是否安装vue-router,选择n不安装(后期需要再手动添加)
-
Use ESLint to lint your code:是否使用ESLint做代码检查,选择n不安装(后期需要再手动添加)
-
Set up unit tests:单元测试相关,选择n不安装(后期需要再手动添加)
-
Setupe2etests with Nightwatch:单元测试相关,选择n不安装(后期需要再手动添加)
-
Should we run npm install for you after the,project has been created:创建完成后直接初始化,选择n,我们手动执行;运行结果!
一、初始化并运行
cd myvue
npm install
npm run dev
执行完成后,目录多了很多依赖。
7.1、webpack使用
7.2、什么是Webpack?
webpack 是代码编译工具,有入口、出口、loader 和插件。webpack 是一个用于现代
JavaScript
应用程序的静态模块打包工具。当 webpack 处理应用程序时,它会在内部构建一个依赖图(dependency graph),此依赖图对应映射到项目所需的每个模块,并生成一个或多个
bundle
。
7.3、安装Webpack
WebPack是一款模块加载器兼打包工具, 它能把各种资源, 如JS、JSX、ES 6、SASS、LESS、图片等都作为模块来处理和使用。
npm install webpack -g
npm install webpack-cli -g
测试安装成功
-
webpack -v
-
webpack-cli -v
成功就会显示版本信息,否则就是安装失败!
7.4、使用WebPack
(1)创建项目,直接中新建一个文件夹,然后用idea打开即可
(2)创建一个名为modules的目录,用于放置JS模块等资源文件
(3)在modules下创建模块文件,如hello.js,用于编写JS模块相关代码
//暴露一个方法:sayHi
exports.sayHi = function(){
document.write("<div>Hello Webpack</div>");
}
(4)在modules下创建一个名为main.js的入口文件,用于打包时设置entry属性
//require 导入一个模块,就可以调用这个模块中的方法了
var hello = require("./hello")
hello.sayHi()
(5)在项目目录下创建webpack.config.js配置文件,使用idea终端用
webpack
命令打包
module.exports = {
entry:"./modules/main.js",
output:{
filename:"./js/bundle.js"
}
}
(6)在项目目录下创建HTML页面,如index.html,导入webpack打包后的JS文件
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>title</title>
</head>
<body>
<script src="dist/js/bundle.js"></script>
</body>
</html>
注意:
-
在IDEA控制台中直接执行webpack;如果失败的话,就使用管理员权限运行即可!
-
运行HTML看效果
说明:
# 参数--watch 用于监听变化
webpack --watch
8.1、vue-router路由
8.2、什么是vue-router?
Vue Router 是
Vue.js
官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。路由实际上就是可以理解为指向,就是我在页面上点击一个按钮需要跳转到对应的页面,这就是路由跳转;
首先我们来学习三个单词(route,routes,router):
route:
首先它是个单数,译为路由,即我们可以理解为单个路由或者某一个路由;
routes:
它是个复数,表示多个的集合才能为复数;即我们可以理解为多个路由的集合,JS中表示多种不同状态的集合的形式只有数组和对象两种,事实上官方定义routes是一个数组;所以我们记住了,routes表示多个数组的集合;
router:
译为路由器,上面都是路由,这个是路由器,我们可以理解为一个容器包含上述两个或者说它是一个管理者,负责管理上述两个;举个常见的场景的例子:当用户在页面上点击按钮的时候,这个时候router就会去routes中去查找route,就是说路由器会去路由集合中找对应的路由。
中文文档:
Vue Router
8.3、安装
基于第一个vue-cli进行测试学习; 先查看项目中node_modules文件夹中是否存在vue-router
vue-router是一个插件包,所以我们还是需要用npm/cnpm来进行安装的。打开命令行工具,进入你的项目目录,输入下面命令。
npm install vue-router --save-dev
如果在一个模块化工程中使用它,必须要通过Vue.use()明确地安装路由功能:
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter);
8.4、测试
(1)先删除没有用的东西
(2)
components
目录下存放我们自己编写的组件
(3)定义一个
Content.vue
的组件
<template>
<div>
<h1>内容页</h1>
</div>
</template>
<script>
export default {
name:"Content"
}
</script>
(4)
Main.vue
组件
<template>
<div>
<h1>首页</h1>
</div>
</template>
<script>
export default {
name:"Main"
}
</script>
(5)安装路由,在src目录下,新建一个文件夹:
router
,专门存放路由,配置路由
index.js
,如下
import Vue from'vue'
//导入路由插件
import Router from 'vue-router'
//导入上面定义的组件
import Content from '../components/Content'
import Main from '../components/Main'
//安装路由
Vue.use(Router) ;
//配置路由
export default new Router({
routes:[
{
//路由路径
path:'/content',
//路由名称
name:'content',
//跳转到组件
component:Content
},{
//路由路径
path:'/main',
//路由名称
name:'main',
//跳转到组件
component:Main
}
]
});
(6)在
main.js
中配置路由
import Vue from 'vue'
import App from './App'
//导入上面创建的路由配置目录
import router from './router'//自动扫描里面的路由配置
//来关闭生产模式下给出的提示
Vue.config.productionTip = false;
new Vue({
el:"#app",
//配置路由
router,
components:{App},
template:'<App/>'
});
(7)在
App.vue
中使用路由
<template>
<div id="app">
<!--
router-link:默认会被渲染成一个<a>标签,to属性为指定链接
router-view:用于渲染路由匹配到的组件
-->
<router-link to="/">首页</router-link>
<router-link to="/content">内容</router-link>
<router-view></router-view>
</div>
</template>
<script>
export default{
name:'App'
}
</script>
9.1、小练习
结合ElementUI组件库掌握Vue的使用。
9.2、创建项目
注意:命令行都要使用管理员模式运行
1、创建一个名为hello-vue的工程
vue init webpack hello-vue
2、安装依赖, 我们需要安装
vue-router
、
element-ui
、
sass-loader
和
node-sass
四个插件
#进入工程目录
cd hello-vue
#安装vue-router
npm install vue-router --save-dev
#安装element-ui
npm i element-ui -S
#安装依赖
npm install
# 安装SASS加载器
cnpm install sass-loader node-sass --save-dev
#启功测试
npm run dev
3、Npm命令解释:
-
npm install moduleName:安装模块到项目目录下
-
npm install -g moduleName:-g的意思是将模块安装到全局,具体安装到磁盘哪个位置要看npm config prefix的位置
-
npm install -save moduleName:–save的意思是将模块安装到项目目录下, 并在package文件的dependencies节点写入依赖,-S为该命令的缩写
-
npm install -save-dev moduleName:–save-dev的意思是将模块安装到项目目录下,并在package文件的devDependencies节点写入依赖,-D为该命令的缩写
9.4、创建登录页面
在src目录中创建如下 结构:
-
assets:用于存放资源文件
-
components:用于存放Vue功能组件
-
views:用于存放Vue视图组件
-
router:用于存放vue-router配置
(1)
创建首页视图,在views目录下创建一个名为Main.vue的视图组件:
<template>
<div>Main</div>
</template>
<script>
export default {
name:"Main"
}
</script>
<style scoped>
</style>
(2)创建登录页视图在views目录下创建名为Login.vue的视图组件,其中el-*的元素为ElementUI组件;
<template>
<div>
<el-form ref="loginForm" :model="form" :rules="rules" label-width="80px" class="login-box">
<h3 class="login-title">欢迎登录</h3>
<el-form-item label="账号" prop="username">
<el-input type="text" placeholder="请输入账号" v-model="form.username"/>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input type="password" placeholder="请输入密码" v-model="form.password"/>
</el-form-item>
<el-form-item>
<el-button type="primary" v-on:click="onSubmit('loginForm')">登录</el-button>
</el-form-item>
</el-form>
<el-dialog
title="温馨提示"
:visible.sync="dialogVisible"
width="30%"
:before-close="handleClose">
<span>请输入账号和密码</span>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="dialogVisible = false">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
name: "Login",
data(){
return{
form:{
username:'',
password:''
},
//表单验证,需要在 el-form-item 元素中增加prop属性
rules:{
username:[
{required:true,message:"账号不可为空",trigger:"blur"}
],
password:[
{required:true,message:"密码不可为空",tigger:"blur"}
]
},
//对话框显示和隐藏
dialogVisible:false
}
},
methods:{
onSubmit(formName){
//为表单绑定验证功能
this.$refs[formName].validate((valid)=>{
if(valid){
//使用vue-router路由到指定界面,该方式称为编程式导航
this.$router.push('/main');
}else{
this.dialogVisible=true;
return false;
}
});
}
}
}
</script>
<style lang="scss" scoped>
.login-box{
border:1px solid #DCDFE6;
width: 350px;
margin:180px auto;
padding: 35px 35px 15px 35px;
border-radius: 5px;
box-shadow: 0 0 25px #909399;
}
.login-title{
text-align:center;
margin: 0 auto 40px auto;
color: #303133;
}
</style>
(3)APP.vue
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App',
}
</script>
(4)main.js
import Vue from 'vue'
import App from './App'
import router from "./router";
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)
Vue.use(router)
new Vue({
el: '#app',
router,
render:h=>h(App)
})
(5)测试
9.5、路由嵌套
嵌套路由又称子路由,在实际应用中,通常由多层嵌套的组件组合而成。
(1) 创建用户信息组件,在 views/user 目录下创建一个名为 Profile.vue 的视图组件。
<template>
<h1>Profile</h1>
</template>
<script>
export default {
name: "Profile"
}
</script>
<style scoped>
</style>
(2)在用户列表组件在 views/user 目录下创建一个名为 List.vue 的视图组件。
<template>
<h1>List User</h1>
</template>
<script>
export default {
name: "List"
}
</script>
<style scoped>
</style>
(3)修改首页视图,我们修改 Main.vue 视图组件,此处使用了 ElementUI 布局容器组件,代码如下:
<template>
<div>
<el-container>
<el-aside width="200px">
<el-menu :default-openeds="['1']">
<el-submenu index="1">
<template slot="title"><i class="el-icon-caret-right"></i>用户管理</template>
<el-menu-item-group>
<el-menu-item index="1-1">
<!--插入的地方-->
<router-link to="/user/profile">个人信息</router-link>
</el-menu-item>
<el-menu-item index="1-2">
<!--插入的地方-->
<router-link to="/user/list">用户列表</router-link>
</el-menu-item>
</el-menu-item-group>
</el-submenu>
<el-submenu index="2">
<template slot="title"><i class="el-icon-caret-right"></i>内容管理</template>
<el-menu-item-group>
<el-menu-item index="2-1">分类管理</el-menu-item>
<el-menu-item index="2-2">内容列表</el-menu-item>
</el-menu-item-group>
</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-menu>
</el-dropdown>
</el-header>
<el-main>
<!--在这里展示视图-->
<router-view />
</el-main>
</el-container>
</el-container>
</div>
</template>
<script>
export default {
name: "Main"
}
</script>
<style scoped lang="scss">
.el-header {
background-color: #B3C0D1;
color: #333;
line-height: 60px;
}
.el-aside {
color: #333;
}
</style>
(4)配置嵌套路由修改 router 目录下的 index.js 路由配置文件,使用children放入main中写入子模块。
//导入vue
import Vue from 'vue';
import VueRouter from 'vue-router';
//导入组件
import Main from "../views/Main";
import Login from "../views/Login";
//导入子模块
import List from "../views/user/List";
import Profile from "../views/user/Profile";
//使用
Vue.use(VueRouter);
//导出
export default new VueRouter({
routes: [
{
//登录页
path: '/main',
component: Main,
// 写入子模块
children: [
{
path: '/user/profile',
component: Profile,
}, {
path: '/user/list',
component: List,
},
]
},
//首页
{
path: '/login',
component: Login
}
]
})
(5)测试
9.6、传递参数
第一种取值方式
(1)修改路由配置, 主要是router下的index.js中的 path 属性中增加了 :id 这样的占位符
{
path: '/user/profile/:id',
name:'Profile',
component: Profile
}
(2)此时我们在Main.vue中的route-link位置处 to 改为了 :to,是为了将这一属性当成对象使用,注意 router-link 中的 name 属性名称 一定要和 路由中的 name 属性名称 匹配,因为这样 Vue 才能找到对应的路由路径。
<!--name是组件的名字 params是传的参数 如果要传参数的话就需要用v:bind:来绑定-->
<router-link :to="{name:'UserProfile',params:{id:1}}">个人信息</router-link>
(3)在要展示的组件Profile.vue中接收参数 使用 {
{$route.params.id}}来接收Profile.vue 部分代码
<template>
<!-- 所有的元素必须在根节点下-->
<div>
<h1>个人信息</h1>
{{$route.params.id}}
</div>
</template>
第二种取值方式 使用props 减少耦合
-
修改路由配置 , 主要在router下的index.js中的路由属性中增加了 props: true 属性
{
path: '/user/profile/:id',
name:'Profile',
component: Profile,
props: true
}
-
传递参数和之前一样 在Main.vue中修改route-link地址
<!--name是组件的名字 params是传的参数 如果要传参数的话就需要用v:bind:来绑定-->
<router-link :to="{name:'Profile',params:{id:1}}">个人信息</router-link>
-
在Profile.vue接收参数为目标组件增加 props 属性
<template>
<div>
个人信息
{{ id }}
</div>
</template>
<script>
export default {
props: ['id'],
name: "Profile"
}
</script>
<style scoped>
</style>
9.7、组件重定向
重定向的意思大家都明白,但 Vue 中的重定向是作用在路径不同但组件相同的情况下,比如:
{
path: '/main',
name: 'Main',
component: Main
},
{
path: '/goHome',
redirect: '/main'
}
说明:这里定义了两个路径,一个是 /main ,一个是 /goHome,其中 /goHome 重定向到了 /main 路径,由此可以看出重定向不需要定义组件。
使用的话,只需要在Main.vue设置对应路径即可。
<el-menu-item index="1-3">
<router-link to="/goHome">回到首页</router-link>
</el-menu-item>
9.8、路由模式与 404
路由模式有两种
-
hash:路径带 # 符号,如
http://localhost/#/login
-
history:路径不带 # 符号,如
http://localhost/login
修改路由配置,代码如下:
export default new Router({
mode: 'history',
routes: [
]
});
404
1.创建一个NotFound.vue视图组件
<template>
<div>
<h1>找不到也面了哦,快叫你的程序猿来修复吧</h1>
</div>
</template>
<script>
export default {
name: "NotFound"
}
</script>
<style scoped>
</style>
2.修改路由配置index.js
import NotFound from '../views/NotFound'
{
path: '*',
component: NotFound
}
路由钩子与异步请求
-
beforeRouteEnter:在进入路由前执行
-
beforeRouteLeave:在离开路由前执行
在Profile.vue中写
export default {
name: "Profile",
beforeRouteEnter: (to, from, next) => {
console.log("进入 --> go");
next();
},
beforeRouteLeave: (to, from, next) => {
console.log("离开个 --> out");
next();
}
}
参数说明:
-
to:路由将要跳转的路径信息
-
from:路径跳转前的路径信息
-
next:路由的控制参数
-
next() 跳入下一个页面
-
next(’/path’) 改变路由的跳转方向,使其跳到另一个路由
-
next(false) 返回原来的页面
-
next((vm)=>{}) 仅在 beforeRouteEnter 中可用,vm 是组件实例
在钩子函数中使用异步请求
(1)安装 Axios
cnpm install --save vue-axios
(2)main.js引用 Axios
import axios from 'axios'
import VueAxios from 'vue-axios'
Vue.use(VueAxios, axios)
(3)准备数据 : 只有我们的 static 目录下的文件是可以被访问到的,所以我们就把静态文件放入该目录下。 数据和之前用的json数据一样 需要的去上述axios例子里
// 静态数据存放的位置
static/mock/data.json
(4)在 beforeRouteEnter 中进行异步请求
export default {
//第二种取值方式
// props:['id'],
name: "UserProfile",
//钩子函数 过滤器
beforeRouteEnter: (to, from, next) => {
//加载数据
console.log("进入 --> go")
next(vm => {
//进入路由之前执行getData方法
vm.getData();
});
},
beforeRouteLeave: (to, from, next) => {
console.log("离开 --> out")
next();
},
//axios
methods: {
getData: function () {
this.axios({
method: 'get',
url: 'http://localhost:8080/static/mock/data.json'
}).then(function (response) {
console.log(response)
})
}
}
}
学习完啦!
-
本文章通过学习
狂神说的vue视频
和结合
狂神说Vue笔记整理
总结出来!