Vue 的核心库只关注视图层,方便与第三方库或既有项目整合。
HTML + CSS + JS : 视图 : 给用户看,刷新后台给的数据
网络通信 : axios
页面跳转 : vue-router
状态管理:vuex
Vue-UI : ICE , Element UI
1、VUE 概述
Vue (读音/vju/, 类似于view)是一套用于构建用户界面的渐进式框架,发布于2014年2月。
与其它大型框架不同的是,Vue被设计为可以自底向上逐层应用。Vue的核心库只关注视图层,不仅易于上手,还便于与第三方库(如: vue-router: 跳转,vue-resource: 通信,vuex:管理)或既有项目整合。
2、前端三要素
HTML (结构) :超文本标记语言(Hyper Text Markup Language) ,决定网页的结构和内容;
CSS (表现) :层叠样式表(Cascading Style sheets) ,设定网页的表现样式;
JavaScript (行为) :是一种弱类型脚本语言,其源代码不需经过编译,而是由浏览器解释运行,用于控制网页的行为。
3、JavaScript框架
jQuery: 大家熟知的JavaScript框架,优点是简化了DOM操作,缺点是DOM操作太频繁,影响前端性能;在前端眼里使用它仅仅是为了兼容IE6、7、8;
Angular: Google收购的前端框架,由一群Java程序员开发,其特点是将后台的MVC模式搬到了前端并增加了模块化开发的理念,与微软合作,采用TypeScript语法开发;对后台程序员友好,对前端程序员不太友好;最大的缺点是版本迭代不合理(如: 1代-> 2代,除了名字,基本就是两个东西;截止发表博客时已推出了Angular6)
React: Facebook出品,一款高性能的JS前端框架;特点是提出了新概念[虚拟DOM]用于减少真实DOM操作,在内存中模拟DOM操作,有效的提升了前端渲染效率;缺点是使用复杂,因为需要额外学习一门[JSX] 语言;
Vue: 一款渐进式JavaScript框架,所谓渐进式就是逐步实现新特性的意思,如实现模块化开发、路由、状态管理等新特性。其特点是综合了Angular (模块化)和React (虚拟DOM)的优点;
Axios: 前端通信框架;因为Vue 的边界很明确,就是为了处理DOM,所以并不具备通信能力,此时就需要额外使用一个通信框架与服务器交互;当然也可以直接选择使用jQuery提供的AJAX通信功能;
前端三大框架:Angular、React、Vue
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中的数据对象来让数据变得更容易管理和使用。其作用如下:
MVVM已经相当成熟了,主要运用但不仅仅在网络应用程序开发中。当下流行的MVVM框架有Vue.js,Anfular JS
MVVM模式和MVC模式一样,主要目的是分离视图(View)和模型(Model),有几大好处
(1)View
View是视图层, 也就是用户界面。前端主要由HTH L和csS来构建, 为了更方便地展现vi eu to del或者Hodel层的数据, 已经产生了各种各样的前后端模板语言, 比如FreeMarker,Thyme leaf等等, 各大MV VM框架如Vue.js.Angular JS, EJS等也都有自己用来构建用户界面的内置模板语言。
(2)Model
Model是指数据模型, 泛指后端进行的各种业务逻辑处理和数据操控, 主要围绕数据库系统展开。这里的难点主要在于需要和前端约定统一的接口规则
(3)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层, 这个解耦是至关重要的, 它是前后端分离方案实施的重要一环。
Vue(读音/vju/, 类似于view) 是一套用于构建用户界面的渐进式框架, 发布于2014年2月。与其它大型框架不同的是, Vue被设计为可以自底向上逐层应用。Vue的核心库只关注视图层, 不仅易于上手, 还便于与第三方库(如:vue-router,vue-resource,vue x) 或既有项目整合。
(1)MVVM模式的实现者
在MVVM架构中, 是不允许数据和视图直接通信的, 只能通过ViewModel来通信, 而View Model就是定义了一个Observer观察者
至此, 我们就明白了, Vue.js就是一个MV VM的实现者, 他的核心就是实现了DOM监听与数据绑定
(2)为什么要使用Vue.js
注意:Vue不支持IE 8及以下版本, 因为Vue使用了IE 8无法模拟的ECMAScript 5特性。但它支持所有兼容ECMAScript 5的浏览器。
[说明]IDEA可以安装Vue的插件!
(1)下载地址
开发版本
CDN
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
(2)代码编写
Vue.js的核心是实现了MVVM模式, 她扮演的角色就是View Model层, 那么所谓的第一个应用程序就是展示她的数据绑定功能,操作流程如下:
1、创建一个HTML文件;
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
body>
html>
2、引入Vue.js;
<!--1.导入Vue.js-->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
12
3、创建一个Vue实例;
<script type="text/javascript">
var vm = new Vue({
el:"#app",
/*Model:数据*/
data:{
message:"hello,vue!"
}
});
</script>
说明:
el: '#vue'
:绑定元素的ID;data:{message:'Hello Vue!'}
:数据对象中有一个名为message的属性,并设置了初始值 Hello Vue!4、将数据绑定到页面元素;
<div id="app">
{{message}}
div>
(3)测试;
为了能够更直观的体验Vue带来的数据绑定功能, 我们需要在浏览器测试一番, 操作流程如下:
1、在浏览器上运行第一个Vue应用程序, 进入开发者工具;
2、在控制台输入vm.message=‘HelloWorld’, 然后回车, 你会发现浏览器中显示的内容会直接变成HelloWorld;
此时就可以在控制台直接输入vm.message来修改值, 中间是可以省略data的, 在这个操作中,并没有主动操作DOM, 就让页面的内容发生了变化, 这就是借助了Vue的数据绑定功能实现的; MVVM模式中要求View Model层就是使用观察者模式来实现数据的监听与绑定, 以做到数据与视图的快速响应。
我们已经成功创建了第一个Vue应用!
看起来这跟渲染一个字符串模板非常类似, 但是Vue在背后做了大量工作。现在数据和DOM已经被建立了关联, 所有东西都是响应式的。我们在控制台操作对象属性,界面可以实时更新!
我们还可以使用v-bind来绑定元素特性!
DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<span v-bind:title="message">
鼠标悬停几秒钟查看此处动态绑定的提示信息!
span>
div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js">script>
<script type="text/javascript">
var vm = new Vue({
el:"#app",
/*Model:数据*/
data:{
message: '页面加载于 ' + new Date().toLocaleString()
}
});
script>
body>
html>
你看到的v-bind等被称为指令。指令带有前缀v以表示它们是Vue提供的特殊特性。可能你已经猜到了, 它们会在渲染的DOM上应用特殊的响应式行为在这里,该指令的意思是:“将这个元素节点的title特性和Vue实例的message属性保持一致”。
如果你再次打开浏览器的JavaScript控制台, 输入appmessage=‘新消息’,就会再一次看到这个绑定了title特性的HTML已经进行了更新。
注:===三个等号在JS中表示绝对等于(就是数据与类型都要相等)上代码:
DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<h1 v-if="type==='A'">Ah1>
<h1 v-else-if="type==='B'">Bh1>
<h1 v-else-if="type==='D'">Dh1>
<h1 v-else>Ch1>
div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js">script>
<script type="text/javascript">
var vm = new Vue({
el:"#app",
/*Model:数据*/
data:{
type: 'A'
}
});
script>
body>
html>
可以用 v-for
来遍历一个对象的 property。
<div id="app">
<li v-for="(item,index) in items">
{{item.message}}---{{index}}
li>
div>
123456
注:items
是数组,item
是数组元素迭代的别名。我们之后学习的Thymeleaf模板引擎的语法和这个十分的相似!
DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<h1>测试h1>
<div id="app">
<ul>
<li v-for="(value, name, index) in object">
{{ name }}: {{ value }}{{ index }}
li>
ul>
div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js">script>
<script type="text/javascript">
var vm = new Vue({
el:"#app",
/*Model:数据*/
data:{
object: [
{name: "Ayin"},
{message: "测试"}
]
}
});
script>
body>
html>
测试:在控制台输入vm.object.push({age:‘18’})尝试追加一条数据,你会发现浏览器中显示的内容会增加一条 2: { “age”: 18 }。
并且通过测试可以发现,index属性会始终出现在列表前端!
可以用 v-on
指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码。
<div id="example-1">
<button v-on:click="counter += 1">Add 1button>
<p>The button above has been clicked {{ counter }} times.p>
div>
var example1 = new Vue({
el: '#example-1',
data: {
counter: 0
}
})
然而许多事件处理逻辑会更为复杂,所以直接把 JavaScript 代码写在 v-on
指令中是不可行的。因此 v-on
还可以接收一个需要调用的方法名称。
<div id="example-2">
<button v-on:click="greet">Greetbutton>
div>
var example2 = new Vue({
el: '#example-2',
data: {
name: 'Vue.js'
},
// 在 `methods` 对象中定义方法
methods: {
greet: function (event) {
// `this` 在方法里指向当前 Vue 实例
alert('Hello ' + this.name + '!')
// `event` 是原生 DOM 事件
if (event) {
alert(event.target.tagName)
}
}
}
})
// 也可以用 JavaScript 直接调用方法
example2.greet() // => 'Hello Vue.js!'
什么是双向数据绑定?
Vue.js是一个MV VM框架, 即数据双向绑定, 即当数据发生变化的时候, 视图也就发生变化, 当视图发生变化的时候,数据也会跟着同步变化。这也算是Vue.js的精髓之处了。
值得注意的是,我们所说的数据双向绑定,一定是对于UI控件来说的非UI控件不会涉及到数据双向绑定。
单向数据绑定是使用状态管理工具的前提。如果我们使用vue x那么数据流也是单项的,这时就会和双向数据绑定有冲突。
为什么要实现数据的双向绑定?
在Vue.js中,如果使用vuex, 实际上数据还是单向的, 之所以说是数据双向绑定,这是用的UI控件来说, 对于我们处理表单, Vue.js的双向数据绑定用起来就特别舒服了。
即两者并不互斥,在全局性数据流使用单项,方便跟踪;局部性数据流使用双向,简单易操作。
如何在表单中使用双向数据绑定?
你可以用v-model指令在表单、及元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。
尽管有些神奇, 但v-model本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
注意: v-model会忽略所有表单元素的value、checked、selected特性的初始值而总是将Vue实例的数据作为数据来源。你应该通过JavaScript在组件的data选项中声明初始值!
你可以用 v-model
指令在表单 、
及
元素上创建双向数据绑定。
它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但 v-model
本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
v-model
在内部为不同的输入元素使用不同的 property 并抛出不同的事件:
value
property 和 input
事件;checked
property 和 change
事件;value
作为 prop 并将 change
作为事件。对于需要使用输入法(如中文、日文、韩文等) 的语言,你会发现 v-model
不会在输入法组合文字过程中得到更新。如果你也想处理这个过程,请使用 input
事件。
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
输入的文本:<input type="text" v-model="message" value="hello">{{message}}
div>
<script src="../js/vue.js">script>
<script type="text/javascript">
var vm = new Vue({
el:"#app",
data:{
message:""
}
});
script>
body>
html>
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
多行文本:<textarea v-model="pan">textarea> 多行文本是:{{pan}}
div>
<script src="../js/vue.js">script>
<script type="text/javascript">
var vm = new Vue({
el:"#app",
data:{
message:"Hello hello!"
}
});
script>
body>
html>
单个复选框,绑定到布尔值:
<input type="checkbox" id="checkbox" v-model="checked">
<label for="checkbox">{{ checked }}label>
多个复选框,绑定到同一个数组:
<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
<label for="jack">Jacklabel>
<input type="checkbox" id="john" value="John" v-model="checkedNames">
<label for="john">Johnlabel>
<input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
<label for="mike">Mikelabel>
<br>
<span>Checked names: {{ checkedNames }}span>
new Vue({
el: '...',
data: {
checkedNames: []
}
})
<div id="example-4">
<input type="radio" id="one" value="One" v-model="picked">
<label for="one">Onelabel>
<br>
<input type="radio" id="two" value="Two" v-model="picked">
<label for="two">Twolabel>
<br>
<span>Picked: {{ picked }}span>
div>
new Vue({
el: '#example-4',
data: {
picked: ''
}
})
单选时:
<div id="example-5">
<select v-model="selected">
<option disabled value="">请选择option>
<option>Aoption>
<option>Boption>
<option>Coption>
select>
<span>Selected: {{ selected }}span>
div>
new Vue({
el: '...',
data: {
selected: ''
}
})
如果 v-model
表达式的初始值未能匹配任何选项, 元素将被渲染为“未选中”状态。在 iOS 中,这会使用户无法选择第一个选项。因为这样的情况下,iOS 不会触发 change 事件。因此,更推荐像上面这样提供一个值为空的禁用选项。
多选时 (绑定到一个数组):
<div id="example-6">
<select v-model="selected" multiple style="width: 50px;">
<option>Aoption>
<option>Boption>
<option>Coption>
select>
<br>
<span>Selected: {{ selected }}span>
div>
new Vue({
el: '#example-6',
data: {
selected: []
}
})
什么是组件?
组件是可复用的Vue实例, 说白了就是一组可以重复使用的模板, 跟JSTL的自定义标签、Thymeleal的th:fragment等框架有着异曲同工之妙,通常一个应用会以一棵嵌套的组件树的形式来组织:
例如,你可能会有页头、侧边栏、内容区等组件,每个组件又包含了其它的像导航链接、博文之类的组件。
为了能在模板中使用,这些组件必须先注册以便 Vue 能够识别。这里有两种组件的注册类型:全局注册和局部注册。至此,我们的组件都只是通过 Vue.component
全局注册的:
第一个Vue组件
注意: 在实际开发中,我们并不会用以下方式开发组件,而是采用vue-cli
创建,vue
模板文件的方式开发,以下方法只是为了让大家理解什么是组件。
使用Vue.component()
方法注册组件,格式如下:
<div id="app">
<ul>
<ayin v-for="item in items" v-bind:value="item">ayin>
ul>
div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js">script>
<script type="text/javascript">
// 先注册组件
Vue.component("ayin", {
props: ['value'],
template: '{{value}} '
});
// 再实例化Vue
var vm = new Vue({
el:"#app",
/*Model:数据*/
data: {
items: ["Java", "MySQL", "Linux"]
}
});
script>
说明:
什么是Axios?
Axios是一个开源的可以用在浏览器端和Node JS的异步通信框架, 她的主要作用就是实现AJAX异步通信,其功能特点如下:
从浏览器中创建XMLHttpRequests
从node.js创建http请求
支持Promise API[JS中链式编程]
拦截请求和响应
转换请求数据和响应数据
取消请求
自动转换JSON数据
客户端支持防御XSRF(跨站请求伪造)
GitHub:https://github.com/axios/axios
中文文档:http://www.axios-js.com/
为什么要使用Axios?
由于Vue.js是一个视图层框架并且作者(尤雨溪) 严格准守SoC(关注度分离原则)所以Vue.js并不包含AJAX的通信功能。
为了解决通信问题, 作者单独开发了一个名为vue-resource的插件,不过在进入2.0版本以后停止了对该插件的维护并推荐了Axios框架。少用jQuery, 因为它操作Dom太频繁!
第一个Axios应用程序
咱们开发的接口大部分都是采用JSON格式, 可以先在项目里模拟一段JSON数据, 数据内容如下:
创建一个名为data.json的文件并填入上面的内容, 放在项目的根目录下;
{
"name":"狂神说java",
"url": "http://baidu.com",
"page": "1",
"isNonProfit":"true",
"address": {
"street": "含光门",
"city":"陕西西安",
"country": "中国"
},
"links": [
{
"name": "B站",
"url": "https://www.bilibili.com/"
},
{
"name": "4399",
"url": "https://www.4399.com/"
},
{
"name": "百度",
"url": "https://www.baidu.com/"
}
]
}
测试代码:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<style>
/*未加载时白屏*/
[v-cloak] {
display: none;
}
style>
head>
<body>
<h1>测试h1>
<div id="vue" v-cloak>
<div>{{info.name}}div>
<h1>{{info.address.country}}h1>
<a v-bind:href="info.links[0].url">点我a>
div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js">script>
<script src="https://unpkg.com/axios/dist/axios.js">script>
<script type="text/javascript">
var vm = new Vue({
el: "#vue",
data(){
return{
info: {
name: null,
address: {
street: null,
city: null,
country: null
},
links: [{
name: null,
url: null
}]
}
}
},
mounted() { // 钩子函数,链式编程,ES6新特性
axios.get("../static/js/data.json").then(response=>(this.info=response.data))
}
});
script>
body>
html>
说明:
Ajax
响应回来的数据格式匹配!官方文档:https://cn.vuejs.org/v2/guide/instance.html#生命周期图示;
Vue实例有一个完整的生命周期,也就是从开始创建初女台化数据、编译模板、挂载DOM、渲染一更新一渲染、卸载等一系列过程,我们称这是Vue的生命周期。通俗说就是Vue实例从创建到销毁的过程,就是生命周期。
在Vue的整个生命周期中,它提供了一系列的事件,可以让我们在事件触发时注册JS方法,可以让我们用自己注册的JS方法控制整个大局,在这些事件响应方法中的this直接指向的是Vue的实例。
什么是计算属性?
计算属性的重点突出在属性两个字上(属性是名词),首先它是个属性其次这个属性有计算的能力(计算是动词),这里的计算就是个函数:简单点说,它就是一个能够将计算结果缓存起来的属性(将行为转化成了静态的属性),仅此而已;可以想象为缓存!
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<h1>测试h1>
<div id="app">
<p>时间戳:{{test1()}}p>
<p>时间戳:{{test2}}p>
div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js">script>
<script type="text/javascript">
var vm = new Vue({
el:"#app",
/*Model:数据*/
data:{
message:null
},
methods: {
test1: function () {
return Date.now();
}
},
computed: {
test2: function () {
this.message;
return Date.now();
}
}
});
script>
body>
html>
注意:methods和computed里的东西不能重名!
说明:
结论:
在Vue.js中我们使用元素作为承载分发内容的出口,作者称其为插槽,可以应用在组合组件的场景中;
比如准备制作一个待办事项组件(todo) , 该组件由待办标题(todo-title) 和待办内容(todo-items)组成,但这三个组件又是相互独立的,该如何操作呢?
代码实例如下:
1、先定义一个待办事项的组件;
<div id="app">
<todo>todo>
div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js">script>
<script type="text/javascript">
Vue.component('todo',{
template:'\
代办事项
\
\
- 数组
\
\
'
})
script>
2、让代办事项的标题和值实现动态绑定,也就是将上面的代码中的p标签和li标签留出一个插槽,即slot;
Vue.component('todo',{
template:'<div>\
<slot name="todo-title">slot>\
<ul>\
<slot name="todo-items">slot>\
ul>\
div>'
});
3、定义一个名为todo-title的待办标题组件 和 todo-items的待办内容组件;
Vue.component('todo-title',{
props:['title'],
template:'<div>{{title}}div>'
});
Vue.component("todo-items",{
props:["item"],
template:"<li>{{item}}li>"
});
4、实例化Vue并初始化数据,并将这些值,通过插槽插入;
var vm = new Vue({
el:"#vue",
data:{
title:"系列课程",
todoItems:['Java','PHP','Python']
}
});
<div id="vue">
<todo>
<todo-title slot="todo-title" :title="title">todo-title>
<todo-li slot="todo-li" v-for="item in todoItems":item="item">todo-li>
todo>
div>
说明:todo-title和todo-items组件分别被分发到了todo组件的todo-title和todo-items插槽中。
通以上代码不难发现,数据项在Vue的实例中, 但删除操作要在组件中完成, 那么组件如何才能删除Vue实例中的数据呢?此时就涉及到参数传递与事件分发了, Vue为我们提供了自定义事件的功能很好的帮助我们解决了这个问题;
使用this.$emit(‘自定义事件名’, 参数) , 操作过程如下:
1、在vue的实例中增加了methods对象并定义了一个名为removeTodoltems的方法;
var vm = new Vue({
el:"#vue",
data:{
title:"系列课程",
todoItems:['Java','PHP','Python']
},
methods: {
removeItem: function (index){
console.log("delete from " + this.todoItems[index] + " is OK");
this.todoItems.splice(index, 1);
}
}
});
2、修改todo-li待办内容组件的代码,增加一个删除按钮,并且绑定事件!
说明:通过以下代码实例可以直接测试,测试结果为当点击按钮时,组件中所绑定的方法会执行Vue实例中方法名一致的方法(弹出信息为“111”的警示框),但现在的问题所在是Vue组件中的methods不能直接绑定到Vue实例中的方法!
Vue.component("todo-li",{
props:["item",'index'],
template:"{{index}}-{{item}} ",
// 只能绑定到当前组件的方法
// 但是现在的需求是想办法让这个组件的方法绑定到Vue对象中的方法!
methods: {
remove: function () {
alert("111")
}
}
});
3、修改todo-li待办内容组件的HTML代码,增加一个自定义事件,比如叫remove,可以和组件的方法绑定,然后绑定到vue的方法!
<todo-li slot="todo-items"
v-for="(item,index) in todoItems"
:item_p="item"
:index_p="index"
v-on:remove="removeItems(index)">
todo-items>
v-on自定义了一个remove的事件,所绑定的方法为Vue实例中的removeItems方法,并传入了index作为参数,而index在之前就已经进行了绑定,所以这个index也是可以进行传递的!
4、修改组件中的methods:
Vue.component("todo-li",{
props:["item",'index'],
// 这里需要将触发事件的方法修改为methods中的方法
template:"{{index}}-{{item}} ",
methods: {
remove: function (index) {
this.$emit('remove', index);
alert("111")
}
}
通过this.$emit(‘remove’, index);就可以在Vue组件中联系到Vue实例中的removeItem方法,具体过程可以这样理解:
核心:数据驱动,组件化
优点:借鉴了AngularJS的模块化开发和React的虚拟Dom,虚拟Dom就是把Demo操作放到内存中执行;
常用的属性:
组件化:
遵循SoC关注度分离原则,Vue是纯粹的视图框架,并不包含,比如Ajax之类的通信功能,为了解决通信问题,我们需要使用Axios框架做异步通信;
说明:
Vue的开发都是要基于NodeJS,实际开发采用Vue-cli脚手架开发,vue-router路由,vuex做状态管理;Vue UI,界面我们一般使用ElementUI(饿了么出品),或者ICE(阿里巴巴出品)来快速搭建前端项目~~
官网:
什么是vue-cli?
vue-cli官方提供的一个脚手架,用于快速生成一个vue的项目模板;
预先定义好的目录结构及基础代码,就好比咱们在创建Maven项目时可以选择创建一个骨架项目,这个估计项目就是脚手架,我们的开发更加的快速;
项目的功能
统一的目录结构
本地调试
热部署
单元测试
集成打包上线
Node.js: http://nodejs.cn/download/,安装就是无脑的下一步就好,安装在自己的环境目录下;
Git:https://git-scm.com/doenloads;
镜像:https://npm.taobao.org/mirrors/git-for-windows/;
确认nodejs安装成功后使用命令窗口输入下面的指令:
这个npm,就是一个软件包管理工具,就和linux下的apt软件安装差不多!
安装Node.js淘宝镜像加速器(cnpm): 安装这个主要是为了提升下载速度~
# -g 就是全局安装
npm install cnpm -g
# 或使用如下语句解决npm速度慢的问题
npm install --registry=https://registry.npm.taobao.org
安装完成后可以使用cnpm -v
指令来查看该加速器是否安装成功!安装的过程可能有点慢~,耐心等待!虽然安装了cnpm,但是尽量少用!
安装的位置:C:\Users\administrator\AppData\Roaming\npm
;
安装vue-cli
cnpm install -g vue-cli
# 测试是否安装成功#查看可以基于哪些模板创建vue应用程序,通常我们选择webpack
vue list
1.创建一个Vue项目,随便建立一个空的文件夹在电脑上,这里在D盘下新建一个目录;
D:\Project\vue-study;
2.创建一个基于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,我们手动执行;运行结果!
3、初始化并运行;
# 切换至根目录
cd myvue
# 安装
npm install
# 打包运行
npm run dev
运行第三行命令,成功之后会显示以下内容:
根据提示访问到http://localhost:8080/,假设此时访问到的页面为以下内容说明成功运行:
WebPack是一款模块加载器兼打包工具, 它能把各种资源, 如JS、JSX、ES 6、SASS、LESS、图片等都作为模块来处理和使用。安装它的目的是为了将ES6的规范全部打包成ES5规范,也就是让绝大部分的浏览器都能运行!
npm install webpack -g
npm install webpack-cli -g
测试是否安装成功:(也有可能在运行第一行命令时,会将webpack和webpack-cli的版本信息都打印出来)
webpack -v
webpack-cli -v
1、创建项目(新建一个文件夹并用IDEA打开即可);
2、创建一个名为modules的目录,用于放置JS模块等资源文件;
3、在modules下创建模块文件,如hello.js,用于编写JS模块相关代码;
//暴露一个方法:sayHi
exports.sayHi = function(){
document.write("Hello Webpack");
}
4、在modules下创建一个名为main.js的入口文件,用于打包时设置entry属性;
//require 导入一个模块,就可以调用这个模块中的方法了
var hello = require("./hello");
hello.sayHi();
5、在项目目录下创建webpack.config.js配置文件,使用webpack(假设IDEA默认以管理员方式执行,那也可以在IDEA的Terminal窗口执行该命令)命令打包;
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>webpacktitle>
head>
<body>
<script src="dist/js/bundle.js">script>
body>
html>
注意:使用该方法进行项目测试的目的仅是为了便于理解”前端就是一个个模块拼接而成“的概念,正常开发并不会单纯这样建立一个项目!
注:学习的时候,尽量的打开官方的文档!
Vue Router是Vue.js官方的路由管理器。它和Vue.js的核心深度集成, 让构建单页面应用变得易如反掌。包含的功能有:
注:基于第一个vue-cli进行测试学习!
在学习之前,先查看node modules中是否存在vue-router;
vue-router是一个插件包, 所以我们还是需要用n pm/cn pm来进行安装的。打开命令行工具,进入你的项目目录,输入下面命令。
s
如果在一个模块化工程中使用它,必须要通过Vue.use()明确地安装路由功能:
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter);
注意:在进行测试之前,需要删除一些无关的内容!在该项目目录下,components
目录下存放我们自己编写的组件!
1、 定义一个Content.vue
的组件;
内容页
2、定义一个Main.vue
组件;
首页
注意:这两个组件可以理解为两个页面,需要注意的是,Vue中一个标签下只能有一个根标签,不能同时有多高标签;
3、安装路由,在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:[
{
// 路由路径(这里可以想象成Spring中的@RequestMapping)
path:'/content',
//路由名称
name:'content',
//跳转到组件
component:Content
},
{
path:'/main',
name:'main',
component:Main
},
]
});
4、在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:' '
});
6、在App.vue
中使用路由;
首页
内容
再次提醒:学习的时候,尽量的打开官方的文档!
Vue Router是Vue.js官方的路由管理器。它和Vue.js的核心深度集成, 让构建单页面应用变得易如反掌。包含的功能有:
注意:命令行都要使用管理员模式运行!
1、创建一个名为hello-vue的工程vue init webpack hello-vue
;
2、安装依赖, 我们需要安装vue-router、element-ui、sass-loader和node-sass四个插件;
#进入工程目录
cd hello-vue
#安装vue-routern
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、将不使用的无关代码删除,并在在源码目录中创建如下结构:
assets:用于存放资源文件
components:用于存放Vue功能组件
views:用于存放Vue视图组件
router:用于存放vue-router配置
4、创建首页视图,在views目录下创建一个名为Main.vue的视图组件;
首页
5、创建登录页视图在views目录下创建名为Login.vue的视图组件,其中el-*的元素为ElementUI组件;
欢迎登录
登录
请输入账号和密码
5、创建路由,在router目录下创建一个名为index.js
的vue-router路由配置文件;
//导入vue
import Vue from 'vue';
import VueRouter from 'vue-router';
//导入组件
import Main from "../views/Main";
import Login from "../views/Login";
//使用
Vue.use(VueRouter);
//导出
export default new VueRouter({
routes: [
{
//登录页
path: '/main',
component: Main
},
//首页
{
path: '/login',
component: Login
},
]
})
6、APP.vue;
7、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 ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(router)
Vue.use(ElementUI)
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
render:h=>h(App)
})
测试:在浏览器打开 http://localhost:8080/#/login
如果出现错误: 可能是因为sass-loader的版本过高导致的编译错误,当前最高版本是8.0.2,需要退回到7.3.1!去package.json文件里面的 "sass-loader"的版本更换成7.3.1,然后重新cnpm install就可以了;
嵌套路由又称子路由,在实际应用中,通常由多层嵌套的组件组合而成。
1、 创建用户信息组件,在 views/user 目录下创建一个名为 Profile.vue 的视图组件;
个人信息
2、在用户列表组件在 views/user 目录下创建一个名为 List.vue 的视图组件;
用户列表
3、 修改首页视图,我们修改 Main.vue 视图组件,此处使用了 ElementUI 布局容器组件,代码如下:
用户管理
个人信息
用户列表
内容管理
分类管理
内容列表
个人信息
退出登录
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 UserList from "../views/user/List";
import UserProfile from "../views/user/Profile";
//使用
Vue.use(VueRouter);
//导出
export default new VueRouter({
routes: [
{
//登录页
path: '/main',
component: Main,
// 写入子模块
children: [
{
path: '/user/profile',
component: UserProfile,
}, {
path: '/user/list',
component: UserList,
},
]
},
//首页
{
path: '/login',
component: Login
},
]
})
第一种取值方式:
1、 修改路由配置, 主要是router下的index.js中的 path 属性中增加了 :id 这样的占位符;
{
path: '/user/profile/:id',
name:'UserProfile',
component: UserProfile
}
2、传递参数;
此时我们在Main.vue中的route-link位置处 to 改为了 :to,是为了将这一属性当成对象使用,注意 router-link 中的 name 属性名称 一定要和 路由中的 name 属性名称 匹配,因为这样 Vue 才能找到对应的路由路径;
个人信息
3、在要展示的组件Profile.vue中接收参数 使用 {{$route.params.id}}来接收;
个人信息
{{$route.params.id}}
第二种取值方式:使用props 减少耦合
1、修改路由配置 , 主要在router下的index.js中的路由属性中增加了 props: true 属性;
{
path: '/user/profile/:id',
name:'UserProfile',
component: UserProfile,
props: true
}
2、传递参数和之前一样 在Main.vue中修改route-link地址;
个人信息
3、在Profile.vue接收参数为目标组件增加 props 属性;
个人信息
{{ id }}
vue 中的重定向是作用在路径不同但组件相同的情况下,比如:
在router下面index.js的配置:
{
path: '/main',
name: 'Main',
component: Main
},
{
path: '/goHome',
redirect: '/main'
}
说明:这里定义了两个路径,一个是 /main ,一个是 /goHome,其中 /goHome 重定向到了 /main 路径,由此可以看出重定向不需要定义组件;
使用的话,只需要在Main.vue设置对应路径即可;
回到首页
路由模式有两种:
修改index.js路由配置,代码如下:
export default new Router({
mode: 'history',
routes: [
]
});
自定义404页面:
1、创建一个NotFound.vue视图组件;
404,你的页面走丢了
2、修改路由配置index.js;
import NotFound from '../views/NotFound'
{
path: '*',
component: NotFound
}
实例测试:(Profile.vue)
export default {
name: "UserProfile",
beforeRouteEnter: (to, from, next) => {
console.log("准备进入个人信息页");
next();
},
beforeRouteLeave: (to, from, next) => {
console.log("准备离开个人信息页");
next();
}
}
参数说明:
在钩子函数中使用异步请求:
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 中进行异步请求(Profile.vue);
export default {
//第二种取值方式
// props:['id'],
name: "UserProfile",
//钩子函数 过滤器
beforeRouteEnter: (to, from, next) => {
//加载数据
console.log("进入路由之前")
next(vm => {
//进入路由之前执行getData方法
vm.getData()
});
},
beforeRouteLeave: (to, from, next) => {
console.log("离开路由之前")
next();
},
//axios
methods: {
getData: function () {
this.axios({
method: 'get',
url: 'http://localhost:8080/static/mock/data.json'
}).then(function (response) {
console.log(response)
})
}
}
}
5、经过测试后可以发现,当页面跳转至Profile.vue路由时,控制台输出了data.json文件中的数据,这就意味着,在该页面下,可以从文件中拿去数据并在页面中展示!
export default {
name: “NotFound”
}
2、修改路由配置index.js;
```js
import NotFound from '../views/NotFound'
{
path: '*',
component: NotFound
}
实例测试:(Profile.vue)
export default {
name: "UserProfile",
beforeRouteEnter: (to, from, next) => {
console.log("准备进入个人信息页");
next();
},
beforeRouteLeave: (to, from, next) => {
console.log("准备离开个人信息页");
next();
}
}
参数说明:
在钩子函数中使用异步请求:
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 中进行异步请求(Profile.vue);
export default {
//第二种取值方式
// props:['id'],
name: "UserProfile",
//钩子函数 过滤器
beforeRouteEnter: (to, from, next) => {
//加载数据
console.log("进入路由之前")
next(vm => {
//进入路由之前执行getData方法
vm.getData()
});
},
beforeRouteLeave: (to, from, next) => {
console.log("离开路由之前")
next();
},
//axios
methods: {
getData: function () {
this.axios({
method: 'get',
url: 'http://localhost:8080/static/mock/data.json'
}).then(function (response) {
console.log(response)
})
}
}
}
5、经过测试后可以发现,当页面跳转至Profile.vue路由时,控制台输出了data.json文件中的数据,这就意味着,在该页面下,可以从文件中拿去数据并在页面中展示!