Introduction to Vue.js
Vue.js 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是 Vue 被设计为可以自底向上逐层应用。
Vue.js 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一 方面,当与 现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。
自底向上逐层应用:作为渐进式框架要实现的目标就是方便项目增量开发(即插即用)。
官方网站: https://cn.vuejs.org/v2/guide/
在 html 页面使用 script 引入 vue.js 的库即可使用:
Vue-CLI
脚手架:使用 vue.js 官方提供的 CLI 脚本架可以方便地去创建 vue.js 工程雏形。
创建一个 vue_test
目录,并且在目录下创建 01_vue入门程序.html
文件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=<device-width>, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
<!-- 引入 vue.js -->
<!-- <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script> -->
<script src="js/vue.min.js"></script>
</head>
<body>
<!-- 创建 id 为 app 的 div -->
<div id="app">{{name}}</div>
</body>
<script>
// 创建 vue 实例
var VM = new Vue({
el: "#app",
data: {
name: "Hello Vue",
},
});
</script>
</html>
{{}}
插值表达式:通常用来获取 Vue.js 实例中定义的数据(data);属性节点中不能够使用插值表达式。
el
挂载点:定义 Vue.js 实例挂载的元素节点,表示 vue.js 接管该区域。
Vue 的作用范围 :Vue 会管理 el 选项中的元素及其内部元素。
选择挂载点时,可以使用其他选择器,但是建议使用 ID 选择器。
挂载点可以设置其他的 DOM 元素进行关联,但是建议选择 DIV,不能使用 HTML 和 Body 标签。
data
数据对象:Vue 中用到的数据定义在 data 中;data 中可以写复杂类型;渲染复杂类型数据的时候遵守 js 语法。
<body>
<!-- 创建 id 为 app 的 div -->
<div id="app">
{{name}} <br>
{{school.name}} {{school.number}} <br>
<ul>
<li>{{names[0]}}</li>
<li>{{names[1]}}</li>
<li>{{names[2]}}</li>
</ul>
</div>
</body>
<script>
// 创建 vue 实例
var VM = new Vue({
el: "#app",
data: {
name: "Hello Vue",
// 对象类型
school: {
name: "学校名称",
number: "100000"
},
// 数组类型
names: ["张人大", "刘小明", "赵小红"]
},
});
</script>
Vue 中的声明式渲染,简单理解就是 Vue 将声明的数据渲染到 HTML。
<body>
<div id="app">
<h2>{{name}}</h2>
</div>
</body>
<!-- <script src="js/jquery-1.8.3.min.js"></script>
<script>
$(document).ready(function() {
$("#app").append("<h2>Hello World</h2>")
});
</script> -->
<script src="js/vue.min.js"></script>
<script>
var VM = new new Vue({
el: "#app",
data: {
name: "Hello World!!",
},
});
</script>
Vue 指令是带有 v-
前缀的特殊属性;通过指令来操作 DOM 元素 。
作用:获取 data 数据,设置标签的内容。
注意:默认写法会替换全部内容,使用插值表达式 {{}}
可以替换指定内容。
<body>
<div id="app">
<h2>{{message}}高级</h2>
<!-- v-text 获取 data 数据,设置标签的内容,会覆盖标签里的内容体-->
<h2 v-text="message">高级</h2>
<!-- 拼接字符串 -->
<h2 v-text="message+1"></h2>
<h2 v-text="message+'abc'"></h2>
</div>
</body>
<script src="js/vue.min.js"></script>
<script>
var VM = new new Vue({
el: "#app",
data: {
message: "Java程序员"
}
});
</script>
作用: 设置元素的 innerHTML
(可以向元素中写入新的标签)
<body>
<div id="app">
<!-- 获取普通文本 -->
<h2>{{message}}</h2>
<h2 v-text="message"></h2>
<h2 v-html="message"></h2>
<!-- 设置元素的 innerHTML -->
<h2 v-html="url"></h2>
<h2 v-text="url"></h2>
</div>
</body>
<script src="js/vue.min.js"></script>
<script>
var VM = new new Vue({
el: "#app",
data: {
message: "Java程序员",
url: "<a href='https://www.baidu.com'>百度一下</a>"
}
});
</script>
作用:为元素绑定事件, 比如: v-on:click
可以简写为 @click="方法"
绑定的方法定义在 VUE 实例的 method 属性中
<body>
<div id="app">
<!-- 使用 v-on 绑定 click 点击事件 -->
<input type="button" value="Button" v-on:click="methodName">
<!-- 使用 @ 符号也可以绑定-->
<input type="button" value="Button" @click="methodName">
<!-- 双击事件 -->
<input type="button" value="双击击按钮" @dblclick="show">
<!-- 绑定点击事件 -->
<h2 @click="changeName">{{food}}</h2>
</div>
</body>
<script src="js/vue.min.js"></script>
<script>
var VM = new new Vue({
el: "#app",
data: {
food: "Turkey"
},
// 通过 methods,专门存放 Vue 中的方法
methods: {
methodName: function() {
alert("提醒!");
},
show: function() {
alert("Double Click");
},
changeName: function() {
console.log(this.food);
// 在 VUE 中不需要考虑如何更改 DOM 元素,
// 重点放在数据更新之后,使用数据的那个元素会同步更新
this.food+=" Delicious!";
}
}
});
</script>
传递自定义参数:函数调用传参
事件修饰符:对事件触发的方式进行限制
<body>
<div id="app">
<!-- 函数传参 -->
<input
type="button"
value="礼物刷起来"
@click="showTime(111, 'test111')"
/>
<!-- 事件修饰符指定哪些方式可以触发事件 -->
<input type="text" @keyup.enter="hiFunction" />
</div>
</body>
<script src="js/vue.min.js"></script>
<script>
var VM = new Vue({
el: "#app",
data: {},
methods: {
showTime: function (p1, p2) {
console.log(p1);
console.log(p2);
},
hiFunction: function () {
alert("How are you");
},
},
});
</script>
.修饰符
可以对事件进行限制.enter
可以限制触发的按键为回车data
中定义数据:比如 num
值为 1
methods
中添加两个方法:比如 add
(递增),sub
(递减){{}}
将 num
设置给 span
标签v-on
将 add
、sub
分别绑定给加、减按钮10
停止0
停止<body>
<body>
<div id="app">
<!-- 计算功能区域 -->
<div>
<input type="button" value="+" v-on:click="add"/>
<span>{{num}}</span>
<input type="button" value="-" @click="sub"/>
</div>
</div>
</body>
<script src="js/vue.min.js"></script>
<script>
//创建 VUE 实例
var VM = new Vue({
el: "#app",
data: {
num:
},
methods: {
add: function() {
if(this.num < ) {
this.num++;
} else {
alert("Number is at Maximum");
}
},
sub: function() {
if(this.num > ) {
this.num--;
} else {
alert("Number is Minimum");
}
}
}
});
</script>
</body>
总结:
el
挂载点,data
数据,methods
方法v-on
指令的作用是绑定事件,简写为 @
this
关键字,获取 data
中的数据v-text
与 {{}}
的作用都是用来设置元素的文本值作用:v-show
指令,根据真假值切换元素的显示状态
<body>
<div id="app">
<input type="button" value="切换状态" @click="changeShow" />
<img v-show="isShow" src="img/car.gif" alt="" />
<img v-show="age > 18" src="img/car.gif" />
</div>
</body>
<script src="js/vue.min.js"></script>
<script>
var VM = new Vue({
el: "#app",
data: {
isShow: true,
age:
},
methods: {
changeShow: function() {
// 触发方法,对 isShow 进行取反
this.isShow = !this.isShow;
}
}
});
</script>
根据表达式的真假,切换元素的显示和隐藏(操作是 dom
)
<body>
<div id="app">
<input type="button" value="切换状态" @click="changeShow" />
<img v-if="isShow" src="img/car.gif" />
</div>
</body>
<script src="js/vue.min.js"></script>
<script>
var VM = new Vue({
el: "#app",
data: {
isShow: false,
},
methods: {
changeShow: function () {
this.isShow = !this.isShow;
},
},
});
</script>
dom
元素,来切换显示状态true
时元素存在于 dom
树,为 false
则从 dom
树中移除v-show
,反之使用 v-if
作用:设置元素的属性(比如:src
,title
,class
)
<body>
<div id="app">
<img src="img/buddha.jpg" alt="" />
<!-- 使用 v-bind 设置 src 属性 -->
<img v-bind:src="imgSrc" />
<!-- v-bind 简写为冒号-->
<img :src="imgSrc" :title="imgTitle" />
<!-- 设置 class -->
<div :style="{ fontSize: size+'px' }">v-bind 指令</div>
</div>
</body>
<script src="js/vue.min.js"></script>
<script>
var VM = new Vue({
el: "#app",
data: {
imgSrc: "img/buddha.jpg",
imgTitle: "Buddha",
size: ,
},
});
</script>
v-bind
指令的作用是:为元素绑定属性v-bind:属性名
,可以简写为 :属性名
作用:根据数据生成列表结构
<body>
<div id="app">
<input type="button" value="添加数据" @click="add" />
<input type="button" value="移除数据" @click="remove" />
<ul>
<!-- 在 li 标签中获取数组的元素 -->
<li v-for="(item, index) in arr">
{{index+1}}城市:{{item}}
</li>
</ul>
<!-- 使用h2标签显示 -->
<h2 v-for="p in persons">
{{p.name}}
</h2>
</div>
</body>
<script src="js/vue.min.js"></script>
<script>
var VM = new Vue({
el: "#app",
data: {
// 数组
arr: ["上海", "北京", "广东", "深圳"],
// 对象数组
persons: [
{ name: "张人大" },
{ name: "刘小明" },
{ name: "赵小红" },
],
},
methods: {
add: function() {
// 向数组添加元素
this.persons.push({name: "小郑"});
},
remove: function() {
// 移除数据
this.persons.shift();
}
}
});
</script>
v-for
结合使用,数组有两个常用方法:push()
向数组末尾添加一个或多个元素;shift()
把数组中的第一个元素删除(item, index) in 数据
item
和 index
可以结合其他指令一起使用MVVM
是 Model-View-ViewModel
的缩写,它是一种基于前端开发的架构模式
MVVM
模式将页面分层了 M
、V
、和 VM
,解释为:
Model
:负责数据存储
View
:负责页面展示
View Model
:负责业务逻辑处理(比如 Ajax 请求等),对数据进行加工后交给视图展示
<body>
<div id="app">
<!-- View 视图部分 -->
<h2>{{name}}</h2>
</div>
</body>
<script src="js/vue.min.js"></script>
<script>
// 创建的 vue 实例就是 ViewModel
var VM = new Vue({
el: "#app",
// data 就是 MVVM 模式中的 model
data: {
name: "hello",
},
});
</script>
首先,我们将 View Model 的 DOM Listeners 和 Data Bindings 看作两个工具,它们是实现双向绑定的关键:
MVVM 的思想主要是为了让开发更加方便,因为 MVVM 提供了数据的双向绑定。
作用:获取和设置表单元素的值,实现双向数据绑定。
填写表单:当用户填写表单时,View 的状态就被更新了,此时 MVVM 框架可以自动更新 Model 的状态,就相当于把 Model 和 View 做了双向绑定。绑定的数据会和表单元素值相关联。
<body>
<div id="app">
<input type="button" value="update message" @click="update" />
<!-- View 视图演示自动单向数据绑定 -->
<input type="text" v-bind:value="message" />
<br>
<!-- v-model 实现自动双向数据绑定 -->
<input type="text" v-model="message" />
<input type="text" v-model="password" />
<h2>{{message}}</h2>
<h2>{{password}}</h2>
</div>
</body>
<script src="js/vue.min.js"></script>
<script>
// VM 业务逻辑控制
var VM = new Vue({
el: "#app",
// Model 数据存储
data: {
message: "Where are you from?",
password: ,
},
methods: {
update: function () {
this.message = "China";
},
},
});
</script>
v-for
数组)v-model
双向绑定)v-on
.enter
事件修饰符)methods
中添加一个删除的方法,使用 splice
函数进行删除list
数组的长度,就是信息的个数<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>记事本</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta name="robots" content="noindex, nofollow" />
<meta name="googlebot" content="noindex, nofollow" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" type="text/css" href="vue_text/css/index.css" />
</head>
<body>
<!-- VUE 示例接管区域 -->
<section id="app">
<!-- 输入框 -->
<header class="header">
<h1>VUE 记事本</h1>
<input autofocus="autofocus" autocomplete="off" placeholder="输入日程" class="new-todo" v-model="inputValue"
@keyup.enter="add" />
</header>
<!-- 列表区域 -->
<section class="main">
<ul class="listview">
<!-- 使用 v-for 指令生成列表结构 -->
<li class="todo" v-for="(item, index) in list">
<div class="view">
<span class="index">{{index+1}}</span>
<label>{{item}}</label>
<!-- 删除操作传递 index -->
<button class="destroys" @click="remove(index)"></button>
</div>
</li>
</ul>
</section>
<!-- 统计和清空 -->
<footer class="footer">
<span class="todo-count">
<strong>{{list.length}}</strong>
items left
</span>
<button class="clear-completed" @click="clear()">
Clear
</button>
</footer>
</section>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var VM = new Vue({
el: "#app",
data: {
list: ["Coding", "Sleep", "Eat"],
inputValue: "996 or 997"
},
methods: {
add: function () {
this.list.push(this.inputValue);
},
remove: function (index) {
this.list.splice(index, );
},
clear: function () {
this.list = [];
}
}
});
</script>
</body>
</html>
Ajax 是指一种创建交互式网页应用的开发技术
Ajax = 异步 JavaScript + XML
Ajax 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新(局部更新)。传统的网页如果需要更新内容,必须重载整个网页页面。 简单记:Ajax 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术,维护用户体验性,进行网页的局部刷新.。
同步访问:客户端必须等待服务器端的响应,在等待过程中不能进行其他操作 异步访问:客户端不需要等待服务的响应,在等待期间浏览器可以进行其他操作
AjaxServlet
@WebServlet("/ajax")
public class AjaxServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取请求参数
String username = req.getParameter("name");
// 模拟业务操作的延时
try {
Thread.sleep();
} catch (InterruptedException e) {
e.printStackTrace();
}
// 打印 username
System.out.println(username);
resp.getWriter().write("Hello Ajax");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
}
ajax.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Ajax</title>
</head>
<body>
<input type="text">
<input type="button" value="JQuery is sending Asynchronous request" onclick="run1()">
</body>
<script src="jquery-1.8.3.min.js"></script>
<script>
function run1() {
$.ajax({
url: "/hello_maven/ajax",
async: true,
data: {
name: "Renda"
},
type: "post",
dataType: "text",
success: function (res) {
console.log(res);
alert("sucess: " + res);
},
error: function () {
alert("error");
}
});
}
</script>
</html>
VUE 中结合网络数据进行应用的开发:
ajax
,进行封装之后使用更加方便axios
作用:在浏览器中可以帮助我们完成 ajax
异步请求的发送Vue 2.0 之后推荐用 axios
替换 JQuery ajax
。
导包:<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
GET:axios.get(地址?key=value&key2=value2).then(function(response){},function(error){});
POST:axios.post(地址,{key:value,key2:value2}).then(function(response){},function(error){});
axios
必须导包才能使用get
或者 post
方法就可以发送请求then
方法中的回调函数会在请求成功或者请求失败的时候触发请求地址:https://autumnfish.cn/api/joke/list
请求方法:get
请求参数:num
(笑话条数,数字)
响应内容:随机笑话
请求地址:https://autumnfish.cn/api/user/reg 请求方法:post 请求参数:username(用户名,字符串) 响应内容:注册成功或失败
请求地址:http://wthrcdn.etouch.cn/weather_mini 请求方法:get 请求参数:city(要查询的城市名称) 响应内容:天气信息
<body>
<div id="app">
<input type="button" value="点击获取一个笑话" @click="getJoke" />
<input type="button" value="Post请求" @click="postRegister">
<p>{{joke}}</p>
</div>
</body>
<script src="vue_text/js/vue.min.js"></script>
<script src="vue_text/js/axios.min.js"></script>
<script>
var VM = new Vue({
el: "#app",
data: {
joke: "This is a Joke",
},
methods: {
getJoke: function () {
var jokeThis = this;
// 异步访问
axios.get("https://autumnfish.cn/api/joke").then(
// 在回调函数内部,this 无法正常使用,需要提前保存起来
function (resp) {
console.log(jokeThis.joke);
jokeThis.joke = resp.data;
},
function (error) {
alert("error: " + error);
}
);
},
postRegister: function () {
axios.post("https://autumnfish.cn/api/user/reg", { username: "张人大" }).then(
function (resp) {
console.log(resp);
alert(resp.data);
},
function (error) {
console.log(error);
alert("error: " + error.data);
}
);
}
}
});
</script>
axios
回调函数中 this
指向已经改变,无法访问 data
中的数据。
解决方案:将 this
进行保存,回调函数中直接使用保存的 this
即可。
js/main.js
var VM = new Vue({
el: "#app",
data: {
city: "",
// 定义数组保存天气信息
weatherList: [],
},
// 编写查询天气的方法
methods: {
searchWeather: function () {
console.log("天气查询");
console.log(this.city);
var savedThis = this;
// 调用接口
axios.get("http://wthrcdn.etouch.cn/weather_mini?city=" + this.city).then(
function (resp) {
console.log(resp)
// 获取天气信息保存到 weatherList
savedThis.weatherList = resp.data.data.forecast;
},
function (error) {
console.log(error);
}
);
},
},
});
HTML 代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>天气查询</title>
<link rel="stylesheet" href="css/reset.css" />
<link rel="stylesheet" href="css/index.css" />
</head>
<body>
<div class="wrap" id="app">
<div class="search_form">
<div class="logo">天气查询</div>
<div class="form_group">
<input
type="text"
class="input_txt"
placeholder="请输入要查询的城市"
v-model="city"
@keyup.enter="searchWeather"/>
<button class="input_sub" @click="searchWeather">回车查询</button>
</div>
</div>
<ul class="weather_list">
<li v-for="item in weatherList">
<div class="info_type">
<span class="iconfont">{{item.type}}</span>
</div>
<div class="info_temp">
<b>{{item.low}}</b>
~
<b>{{item.high}}</b>
</div>
<div class="info_date"><span>{{item.date}}</span></div>
</li>
</div>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 官网提供的 axios 在线地址 -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<!-- 自定义 main.js -->
<script src="js/main.js"></script>
</body>
</html>
axios
回调函数中的 this
的指向改变,无法正常使用,需要另外保存一份当网络较慢,网页还在加载 Vue.js ,而导致 Vue 来不及渲染,这时页面就会显示出 Vue 源代码,可以使用 v-cloak 指令来解决这一问题。
v-cloak
指令:解决插值表达式闪烁问题。
<!-- 添加样式 -->
<style>
/*
通过属性选择器,设置添加了 v-cloak
*/
[v-cloak] {
display: none;
}
</style>
<!-- 在 id 为 app 的 div 中添加 v-cloak -->
<div class="wrap" id="app" v-cloak>
...
</div>
computed
的作用:减少运算次数,缓存运算结果,运用于重复相同的计算。
<body>
<div id="app">
<h1>{{res()}}</h1>
<h2>{{res()}}</h2>
<h1>{{resComputed}}</h1>
<h2>{{resComputed}}</h2>
</div>
</body>
<script src="js/vue.min.js"></script>
<script>
var VM = new new Vue({
el: "#app",
data: {
a: ,
b: ,
},
methods: {
res: function() {
console.log("res method had been executed");
return this.a * this.b;
},
},
computed: {
resComputed: function() {
console.log("resComputed method had been executed.")
return this.a * this.b;
}
}
});
</script>
定义函数也可以实现与 计算属性相同的效果,都可以简化运算;
不同的是计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。
过滤器是对即将显示的数据做进一步的筛选处理,然后进行显示;值得注意的是过滤器并没有改变原 来的数据,只是在原数据的基础上产生新的数据。
数据加工车间,对值进行筛选加工。
过滤器使用位置:
{{ msg | filterA }}
:msg
是需要处理的数据,filterA
是过滤器, |
这个竖线是管道,通过这个管道将数据传输给过滤器进行过滤加工操作。v-bind
绑定的值的地方:
{{ msg }}
<!-- 局部过滤器 -->
<body>
<div id="app">
<!-- 使用插值表达式,调用过滤器 -->
<p>Computer Price: {{price | addIcon}}</p>
</div>
</body>
<script src="js/vue.min.js"></script>
<script>
var VM = new Vue({
el: "#app",
data: {
price: ,
},
methods: {
},
computed: {
},
// 局部过滤器 在 vue 实例的内部创建 filter
filters: {
addIcon(value) {
return "$" + value;
}
}
})
</script>
<!-- 全局过滤器 -->
<body>
<div id="app">
<p>{{user.name | changeName}}</p>
</div>
</body>
<script src="js/vue.min.js"></script>
<script>
// 在创建 vue 实例之前创建全局过滤器
Vue.filter("changeName", function(value) {
// Change the first letter of the name to uppercase
return value.charAt().toUpperCase() + value.slice();
});
var VM = new Vue({
el: "#app",
data: {
user: { name: "renda" }
}
})
</script>
v-bind
表达式。作用:当有一些数据需要随着其它数据变动而变动时,可以使用侦听属性;它用于观察 Vue 实例上的数据变动。
<!-- 监听数字变化 -->
<body>
<div id="app">
<h2>计数器:{{count}}</h2>
<input type="button" @click="count++" value="CLICK">
</div>
</body>
<script src="js/vue.min.js"></script>
<script>
var VM = new Vue({
el: "#app",
data: {
count: ,
},
watch: {
count: function(nval, oval) {
alert("Counter Change from " + oval + " to " + nval);
}
}
});
</script>
<!-- 监听姓名变化并实时显示 -->
<body>
<div id="app">
<label>First Name: <input type="text" v-model="firstName"></label>
<label>Last Name: <input type="text" v-model="lastName"></label>
{{fullName}}
</div>
</body>
<script src="js/vue.min.js"></script>
<script>
var VM = new Vue({
el: "#app",
data: {
firstName: "",
lastName: "",
fullName: ""
},
watch: {
firstName: function(nval, oval) {
this.fullName = nval + " " + this.lastName;
},
lastName: function(nval, oval) {
this.fullName = this.firstName + " " + nval;
}
}
})
</script>
组件(Component)是自定义封装的功能。在前端开发过程中,经常出现多个网页的功能是重复的,而且很多不同的页面之间,也存在同样的功能。
将相同的功能进行抽取,封装为组件;这样前端人员就可以在组件化开发时,只需要书写一次代码,随处引入即可使用。
组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树。
Vue 的组件有两种:全局组件和局部组件 。
注意:
hello-Word
data
必须是一个函数,注意与 Vue 实例中的 data
区分template
模板中,只能有一个根元素components
的末尾有 s
,而全局组件是不用加 s
的;这意味着 components
里可以创建多个组件相比起全局组件,局部组件只能在同一个实例内才能被调用。
局部组件的写法和全局组件差不多,唯一不同就是:局部组件要写在 Vue 实例里面。
<!-- 全局组件 -->
<body>
<div id="app">
<!-- 使用组件 -->
<renda-header></renda-header>
</div>
</body>
<script src="js/vue.min.js"></script>
<script>
// 定义全局组件
// 组件的命名规则:一般用短横线进行连接,左边是公司名,右边组件的作用名称
Vue.component("renda-header", {
// template 模板中只能有一个根元素
template: "<div>TEST <h1 @click='hello'>{{msg}}</h1> </div>",
data() {
// 组件中的 data 是一个函数
return {
msg: "This is the data part of the renda-header",
};
},
methods: {
hello() {
alert("Hello !");
},
},
});
var VM = new Vue({
el: "#app",
data: {},
methods: {},
});
</script>
<!-- 局部组件 -->
<body>
<div id="app">
<web-msg></web-msg>
</div>
</body>
<script src="js/vue.min.js"></script>
<script>
var VM = new Vue({
el: "#app",
components: {
"web-msg": {
template: "<div><h1>{{msg1}}</h1><h1>{{msg2}}</h1></div>",
data() {
return {
msg1: "Developing...",
msg2: "Development finished"
}
},
}
}
});
</script>
<!-- 组件与模板分离 -->
<!-- 由于把 html 语言写在组件里面很不方便且不好看,所以将它们分开写 -->
<body>
<div id="app">
<!-- 使用组件 -->
<web-msg></web-msg>
</div>
<!-- 将模板写在 HTML 中,给模板一个 id -->
<template id="t1">
<div>
<button @click="show">{{msg}}</button>
</div>
</template>
</body>
<script src="js/vue.min.js"></script>
<script>
var VM = new Vue({
el: "#app",
components: {
"web-msg": {
template: "#t1",
data() {
return {
msg: "Search"
}
},
methods: {
show() {
alert("Please wait...");
}
},
}
}
});
</script>
每个 Vue 实例在被创建之前都要经过一系列的初始化过程,这个过程就是 Vue 的生命周期。
生命周期中的钩子函数:钩子函数是在一个事件触发的时候,在系统级捕获到了他,然后做一些操作。
beforeCreate()
- 在创建 Vue 实例之前,可以执行这个方法,例如加载动画操作。created()
- 实例创建完成,属性绑定好了,但是 DOM 还没有生成。beforeMount()
- 模板已经在内存中编辑完成了,尚未被渲染到页面中。mounted()
- 内存中的模板已经渲染到页面,用户已经可以看见内容。beforeUpdate()
- 数据更新的前一刻,组件在发生更新之前,调用的函数。updated()
- updated 执行时,内存中的数据已更新,并且页面已经被渲染。beforeDestroy ()
- 钩子函数在实例销毁之前调用。destroyed ()
- 钩子函数在 Vue 实例销毁后调用。<body>
<div id="app">
<h2 id="msg">{{message}}</h2>
<button @click="next">Next</button>
</div>
</body>
<script src="js/vue.min.js"></script>
<script>
var VM = new Vue({
el: "#app",
data: {
message: "I am Renda Zhang",
},
methods: {
show() {
alert("show method is executed");
},
next() {
this.message = "Who are you?";
}
},
// 在 Vue 对象实例化之前执行
beforeCreate() {
alert("Before Create");
console.log(this.message); // undefined
this.show(); // error
},
// 组件的实例化完成,但是 DOM 页面还未生成
created() {
alert("Created");
console.log(this.message);
this.show();
},
// 模板已经在内存中编辑完成了,但是还没有被渲染到页面中
beforeMount() {
alert("Before Mount");
console.log("Page content: " + document.getElementById("msg").innerText);
console.log("data: " + this.message);
},
// 模板已经被渲染到页面,执行完就会显示页面
mounted() {
alert("Mounted");
console.log("Page content: " + document.getElementById("msg").innerText);
},
// 内存中的数据已经更新,但是还没有渲染到页面
beforeUpdate() {
alert("Before Update");
console.log("Page content: " + document.getElementById("msg").innerText);
console.log("data: " + this.message);
},
// 内存中的数据已经更新,此方法执行完显示页面
updated() {
alert("Updated");
console.log("Page content: " + document.getElementById("msg").innerText);
console.log("data: " + this.message);
},
});
</script>
在 Web 开发中,路由是指根据 URL 分配到对应的处理程序。
路由允许我们通过不同的 URL 访问不同的内容。
通过 Vue.js 可以实现多视图单页面 web 应用。
单页面 Web 应用(single page web application,SPA),就是只有一张 Web 页面的应用,是加载单个 HTML 页面并在用户与应用程序交互时动态更新该页面的 Web 应用程序。
单页应用不存在页面跳转,它本身只有一个 HTML 页面;传统意义上的页面跳转在单页应用的概念下转变为了 body 内某些元素的替换和更新。
整个 body 的内容从登录组件变成了欢迎页组件,从视觉上感受页面已经进行了跳转。但实际上,页面只是随着用户操作,实现了局部内容更新,依然还是在 index.html 页面中。
单页面应用的好处:
router
:是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用(SPA)变得易如反掌,router
就相当于一个管理者,它来管理路由。route
:router
相当于路由器,route
就相当于一条路由。比如,Home 按钮 => home 内容
, 这是一条 route
;news 按钮 => news 内容
, 这是另一条 route
。routes
:是一组路由。把上面的每一条路由组合起来,形成一个数组。[{ home 按钮 => home 内容 }, { about 按钮 => about 内容 }]
。router-link
组件: router-link
是一个组件,是对 标签的一个封装。该组件用于设置一个导航链接,切换不同 HTML 内容。to
属性为目标地址, 即要显示的内容。router-view
组件:路由导航到指定组件后,进行渲染显示页面。Vue.js 路由需要载入 vue-router
库:
// 方式 1: 本地导入
<script src="vue-router.min.js"></script>
// 方式 2: CDN
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
使用步骤:
path
(路径),component
(组件)router
路由器实例,管理路由$mount()
指定挂载点Vue 的 mount()为手动挂载,在项目中可用于延时挂载(例如在挂载之前要进行一些其他操作、判断等),之后要手动挂载上。新建Vue时,el和mount 并没有本质上的不同。
<body>
<div id="app">
<h1>renda.com</h1>
<p>
<!-- 添加超链接,router-link 组件来进行导航,to 属性指定链接 -->
<router-link to="/home">Go to Home</router-link>
<router-link to="/news">Go to News</router-link>
</p>
<!-- 路由的出口,路由匹配到组件之后,要渲染到这里 -->
<router-view></router-view>
</div>
</body>
<script src="js/vue.min.js"></script>
<script src="js/vue-router.min.js"></script>
<script>
// 定义路由所需的组件
const home = { template: "<div>首页</div>" };
const news = { template: "<div>新闻</div>" };
// 定义路由,每个路由有两部分 path(路径),component(组件)
const routes = [
{ path: "/home", component: home },
{ path: "/news", component: news },
];
// 创建路由管理器实例
const router = new VueRouter({
routes: routes,
});
// 创建 Vue 实例,将 router 注入到 vue 实例中,让整个应用都拥有路由的功能
var VM = new Vue({
router,
// 代替 el
}).$mount("#app");
</script>
router
是 Vue 中的路由管理器对象,用来管理路由route
是路由对象,一个路由就对应了一条访问路径,一组路由用 routes
表示path
(路径)和 component
(组件)router-link
是对 a
标签的封装,通过 to
属性指定连接router-view
路由访问到指定组件后,进行页面展示