1. vue.js的快速入門使用
1.1 vue.js庫的下載
vue.js
是目前前端web開發最流行的工具庫,由尤雨溪在2014年2月發布的。
另外幾個常見的工具庫:react.js /angular.js
官方網站:
英文:https://vuejs.org/
官方文檔:https://cn.vuejs.org/v2/guide/
vue.js目前有1.x、2.x和3.x 版本,我們學習2.x版本的。
1.2 vue.js庫的基本使用
在github下載:https://github.com/vuejs/vue/releases
在官網下載地址: https://cn.vuejs.org/v2/guide/installation.html
vue的引入類似於jQuery,開發中可以使用開發版本vue.js,產品上線要換成vue.min.js。
下圖是github網站下載的vue.js目錄
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="js/vue.min.js"></script>
<script>
window.onload = function(){
// vue.js的代碼開始於一個Vue對象。所以每次操作數據都要聲明Vue對象開始。
var vm = new Vue({
el:'#app', // 設置當前vue對象要控制的標簽范圍。
data:{ // data是將要展示到HTML標簽元素中的數據。
message: 'hello world!',
}
});
}
</script>
</head>
<body>
<div id="app">
<!-- {{ message }} 表示把vue對象里面data屬性中的對應數據輸出到頁面中 -->
<!-- 在雙標簽中顯示數據要通過{{ }}來完成 -->
<p>{{ message }}</p>
</div>
</body>
</html>
代碼執行效果:
總結:
1. vue的使用要從創建Vue對象開始
var vm = new Vue();
2. 創建vue對象的時候,需要傳遞參數,是json對象,json對象對象必須至少有兩個屬性成員
var vm = new Vue({
el:"#app",
data: {
數據變量:"變量值",
數據變量:"變量值",
數據變量:"變量值",
},
});
el:設置vue可以操作的html內容范圍,值就是css的id選擇器。
data: 保存vue.js中要顯示到html頁面的數據。
3. vue.js要控制器的內容外圍,必須先通過id來設置。
<div id="app">
<h1>{{message}}</h1>
<p>{{message}}</p>
</div>
1.3 vue.js的M-V-VM思想
MVVM 是Model-View-ViewModel 的縮寫,它是一種基於前端開發的架構模式。
Model
指代的就是vue對象的data屬性里面的數據。這里的數據要顯示到頁面中。
View
指代的就是vue中數據要顯示的HTML頁面,在vue中,也稱之為“視圖模板” 。
ViewModel
指代的是vue.js中我們編寫代碼時的vm對象了,它是vue.js的核心,負責連接 View 和 Model,保證視圖和數據的一致性,所以前面代碼中,data里面的數據被顯示中p標簽中就是vm對象自動完成的。
編寫代碼,讓我們更加清晰的了解MVVM:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.min.js"></script>
<script>
window.onload = function(){
// 創建vm對象
var vm = new Vue({
el: "#app",
data: {
name:"大標題",
age:16,
},
})
}
</script>
</head>
<body>
<div id="app">
<!-- 在雙標簽中顯示數據要通過{{ }}來完成 -->
<h1>{{name}}</h1>
<p>{{age}}</p>
<!-- 在表單輸入框中顯示數據要使用v-model來完成,模板語法的時候,我們會詳細學習 -->
<input type="text" v-model="name">
</div>
</body>
</html>
代碼執行效果:
在瀏覽器中可以在 console.log通過 vm對象可以直接訪問el和data屬性,甚至可以訪問data里面的數據
console.log(vm.$el) # #box vm對象可以控制的范圍
console.log(vm.$data); # vm對象要顯示到頁面中的數據
console.log(vm.message);# 這個 message就是data里面聲明的數據,也可以使用 vm.變量名顯示其他數據,message只是舉例.
總結:
1. 如果要輸出data里面的數據作為普通標簽的內容,需要使用{{ }}
用法:
vue對象的data屬性:
data:{
name:"小明",
}
標簽元素:
<h1>{{ name }}</h1>
2. 如果要輸出data里面的數據作為表單元素的值,需要使用vue.js提供的元素屬性v-model
用法:
vue對象的data屬性:
data:{
name:"小明",
}
表單元素:
<input v-model="name">
使用v-model把data里面的數據顯示到表單元素以后,一旦用戶修改表單元素的值,則data里面對應數據的值也會隨之發生改變,甚至,頁面中凡是使用了這個數據都會發生變化。
1.4 顯示數據
- 在雙標簽中顯示數據要通過{{ }}來完成數據顯示
- 在表單輸入框中顯示數據要使用v-model來完成數據顯示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.min.js"></script>
<script>
window.onload = function(){
var vm = new Vue({
el:"#app",
data:{
str1: "hello",
num: 20,
url1: "http://www.baidu.com",
url2: "http://www.taobao.com"
}
})
}
</script>
</head>
<body>
<p>{{ str1 }}</p>
<p>{{ str1.split("").reverse().join("") }}</p>
<p>num和num2中比較大的數是:{{ num>num2 ? num:num2 }}</p>
<input type="text" v-model="name">
</body>
</html>
雙花括號僅用輸出文本內容,如果要輸出html代碼,則不能使用這個.要使用v-html來輸出.
v-html必須在html標簽里面作為屬性寫出來.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div class="app">
<h1>{{title}}</h1>
<h3>{{url1}}</h3>
{{img}}<br>
<span v-html="img"></span>
</div>
<script>
let vm = new Vue({
el:".app",
data:{
title:"我的vue",
url1:"我的收獲地址",
img:'<img src="images/shendan.png">',
}
})
</script>
</body>
</html>
總結:
1. 可以在普通標簽中使用{{ }} 或者 v-html 來輸出data里面的數據
<h1>{{message}}</h1>
2. 可以在表單標簽中使用v-model屬性來輸出data里面的數據,同時還可以修改data里面的數據
<input type="text" v-model="username">
在輸出內容到普通標簽的使用{{ }}還支持js代碼。
<h1>{{str1.split("").reverse().join("")}}</h1>
<!-- 3.2 支持js的運算符-->
<h1>{{num1+3}}</h1>
<!-- 3.3 js還有一種運算符,三元運算符,類似於python里面的三元表達式
三元運算符的語法:
判斷條件 ? 條件為true : 條件為false的結果
python 三元表達式[三目運算符]的語法:
a if 條件 else b
-->
<h1>num1和num2之間進行比較,最大值:{{ num2>num1?num2:num1 }}</h1>
2. 常用指令
指令 (Directives) 是帶有“v-”前綴的特殊屬性。每一個指令在vue中都有固定的作用。
在vue中,提供了很多指令,常用的有:v-if、v-model、v-for等等。
指令會在vm對象的data屬性的數據發生變化時,會同時改變元素中的其控制的內容或屬性。
因為vue的歷史版本原因,所以有一部分指令都有兩種寫法:
vue1.x寫法 vue2.x的寫法
v-html ----> {{ }} # vue2.x 也支持v-html
v-bind:屬性名 ----> :屬性
v-on:事件名 ----> @事件名
2.1 操作屬性
格式:
<標簽名 :標簽屬性="data屬性"></標簽名>
<p :title="str1">{{ str1 }}</p> <!-- 也可以使用v-html顯示雙標簽的內容,{{ }} 是簡寫 -->
<a :href="url2">淘寶</a>
<a v-bind:href="url1">百度</a> <!-- v-bind是vue1.x版本的寫法 -->
顯示wifi密碼效果:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="index">
<img :src="url" :alt="title"><br>
<input :type="type" placeholder="請輸入wifi密碼"> <button @click="type='text'">顯示密碼</button>
</div>
<script>
let vm = new Vue({
el:"#index",
data:{
url:"https://www.luffycity.com/static/img/head-logo.a7cedf3.svg",
title:"路飛學成",
type:"password"
}
})
</script>
</body>
</html>
2.2 事件綁定
有兩種事件操作的寫法,@事件名 和 v-on:事件名
<button v-on:click="num++">按鈕</button> <!-- v-on 是vue1.x版本的寫法 -->
<button @click="num+=5">按鈕2</button>
總結:
1. 使用@事件名來進行事件的綁定
語法:
<h1 @click="num++">{{num}}</h1>
2. 綁定的事件的事件名,全部都是js的事件名:
@submit ---> onsubmit
@focus ---> onfocus
....
例如:完成商城的商品增加減少數量
步驟:
- 給vue對象添加操作數據的方法
- 在標簽中使用指令調用操作數據的方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="box">
<button @click="++num">+</button>
<input type="text" v-model="num">
<button @click="sub">-</button>
</div>
<script>
let vm = new Vue({
el:"#box",
data:{
num:0,
},
methods:{
sub(){
if(this.num<=1){
this.num=0;
}else{
this.num--;
}
}
}
})
</script>
</body>
</html>
<!--#box>(button+input+button) tab鍵-->
2.3 操作樣式
2.3.1 控制標簽class類名
格式:
<h1 :class="值">元素</h1> 值可以是對象、對象名、數組
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
<style>
.box1{
color: red;
border: 1px solid #000;
}
.box2{
background-color: orange;
font-size: 32px;
}
</style>
</head>
<body>
<div id="box">
<!--- 添加class類名,值是一個對象
{
class類1:布爾值變量1,
class類2:布爾值變量2,
}
-->
<p :class="{box1:myclass1}">一個段落</p>
<p @click="myclass3=!myclass3" :class="{box1:myclass2,box2:myclass3}">一個段落</p>
</div>
<script>
let vm1=new Vue({
el:"#box",
data:{
myclass1:false, // 布爾值變量如果是false,則不會添加對象的屬性名作為樣式
myclass2:true, // 布爾值變量如果是true,則不會添加對象的屬性名作為樣式
myclass3:false,
},
})
</script>
<!-- 上面的代碼可以:class的值保存到data里面的一個變量,然后使用該變量作為:class的值 -->
<style>
.box4{
background-color: red;
}
.box5{
color: green;
}
</style>
<div id="app">
<button @click="mycls.box4=!mycls.box4">改變背景</button>
<button @click="mycls.box5=!mycls.box5">改變字體顏色</button>
<p :class="mycls">第二個段落</p>
</div>
<script>
let vm2 = new Vue({
el:"#app",
data:{
mycls:{
box4:false,
box5:true
},
}
})
</script>
<!-- 批量給元素增加多個class樣式類 -->
<style>
.box6{
background-color: red;
}
.box7{
color: green;
}
.box8{
border: 1px solid yellow;
}
</style>
<div id="app2">
<p :class="[mycls1,mycls2]">第三個段落</p>
</div>
<script>
let vm3 = new Vue({
el:"#app2",
data:{
mycls1:{
box6:true,
box7:true,
},
mycls2:{
box8:true,
}
}
})
</script>
</body>
</html>
代碼執行效果:
總結:
1. 給元素綁定class類名,最常用的就是第二種。
vue對象的data數據:
data:{
myObj:{
complete:true,
uncomplete:false,
}
}
html元素:
<div class="box" :class="myObj">2222</div>
最終瀏覽器效果:
<div class="box complete">2222</div>
2.3.2 控制標簽style樣式
格式1:值是json對象,對象寫在元素的:style屬性中
標簽元素:
<div :style="{color: activeColor, fontSize: fontSize + 'px' }"></div>
data數據如下:
data: {
activeColor: 'red',
fontSize: 30
}
格式2:值是對象變量名,對象在data中進行聲明
標簽元素:
<div v-bind:style="styleObject"></div>
data數據如下:
data: {
styleObject: {
color: 'red',
fontSize: '13px'
}
}
格式3:值是數組
標簽元素:
<div v-bind:style="[style1, style2]"></div>
data數據如下:
data: {
style1:{
color:"red"
},
style2:{
background:"yellow",
fontSize: "21px"
}
}
2.3.2 實例-vue版本選項卡
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
#card{
width: 500px;
height: 350px;
}
.title{
height:50px;
}
.title span{
width: 100px;
height: 50px;
background-color:#ccc;
display: inline-block;
line-height: 50px; /* 設置行和當前元素的高度相等,就可以讓文本內容上下居中 */
text-align:center;
}
.content .list{
width: 500px;
height: 300px;
background-color: yellow;
display: none;
}
.content .active{
display: block;
}
.title .current{
background-color: yellow;
}
</style>
<script src="js/vue.js"></script>
</head>
<body>
<div id="card">
<div class="title">
<span @click="num=0" :class="num==0?'current':''">國內新聞</span>
<span @click="num=1" :class="num==1?'current':''">國際新聞</span>
<span @click="num=2" :class="num==2?'current':''">銀河新聞</span>
<!--<span>{{num}}</span>-->
</div>
<div class="content">
<div class="list" :class="num==0?'active':''">國內新聞列表</div>
<div class="list" :class="num==1?'active':''">國際新聞列表</div>
<div class="list" :class="num==2?'active':''">銀河新聞列表</div>
</div>
</div>
<script>
// 思路:
// 當用戶點擊標題欄的按鈕[span]時,顯示對應索引下標的內容塊[.list]
// 代碼實現:
var card = new Vue({
el:"#card",
data:{
num:0,
},
});
</script>
</body>
</html>
代碼運行效果:
2.4 條件渲染指令
vue中提供了兩個指令可以用於判斷是否要顯示元素,分別是v-if和v-show。
2.4.1 v-if
標簽元素:
<!-- vue對象最終會把條件的結果變成布爾值 -->
<h1 v-if="ok">Yes</h1>
data數據:
data:{
ok:false // true則是顯示,false是隱藏
}
2.4.2 v-else
v-else指令來表示 v-if 的“else 塊”,v-else 元素必須緊跟在帶 v-if 或者 v-else-if 的元素的后面,否則它將不會被識別。
標簽元素:
<h1 v-if="ok">Yes</h1>
<h1 v-else>No</h1>
data數據:
data:{
ok:false // true則是顯示,false是隱藏
}
2.4.3 v-else-if
可以出現多個v-else-if語句,但是v-else-if之前必須有一個v-if開頭。后面可以跟着v-else,也可以沒有。
標簽元素:
<h1 v-if="num==1">num的值為1</h1>
<h1 v-else-if="num==2">num的值為2</h1>
<h1 v-else>num的值是{{num}}</h1>
data數據:
data:{
num:2
}
2.4.4 v-show
用法和v-if大致一樣,區別在於2點:
- v-show后面不能v-else或者v-else-if
- v-show隱藏元素時,使用的是display:none來隱藏的,而v-if是直接從HTML文檔中移除元素[ DOM操作中的remove ]
標簽元素:
<h1 v-show="ok">Hello!</h1>
data數據:
data:{
ok:false // true則是顯示,false是隱藏
}
2.5 列表渲染指令
在vue中,可以通過v-for指令可以將一組數據渲染到頁面中,數據可以是數組或者對象。
數據是數組:
<ul>
<!--i是列表的每一個元素-->
<li v-for="book in book_list">{{book.title}}</li>
</ul>
<ul>
<!--i是列表的每一個元素,j是每個元素的下標-->
<li v-for="(book, index) in book_list">第{{ index+1}}本圖書:{{book.title}}</li>
</ul>
<script>
var vm1 = new Vue({
el:"#app",
data:{
book_list:[
{"id":1,"title":"圖書名稱1","price":200},
{"id":2,"title":"圖書名稱2","price":200},
{"id":3,"title":"圖書名稱3","price":200},
{"id":4,"title":"圖書名稱4","price":200},
]
}
})
</script>
數據是對象:
<ul>
<!--i是每一個value值-->
<li v-for="value in book">{{value}}</li>
</ul>
<ul>
<!--i是每一個value值,j是每一個鍵名-->
<li v-for="attr, value in book">{{attr}}:{{value}}</li>
</ul>
<script>
var vm1 = new Vue({
el:"#app",
data:{
book: {
// "attr":"value"
"id":11,
"title":"圖書名稱1",
"price":200
},
},
})
</script>
練習:
goods:[
{"name":"python入門","price":150},
{"name":"python進階","price":100},
{"name":"python高級","price":75},
{"name":"python研究","price":60},
{"name":"python放棄","price":110},
]
# 把上面的數據采用table表格輸出到頁面,價格大於60的那一條數據需要添加背景色
3. Vue對象提供的屬性功能
3.1 過濾器
過濾器,就是vue允許開發者自定義的文本格式化函數,可以使用在兩個地方:輸出內容和操作數據中。
定義過濾器的方式有兩種。
3.1.1 使用Vue.filter()進行全局定義
Vue.filter("RMB1", function(v){
//就是來格式化(處理)v這個數據的
if(v==0){
return v
}
return v+"元"
})
3.1.2 在vue對象中通過filters屬性來定義
var vm = new Vue({
el:"#app",
data:{},
filters:{
RMB2:function(value){
if(value==''){
return;
}else{
return '¥ '+value;
}
}
}
});
3.4 計算和偵聽屬性
3.4.1 計算屬性
我們之前學習過字符串反轉,如果直接把反轉的代碼寫在元素中,則會使得其他同事在開發時時不易發現數據被調整了,所以vue提供了一個計算屬性(computed),可以讓我們把調整data數據的代碼存在在該屬性中。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.min.js"></script>
<script>
window.onload = function(){
var vm = new Vue({
el:"#app",
data:{
str1: "abcdefgh"
},
computed:{ //計算屬性:里面的函數都必須有返回值
strRevs: function(){
var ret = this.str1.split("").reverse().join("");
return ret
}
}
});
}
</script>
</head>
<body>
<div id="app">
<p>{{ str1 }}</p>
<p>{{ strRevs }}</p>
</div>
</body>
</html>
3.4.2 監聽屬性
偵聽屬性,可以幫助我們偵聽data某個數據的變化,從而做相應的自定義操作。
偵聽屬性是一個對象,它的鍵是要監聽的對象或者變量,值一般是函數,當偵聽的data數據發生變化時,會自定執行的對應函數,這個函數在被調用時,vue會傳入兩個形參,第一個是變化前的數據值,第二個是變化后的數據值。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.min.js"></script>
<script>
window.onload = function(){
var vm = new Vue({
el:"#app",
data:{
num:20
},
watch:{
num:function(newval,oldval){
//num發生變化的時候,要執行的代碼
console.log("num已經發生了變化!");
}
}
})
}
</script>
</head>
<body>
<div id="app">
<p>{{ num }}</p>
<button @click="num++">按鈕</button>
</div>
</body>
</html>
3.5 vue對象的生命周期
每個Vue對象在創建時都要經過一系列的初始化過程。在這個過程中Vue.js會自動運行一些叫做生命周期的的鈎子函數,我們可以使用這些函數,在對象創建的不同階段加上我們需要的代碼,實現特定的功能。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.min.js"></script>
<script>
window.onload = function(){
var vm = new Vue({
el:"#app",
data:{
num:0
},
beforeCreate:function(){
console.log("beforeCreate,vm對象尚未創建,num="+ this.num); //undefined
this.name=10; // 此時沒有this對象呢,所以設置的name無效,被在創建對象的時候被覆蓋為0
},
created:function(){
console.log("created,vm對象創建完成,設置好了要控制的元素范圍,num="+this.num ); // 0
this.num = 20;
},
beforeMount:function(){
console.log( this.$el.innerHTML ); // <p>{{num}}</p>
console.log("beforeMount,vm對象尚未把data數據顯示到頁面中,num="+this.num ); // 20
this.num = 30;
},
mounted:function(){
console.log( this.$el.innerHTML ); // <p>30</p>
console.log("mounted,vm對象已經把data數據顯示到頁面中,num="+this.num); // 30
},
beforeUpdate:function(){
// this.$el 就是我們上面的el屬性了,$el表示當前vue.js所控制的元素#app
console.log( this.$el.innerHTML ); // <p>30</p>
console.log("beforeUpdate,vm對象尚未把更新后的data數據顯示到頁面中,num="+this.num); // beforeUpdate----31
},
updated:function(){
console.log( this.$el.innerHTML ); // <p>31</p>
console.log("updated,vm對象已經把過呢更新后的data數據顯示到頁面中,num=" + this.num ); // updated----31
},
});
}
</script>
</head>
<body>
<div id="app">
<p>{{num}}</p>
<button @click="num++">按鈕</button>
</div>
</body>
</html>
總結:
在vue使用的過程中,如果要初始化操作,把初始化操作的代碼放在 mounted 中執行。
mounted階段就是在vm對象已經把data數據實現到頁面以后。一般頁面初始化使用。例如,用戶訪問頁面加載成功以后,就要執行的ajax請求。
另一個就是created,這個階段就是在 vue對象創建以后,把ajax請求后端數據的代碼放進 created
3.2 阻止事件冒泡和刷新頁面
使用.stop和.prevent
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.box1{
width: 200px;
height: 200px;
background: #ccc;
}
.box2{
width: 100px;
height: 100px;
background: pink;
}
</style>
<script src="js/vue.min.js"></script>
<script>
window.onload = function(){
var vm = new Vue({
el:"#app",
data:{}
})
}
</script>
</head>
<body>
<div id="app">
<div class="box1" @click="alert('box1')">
<div class="box2" @click.stop.prevent="alert('box2')"></div> <!-- @click.stop來阻止事件冒泡 -->
</div>
<form action="#">
<input type="text">
<input type="submit">
<input type="submit" value="提交02" @click.prevent=""> <!-- @click.prevent來阻止表單提交 -->
</form>
</div>
</body>
</html>
3.3 綜合案例-todolist
我的計划列表
html代碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>todolist</title>
<style type="text/css">
.list_con{
width:600px;
margin:50px auto 0;
}
.inputtxt{
width:550px;
height:30px;
border:1px solid #ccc;
padding:0px;
text-indent:10px;
}
.inputbtn{
width:40px;
height:32px;
padding:0px;
border:1px solid #ccc;
}
.list{
margin:0;
padding:0;
list-style:none;
margin-top:20px;
}
.list li{
height:40px;
line-height:40px;
border-bottom:1px solid #ccc;
}
.list li span{
float:left;
}
.list li a{
float:right;
text-decoration:none;
margin:0 10px;
}
</style>
</head>
<body>
<div class="list_con">
<h2>To do list</h2>
<input type="text" name="" id="txt1" class="inputtxt">
<input type="button" name="" value="增加" id="btn1" class="inputbtn">
<ul id="list" class="list">
<!-- javascript:; # 阻止a標簽跳轉 -->
<li>
<span>學習html</span>
<a href="javascript:;" class="up"> ↑ </a>
<a href="javascript:;" class="down"> ↓ </a>
<a href="javascript:;" class="del">刪除</a>
</li>
<li><span>學習css</span><a href="javascript:;" class="up"> ↑ </a><a href="javascript:;" class="down"> ↓ </a><a href="javascript:;" class="del">刪除</a></li>
<li><span>學習javascript</span><a href="javascript:;" class="up"> ↑ </a><a href="javascript:;" class="down"> ↓ </a><a href="javascript:;" class="del">刪除</a></li>
</ul>
</div>
</body>
</html>
特效實現效果:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>todolist</title>
<style type="text/css">
.list_con{
width:600px;
margin:50px auto 0;
}
.inputtxt{
width:550px;
height:30px;
border:1px solid #ccc;
padding:0px;
text-indent:10px;
}
.inputbtn{
width:40px;
height:32px;
padding:0px;
border:1px solid #ccc;
}
.list{
margin:0;
padding:0;
list-style:none;
margin-top:20px;
}
.list li{
height:40px;
line-height:40px;
border-bottom:1px solid #ccc;
}
.list li span{
float:left;
}
.list li a{
float:right;
text-decoration:none;
margin:0 10px;
}
</style>
<script src="js/vue.js"></script>
</head>
<body>
<div id="todolist" class="list_con">
<h2>To do list</h2>
<input type="text" v-model="message" class="inputtxt">
<input type="button" @click="addItem" value="增加" class="inputbtn">
<ul id="list" class="list">
<li v-for="item,key in dolist">
<span>{{item}}</span>
<a @click="upItem(key)" class="up" > ↑ </a>
<a @click="downItem(key)" class="down"> ↓ </a>
<a @click="delItem(key)" class="del">刪除</a>
</li>
</ul>
</div>
<script>
// 計划列表代碼
let vm = new Vue({
el:"#todolist",
data:{
message:"",
dolist:[
"學習html",
"學習css",
"學習javascript",
]
},
methods:{
addItem(){
if(this.messsage==""){
return false;
}
this.dolist.push(this.message);
this.message = ""
},
delItem(key){
// 刪除和替換
// 參數1: 開始下表
// 參數2: 元素長度,如果不填默認刪除到最后
// 參數3: 表示使用當前參數替換已經刪除內容的位置
this.dolist.splice(key, 1);
},
upItem(key){
if(key==0){
return false;
}
// 向上移動
let result = this.dolist.splice(key,1);
this.dolist.splice(key-1,0,result[0]);
},
downItem(key){
// 向下移動
let result = this.dolist.splice(key, 1);
console.log(result);
this.dolist.splice(key+1,0,result[0]);
}
}
})
</script>
</body>
</html>
小結
let vm = new Vue({
el: "#app",
data: {},
// 事件及方法
methods:{},
// 自定義過濾器
filters:{},
//計算屬性
computed:{}, // 里面的函數都必須有返回值
// 監聽屬性
watch:{}, // 這個函數在被調用時,vue會傳入兩個形參
// 生命周期(鈎子函數)
beforeCreate:function(){}, // vm對象尚未創建,此時沒有this對象
created:function(){}, // vm對象創建完成,設置好了要控制的元素范圍
beforeMount:function(){}, // vm對象尚未把data數據顯示到頁面中
mounted:function(){}, // vm對象已經把data數據顯示到頁面中
beforeUpdate:function(){}, // vm對象尚未把更新后的data數據顯示到頁面
updated(){}, // vm對象已經把過呢更新后的data數據顯示到頁面中
})
4. 通過axios實現數據請求
vue.js默認沒有提供ajax功能的。
所以使用vue的時候,一般都會使用axios的插件來實現ajax與后端服務器的數據交互。
注意,axios本質上就是javascript的ajax封裝,所以會被同源策略限制。
下載地址:
https://unpkg.com/axios@0.18.0/dist/axios.js
https://unpkg.com/axios@0.18.0/dist/axios.min.js
axios提供發送請求的常用方法有兩個:axios.get() 和 axios.post() 。
- post 增
- delete 刪
- put 改
- get 查
// 發送get請求
// 參數1: 必填,字符串,請求的數據接口的url地址,例如請求地址:http://www.baidu.com?id=200
// 參數2:可選,json對象,要提供給數據接口的參數
// 參數3:可選,json對象,請求頭信息
axios.get('服務器的資源地址',{ // http://www.baidu.com
params:{
參數名:'參數值', // id: 200,
}
}).then(function (response) { // 請求成功以后的回調函數
console.log("請求成功");
console.log(response);
}).catch(function (error) { // 請求失敗以后的回調函數
console.log("請求失敗");
console.log(error.response);
});
// 發送post請求,參數和使用和axios.get()一樣。
// 參數1: 必填,字符串,請求的數據接口的url地址
// 參數2:必填,json對象,要提供給數據接口的參數,如果沒有參數,則必須使用{}
// 參數3:可選,json對象,請求頭信息
axios.post('服務器的資源地址',{
username: 'xiaoming',
password: '123456'
},{
responseData:"json",
})
.then(function (response) { // 請求成功以后的回調函數
console.log(response);
})
.catch(function (error) { // 請求失敗以后的回調函數
console.log(error);
});
// b'firstName=Fred&lastName=Flintstone'
4.1 json
json是 JavaScript Object Notation 的首字母縮寫,單詞的意思是javascript對象表示法,這里說的json指的是類似於javascript對象的一種數據格式。
json的作用:在不同的系統平台,或不同編程語言之間傳遞數據。
4.1.1 json數據的語法
json數據對象類似於JavaScript中的對象,但是它的鍵對應的值里面是沒有函數方法的,值可以是普通變量,不支持undefined,值還可以是數組或者json對象。
// json數據的對象格式:
{
"name":"tom",
"age":18
}
// json數據的數組格式:
["tom",18,"programmer"]
復雜的json格式數據可以包含對象和數組的寫法。
{
"name":"小明",
"age":200,
"fav":["code","eat","swim","read"],
"son":{
"name":"小小明",
"age":100,
"lve":["code","eat"],
}
}
// 數組結構也可以作為json傳輸數據。
json數據可以保存在.json文件中,一般里面就只有一個json對象。
總結:
1. json文件的后綴是.json
2. json文件一般保存一個單一的json數據
3. json數據的屬性不能是方法或者undefined,屬性值只能:數值、字符串、json和數組
4. json數據只使用雙引號、每一個屬性成員之間使用逗號隔開,並且最后一個成員沒有逗號。
{
"name":"小明",
"age":200,
"fav":["code","eat","swim","read"],
"son":{
"name":"小小明",
"age":100
}
}
工具:postman可以用於測試開發的數據接口。
4.1.2 js中提供的json數據轉換方法
javascript提供了一個JSON對象來操作json數據的數據轉換.
方法 | 參數 | 返回值 | 描述 |
---|---|---|---|
stringify | json對象 | 字符串 | json對象轉成字符串 |
parse | 字符串 | json對象 | 字符串格式的json數據轉成json對象 |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
// json語法
let humen = {
"username":"xiaohui",
"password":"1234567",
"age":20
};
console.log(humen);
console.log(typeof humen);
// JSON對象提供對json格式數據的轉換功能
// stringify(json對象) # 用於把json轉換成字符串
let result = JSON.stringify(humen);
console.log(result);
console.log(typeof result);
// parse(字符串類型的json數據) # 用於把字符串轉成json對象
let json_str = '{"password":"1123","age":20,"name":"xiaobai"}';
console.log(json_str)
console.log(typeof json_str)
let json_obj = JSON.parse(json_str);
console.log(json_obj);
console.log(typeof json_obj)
console.log(json_obj.age)
</script>
</body>
</html>
4.2 ajax
ajax,一般中文稱之為:"阿賈克斯",是英文 “Async Javascript And Xml”的簡寫,譯作:異步js和xml數據傳輸數據。
ajax的作用: ajax可以讓js代替瀏覽器向后端程序發送http請求,與后端通信,在用戶不知道的情況下操作數據和信息,從而實現頁面局部刷新數據/無刷新更新數據。
所以開發中ajax是很常用的技術,主要用於操作后端提供的數據接口
,從而實現網站的前后端分離
。
ajax技術的原理是實例化js的XMLHttpRequest對象,使用此對象提供的內置方法就可以與后端進行數據通信。
4.2.1 數據接口
數據接口,也叫api接口,表示后端提供
操作數據/功能的url地址給客戶端使用。
客戶端通過發起請求向服務端提供的url地址申請操作數據【操作一般:增刪查改】
同時在工作中,大部分數據接口都不是手寫,而是通過函數庫/框架來生成。
4.2.3 ajax的使用
ajax的使用必須與服務端程序配合使用但是目前我們先學習ajax的使用,所以暫時先不涉及到服務端python代碼的編寫。因此,我們可以使用別人寫好的數據接口進行調用。
jQuery將ajax封裝成了一個函數$.ajax(),我們可以直接用這個函數來執行ajax請求。
編寫代碼獲取接口提供的數據:
jQ版本
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/jquery-1.12.4.js"></script>
<script>
$(function(){
$("#btn").on("click",function(){
$.ajax({
// 后端程序的url地址
url: 'http://wthrcdn.etouch.cn/weather_mini',
// 也可以使用method,提交數據的方式,默認是'GET',常用的還有'POST'
type: 'get',
dataType: 'json', // 返回的數據格式,常用的有是'json','html',"jsonp"
data:{ // 設置發送給服務器的數據,如果是get請求,也可以寫在url地址的?后面
"city":'北京'
}
})
.done(function(resp) { // 請求成功以后的操作
console.log(resp);
})
.fail(function(error) { // 請求失敗以后的操作
console.log(error);
});
});
})
</script>
</head>
<body>
<button id="btn">點擊獲取數據</button>
</body>
</html>
vue版本:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
<script src="js/axios.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-model="city">
<button @click="get_weather">點擊獲取天氣</button>
</div>
<script>
let vm = new Vue({
el:"#app",
data:{
city:"",
},
methods:{
get_weather(){
// http://wthrcdn.etouch.cn/weather_mini?city=城市名稱
axios.get("http://wthrcdn.etouch.cn/weather_mini?city="+this.city)
.then(response=>{
console.log(response);
}).catch(error=>{
console.log(error.response)
});
}
}
})
</script>
</body>
</html>
1. 發送ajax請求,要通過$.ajax(),參數是對象,里面有固定的參數名稱。
$.ajax({
"url":"數據接口url地址",
"method":"http請求方式,前端只支持get和post",
"dataType":"設置服務器返回的數據格式,常用的json,html,jsonp,默認值就是json",
// 要發送給后端的數據參數,post時,數據必須寫在data,get可以寫在data,也可以跟在地址欄?號后面
"data":{
"數據名稱":"數據值",
}
}).then(function(resp){ // ajax請求數據成功時會自動調用then方法的匿名函數
console.log( resp ); // 服務端返回的數據
}).fail(function(error){ // ajax請求數據失敗時會自動調用fail方法的匿名函數
console.log( error );
});
2. ajax的使用往往配合事件/鈎子操作進行調用。
jQuery還提供了$.get 和 $post簡寫$.ajax的操作。
// 發送get請求
// 參數1:數據接口的請求地址
// 參數2:發送給接口地址的數據參數
// 參數3:ajax請求成功以后,調用的匿名函數,匿名函數的第一個參數還是服務端返回的數據
// 參數4:設置服務端返回的數據格式,告訴給jQuery
$.get("test.php", { "func": "getNameAndTime" },
function(data){
alert(data.name); // John
console.log(data.time); // 2pm
}, "json");
// 發送post請求
// 參數1:數據接口的請求地址
// 參數2:發送給接口地址的數據參數
// 參數3:ajax請求成功以后,調用的匿名函數,匿名函數的第一個參數還是服務端返回的數據
// 參數4:設置服務端返回的數據格式,告訴給jQuery
$.post("test.php", { "func": "getNameAndTime" },
function(data){
alert(data.name); // John
console.log(data.time); // 2pm
}, "json");
4.2.4 同源策略
URL由協議、域名[IP]、端口和路徑組成
同源策略,是瀏覽器為了保護用戶信息安全的一種安全機制。所謂的同源就是指代通信的兩個地址(例如服務端接口地址與瀏覽器客戶端頁面地址)之間比較,協議、域名(IP)和端口, 是否相同。不同源的客戶端腳本[javascript]在沒有明確授權的情況下,沒有權限讀寫對方信息。
ajax本質上還是javascript,是運行在瀏覽器中的腳本語言,所以會被受到瀏覽器的同源策略所限制。
瀏覽器攔截的是返回的數據
前端地址:http://www.oldboy.cn/index.html 默認80端口 |
是否同源 | 原因 |
---|---|---|
http://www.oldboy.cn/user/login.html |
是 | 協議、域名、端口相同 |
http://www.oldboy.cn/about.html |
是 | 協議、域名、端口相同 |
https://www.oldboy.cn/user/login.html |
否 | 協議不同 ( https和http ) |
http:/www.oldboy.cn:5000/user/login.html |
否 | 端口 不同( 5000和80) |
http://bbs.oldboy.cn/user/login.html |
否 | 域名不同 ( bbs和www ) |
同源策略針對ajax的攔截,代碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
<script src="js/axios.js"></script>
</head>
<body>
<div id="app">
<button @click="get_music">點擊獲取天氣</button>
</div>
<script>
let vm = new Vue({
el:"#app",
data:{},
methods:{
get_music(){
axios.get("http://tingapi.ting.baidu.com/v1/restserver/ting?method=baidu.ting.search.catalogSug&query=我的中國心")
.then(response=>{
console.log(response);
}).catch(error=>{
console.log(error.response)
});
}
}
})
</script>
</body>
</html>
上面代碼運行錯誤如下:
Access to XMLHttpRequest at 'http://tingapi.ting.baidu.com/v1/restserver/ting?method=baidu.ting.search.catalogSug&query=%E6%88%91%E7%9A%84%E4%B8%AD%E5%9B%BD%E5%BF%83' from origin 'http://localhost:63342' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
上面錯誤,關鍵詞:Access-Control-Allow-Origin
只要出現這個關鍵詞,就是訪問受限。出現同源策略的攔截問題。
4.2.5 ajax跨域(跨源)方案之CORS
CORS是一個W3C標准,全稱是"跨域資源共享",它允許瀏覽器向跨源的后端服務器發出ajax請求,從而克服了AJAX只能同源使用的限制。
實現CORS主要依靠后端服務器中響應數據中設置響應頭信息返回的。
django的視圖
def post(request):
response = new Response()
response .set_header("Access-Control-Allow-Origin","*")
return response;
// 在響應行信息里面設置以下內容:
Access-Control-Allow-Origin: ajax所在的域名地址
Access-Control-Allow-Origin: www.oldboy.cn # 表示只允許www.oldboy.cn域名的客戶端的ajax跨域訪問
// * 表示任意源,表示允許任意源下的客戶端的ajax都可以訪問當前服務端信息
Access-Control-Allow-Origin: *
總結:
0. 同源策略:瀏覽器的一種保護用戶數據的一種安全機制。
瀏覽器會限制腳本語法不能跨源訪問其他源的數據地址。
同源:判斷兩個通信的地址之間,是否協議,域名[IP],端口一致。
ajax: http://127.0.0.1/index.html
api數據接口: http://localhost/index
這兩個是同源么?不是同源的。是否同源的判斷依據不會根據電腦來判斷,而是通過協議、域名、端口的字符串是否來判斷。
1. ajax默認情況下會受到同源策略的影響,一旦受到影響會報錯誤如下:
No 'Access-Control-Allow-Origin' header is present on the requested resource
2. 解決ajax只能同源訪問數據接口的方式:
1. 在服務端的響應行中設置:
Access-Control-Allow-Origin: 允許訪問的域名地址
2. jsonp
3. 是否服務端代理
思路:通過python來請求對應的服務器接口,獲取到數據以后,
5. 組件化開發
5.1 組件[component]
組件(Component)是自定義封裝的功能。在前端開發過程中,經常出現多個網頁的功能是重復的,而且很多不同的網站之間,也存在同樣的功能。
而在網頁中實現一個功能,需要使用html定義功能的內容結構,使用css聲明功能的外觀樣式,還要使用js來定義功能的特效,因此就產生了把一個功能相關的[HTML、css和javascript]代碼封裝在一起組成一個整體的代碼塊封裝模式,我們稱之為“組件”。
所以,組件就是一個html網頁中的功能,一般就是一個標簽,標簽中有自己的html內容結構,css樣式和js特效。
這樣,前端人員就可以在開發時,只需要書寫一次代碼,隨處引入即可使用。
組件有兩種:默認組件[全局組件] 和 單文件組件
5.1.1 默認組件
<div id="app">
<addnum></addnum>
<addnum></addnum>
<addnum></addnum>
<addnum></addnum>
<addnum></addnum>
</div>
<script>
Vue.component("addnum",{
template:'<div><input type="text" v-model="num"><button @click="num+=1">點擊</button></div>',
data: function(){
// 寫在這里的數據只有當前組件可以使用
return {
num:1,
}
}
});
var vm = new Vue({
el:"#app",
// 這里寫的數據是全局公用的,整個文件共享
data:{
}
})
</script>
5.2 Vue自動化工具(Vue-cli)
前面學習了普通組件以后,接下來我們繼續學習單文件組件則需要提前先安裝准備一些組件開發工具。否則無法使用和學習單文件組件。
一般情況下,單文件組件,我們運行在 自動化工具vue-CLI中,可以幫我們編譯單文件組件。所以我們需要在系統中先搭建vue-CLI工具,
Vue CLI 需要 Node.js 8.9 或更高版本 (推薦 8.11.0+)。你可以使用 nvm 或 nvm-windows在同一台電腦中管理多個 Node 版本。
nvm工具的下載和安裝: https://www.jianshu.com/p/d0e0935b150a
https://www.jianshu.com/p/622ad36ee020
安裝記錄:
打開:https://github.com/coreybutler/nvm-windows/releases
安裝完成以后,先查看環境變量是否設置好了.
常用的nvm命令
nvm list # 列出目前在nvm里面安裝的所有node版本
nvm install node版本號 # 安裝指定版本的node.js
nvm uninstall node版本號 # 卸載指定版本的node.js
nvm use node版本號 # 切換當前使用的node.js版本
如果使用nvm工具,則直接可以不用自己手動下載,如果使用nvm下載安裝 node的npm比較慢的時候,可以修改nvm的配置文件(在安裝根目錄下)
# settings.txt
root: C:\tool\nvm [這里的目錄地址是安裝nvm時自己設置的地址,要根據實際修改]
path: C:\tool\nodejs
arch: 64
proxy: none
node_mirror: http://npm.taobao.org/mirrors/node/
npm_mirror: https://npm.taobao.org/mirrors/npm/
5.2.1 安裝node.js
Node.js是一個新的后端(后台)語言,它的語法和JavaScript類似,所以可以說它是屬於前端的后端語言,后端語言和前端語言的區別:
- 運行環境:后端語言一般運行在服務器端,前端語言運行在客戶端的瀏覽器上
- 功能:后端語言可以操作文件,可以讀寫數據庫,前端語言不能操作文件,不能讀寫數據庫。
我們一般安裝LTS(長線支持版本):
下載地址:https://nodejs.org/en/download/【上面已經安裝了nvm,那么這里不用手動安裝了】
node.js的版本有兩大分支:
官方發布的node.js版本:0.xx.xx 這種版本號就是官方發布的版本
社區發布的node.js版本:xx.xx.x 就是社區開發的版本
Node.js如果安裝成功,可以查看Node.js的版本,在終端輸入如下命令:
node -v
5.2.2 npm
在安裝node.js完成后,在node.js中會同時幫我們安裝一個npm包管理器npm。我們可以借助npm命令來安裝node.js的包。這個工具相當於python的pip管理器。
npm install -g 包名 # 安裝模塊 -g表示全局安裝,如果沒有-g,則表示在當前項目安裝
npm list # 查看當前目錄下已安裝的node包
npm view 包名 engines # 查看包所依賴的Node的版本
npm outdated # 檢查包是否已經過時,命令會列出所有已過時的包
npm update 包名 # 更新node包
npm uninstall 包名 # 卸載node包
npm 命令 -h # 查看指定命令的幫助文檔
5.2.3 安裝Vue-cli
npm install -g vue-cli
如果安裝速度過慢,一直超時,可以考慮切換npm鏡像源:http://npm.taobao.org/
5.2.4 使用Vue-CLI初始化創建項目
5.2.4.1 生成項目目錄
使用vue自動化工具可以快速搭建單頁應用項目目錄。
該工具為現代化的前端開發工作流提供了開箱即用的構建配置。只需幾分鍾即可創建並啟動一個帶熱重載、保存時靜態檢查以及可用於生產環境的構建配置的項目:
// 生成一個基於 webpack 模板的新項目
vue init webpack 項目名
例如:
vue init webpack myproject
// 啟動開發服務器 ctrl+c 停止服務
cd myproject
npm run dev # 運行這個命令就可以啟動node提供的測試http服務器
運行了上面代碼以后,終端下會出現以下效果提示:
5.2.4.2 項目目錄結構
├── build/
├── config/
├── index.html
├── node_modules/ # 項目運行的依賴庫存儲目錄[非常大]
├── package.json # 項目運行需要的依賴庫記錄配置
├── src/
│ ├── App.vue # 父級組件
│ ├── assets/ # 靜態資源目錄,圖片存放在這里
│ ├── components/ # 單文件組件保存目錄
│ └── main.js
└── static/ # 靜態資源目錄,所有的css,js等文件放在這個目錄
src 主開發目錄,要開發的單文件組件全部在這個目錄下的components目錄下
static 靜態資源目錄,所有的css,js文件放在這個文件夾
dist 項目打包發布文件夾,最后要上線單文件項目文件都在這個文件夾中[后面打包項目,讓項目中的vue組件經過編譯變成js 代碼以后,dist就出現了]
node_modules目錄是node的包目錄,
config是配置目錄,
build是項目打包時依賴的目錄
src/router 路由,后面需要我們在使用Router路由的時候,自己聲明.
5.2.4.3 項目執行流程圖
整個項目是一個訪問入口文件index.html,index.html中會引入src文件夾中的main.js,main.js中會導入頂級單文件組件App.vue,App.vue中會通過組件嵌套或者路由來引用components文件夾中的其他單文件組件。
5.3 單文件組件的使用
組件有兩種:普通組件、單文件組件
普通組件的缺點:
- html代碼是作為js的字符串進行編寫,所以組裝和開發的時候不易理解,而且沒有高亮效果。
- 普通組件用在小項目中非常合適,但是復雜的大項目中,如果把更多的組件放在html文件中,那么維護成本就會變得非常昂貴。
- 普通組件只是整合了js和html,但是css代碼被剝離出去了。使用的時候的時候不好處理。
將一個組件相關的html結構,css樣式,以及交互的JavaScript代碼從html文件中剝離出來,合成一個文件,這種文件就是單文件組件,相當於一個組件具有了結構、表現和行為的完整功能,方便組件之間隨意組合以及組件的重用,這種文件的擴展名為“.vue”,比如:"Home.vue"。
-
創建組件
在組件中編輯三個標簽,編寫視圖template、vm對象script標簽和css樣式代碼style。
5.3.1 template 編寫html代碼的地方
<template>
<div id="Home">
<Header/>
<div class="main">
頁面主題內容
</div>
<div class="footer">
頁面腳步內容
</div>
</div>
</template>
5.3.2 script編寫vue.js代碼
<script>
import Header from "./common/Header"
export default {
name:"Home", // 組件名稱,用於以后路由跳轉
data(){ // 當前組件中需要使用的數據
return {
}
},
components:{
Header,
}
}
</script>
5.3.3 style編寫當前組件的樣式代碼
// scoped 表示當前style的樣式只作用於當前組件的template代碼中,其他地方不會被影響
<style scoped>
.header{
height: 100px;
line-height: 100px;
background-color: #eee;
text-align: center;
}
</style>
5.3.3.1 在Home.vue中引入子組件
創建保存子組件的目錄common
在common目錄下創建Header.vue
把Home.vue的style標簽的頭部樣式放置到Header.vue
<template>
<div id="Header" class="header">
頁面頭部
</div>
</template>
<script>
export default {
name:"Header", // 組件名稱,用於以后路由跳轉
data(){ // 當前組件中需要使用的數據
return {
}
}
}
</script>
// scoped 表示當前style的樣式只作用於當前組件的template代碼中,其他地方不會被影響
<style scoped>
.header{
height: 100px;
line-height: 100px;
background-color: #eee;
text-align: center;
}
</style>
5.3.4 完成案例-點擊加減數字
在Home.vue的主體部分里面直接編寫代碼了
<template>
<div id="Home">
<Header/>
<div class="main">
<p>加減數字的功能</p>
<div class="box">
<button @click="num++">+</button>
<input type="text" v-model="num">
<button @click="num--">-</button>
</div>
</div>
<div class="footer">
頁面腳步內容
</div>
</div>
</template>
<script>
import Header from "./common/Header"
export default {
name:"Home", // 組件名稱,用於以后路由跳轉
data(){ // 當前組件中需要使用的數據
return {
num:0,
}
},
components:{
Header,
}
}
</script>
// scoped 表示當前style的樣式只作用於當前組件的template代碼中,其他地方不會被影響
<style scoped>
.header{
height: 100px;
line-height: 100px;
background-color: #eee;
text-align: center;
}
</style>
效果:
5.3.4 組件的嵌套
有時候開發vue項目時,頁面也可以算是一個大組件,同時頁面也可以分成多個子組件.
因為,產生了父組件調用子組件的情況.
例如,我們可以聲明一個組件,作為父組件
在components/創建一個保存子組件的目錄HomeSon
在HomeSon目錄下,可以創建當前頁面的子組件,例如,是Menu.vue
// 組件中代碼必須寫在同一個標簽中
<template>
<div id="menu">
<span>{{msg}}</span>
<div>hello</div>
</div>
</template>
<script>
export default {
name:"Menu",
data: function(){
return {
msg:"這是Menu組件里面的菜單",
}
}
}
</script>
然后,在父組件中調用上面聲明的子組件。
最后,父組件被App.vue調用.就可以看到頁面效果.
效果:
5.3.5 傳遞數據
例如,我們希望把父組件Home.vue的數據傳遞給子組件,例如Header.vue.
可以通過props屬性來進行傳遞.
傳遞數據三個步驟:
-
在父組件中,調用子組件的組名處,使用屬性值的方式往下傳遞數據
<Menu :mynum="num" title="home里面寫的數據"/> // 上面表示在父組件調用Menu子組件的時候傳遞了2個數據: // 如果要傳遞變量[變量可以各種類型的數據],屬性名左邊必須加上冒號:,同時,屬性名是自定義的,會在子組件中使用。如果要傳遞普通字符串數據,則不需要加上冒號:
-
在子組件中接受上面父組件傳遞的數據,需要在vm組件對象中,使用props屬性類接受。
<script> export default { name:"Menu", props:["mynum","title"], data: function(){ return { msg:"這是Menu組件里面的菜單", } } } </script> // 上面 props屬性中表示接受了兩個數據。
-
在子組件中的template中使用父組件傳遞過來的數據.
<template> <div id="menu"> <span>{{msg}},{{title}}</span> <div>hello,{{mynum}}</div> </div> </template>
效果:
步驟流程:
使用父組件傳遞數據給子組件時, 注意一下幾點:
-
傳遞數據是變量,則需要在屬性左邊添加冒號.
傳遞數據是變量,這種數據稱之為"動態數據傳遞"
傳遞數據不是變量,而是數值或者字符串,這種數據稱之為"靜態數據傳遞"
-
父組件中修改了數據,在子組件中會被同步修改,但是,子組件中的數據修改了,是不會影響到父組件中的數據.
這種情況,在開發時,也被稱為"單向數據流"
事實上,我們如果要在子組件中把數據傳遞給父組件,也可以完成的。
通過事件冒泡的方式,進行數據傳遞
在vue中提供的this.$emit()方法進行給我們傳遞數據
5.4 在組件中使用axios獲取數據
默認情況下,我們的項目中並沒有對axios包的支持,所以我們需要下載安裝。
在項目根目錄中使用 npm安裝包在命令行下執行安裝包的命令:
npm install axios
接着在main.js文件中,導入axios並把axios對象 掛載到vue屬性中多為一個子對象,這樣我們才能在組件中使用。
// 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 axios from 'axios'; // 從node_modules目錄中導入包
Vue.config.productionTip = false
Vue.prototype.$axios = axios; // 把對象掛載vue中
/* eslint-disable no-new */
new Vue({
el: '#app',
components: { App },
template: '<App/>'
});
5.4.1 在組件中使用axios獲取數據
代碼編寫在Heaer.vue子組件中
<template>
<div id="Header" class="header">
{{message}}
<p>num: <input type="text" v-model="num"></p>
<p>深圳的天氣情況: {{weather_info}}</p>
</div>
</template>
<script>
export default {
name:"Header", // 組件名稱,用於以后路由跳轉
props:["num"],
data(){ // 當前組件中需要使用的數據
return {
message:"頁面頭部",
weather_info:"",
}
},
// 鈎子方法,在頁面中vue掛在data數據以后,自動執行
created() {
// 使用axios發送請求獲取數據
this.$http.get("http://wthrcdn.etouch.cn/weather_mini?city=深圳").then(response=>{
console.log(response.data);
console.log(response.data.data.ganmao);
this.weather_info = response.data.data.ganmao;
}).catch(error=>{
});
}
}
</script>
// scoped 表示當前style的樣式只作用於當前組件的template代碼中,其他地方不會被影響
<style scoped>
.header{
height: 100px;
line-height: 100px;
background-color: #eee;
text-align: center;
}
</style>
使用的時候,因為本質上來說,我們還是原來的axios,所以也會收到同源策略的影響。
后面開發項目的時候,我們會使用cors來解決跨域的問題。
小結
組件化開發
<template>
<div id="app">
<router-view/>
</div>
</template>
<script>
export default {
name: 'App',
props: ["prop1", "prop2"], // 接收父組件傳遞過來的數據
data(){ // data: function() {return {} }
return {}
},
components: {},
created(){},
}
</script>
<style>
</style>