網(wǎng)友投稿
891
2022-05-30
上一章節(jié)我們講解了組件的基礎(chǔ)知識(shí),本章我們將深入講解組件的傳值以及使用綜合案例進(jìn)行實(shí)踐操作。
5
6
7
8
9
6.1 兄弟組件傳值
在前面的內(nèi)容中我們已經(jīng)學(xué)習(xí)了父與子之間的傳值,接下來我們來看如果組件之間的關(guān)系是平級(jí)的也就是兄弟組件之間該如何傳值呢?兄弟傳值有兩種方式,一種是使用EventBus,另一種是借助父子傳值實(shí)現(xiàn)兄弟傳值,下面詳細(xì)解釋。
6.1.1 第一種方式Vue實(shí)例
我們先寫兩個(gè)兄弟組件,大家看案例代碼:
例6-1 Demo0601.html
1
2
3
4
5
6
7
8
子組件向父組件傳值9
10
16
表白墻
17
18
19
20
21
22
23
24
25
30
31
32
36
37
38
39
40
41 // 確定名字組件
42 let x1 = Vue.extend({
43 template: "#x1",
44 data() {
45 return {
46 username: ""
47 }
48 },
49
50 });
51 //確定名字后的表白組件
52 let x2 = Vue.extend({
53 template: "#x2"
54 });
55 var vm = new Vue({
56 el: '#app',
57 components: {
58 'likename': x1,
59 'likewords': x2
60 }
61
62
63 })
64
65
66
程序的運(yùn)行結(jié)果如下:
圖 6- 1 案例效果
我們現(xiàn)在要做的是在組件1中輸入喜歡人的名字,點(diǎn)擊確定按鈕,把名字傳給兄弟組件2中顯示。
第一步:建立一個(gè)空的Vue實(shí)例,用來兄弟組件之間的數(shù)據(jù)傳遞:
let bus = new Vue();
第二步:在組件1中觸發(fā)組件的事件:使用 $emit 觸發(fā),點(diǎn)擊按鈕的時(shí)候把名字傳過去
// 確定名字組件
let x1 = Vue.extend({
template: "#x1",
data() {
return {
username: ""
}
},
methods: {
getName() {
bus.$emit("editName", this.username);//點(diǎn)擊確定按鈕把名字傳過去
}
}
});
第三步:在組件2中接受,接受組件的事件: 使用 $on 接受,必須寫在鉤子函數(shù)中
//確定名字后的表白組件
let x2 = Vue.extend({
template: "#x2",
data() {
return {
name: "小麗",
}
},
methods: {
myfn() {
bus.$on("editName", (name) => {
this.name = name;
});
}
},
created() {
this.myfn();
}
});
也可以這樣寫,直接在鉤子函數(shù)中去接受傳過來的數(shù)據(jù)。
let x2 = Vue.extend({
template: "#x2",
data() {
return {
name: "小麗",
}
},
methods: {
},
created() {
bus.$on("editName", (name) => {
this.name = name;
});
}
});
完整代碼如下:
1
2
3
4
5
6
7
8
子組件向父組件傳值9
10
16
表白墻
17
18
19
20
21
22
23
24
25
30
31
32
33
34
{{name}}
35
你在我心中最美!
36
37
38
39
40
41
42 let bus = new Vue();
43 // 確定名字組件
44 let x1 = Vue.extend({
45 template: "#x1",
46 data() {
47 return {
48 username: ""
49 }
50 },
51 methods: {
52 getName() {
53 bus.$emit("editName", this.username)
54 }
55 }
56
57 });
58 //確定名字后的表白組件
59 let x2 = Vue.extend({
60 template: "#x2",
61 data() {
62 return {
63 name: "小麗",
64 }
65 },
66 methods: {
67 myfn() {
68 //editName是一個(gè)方法的名字,但是這個(gè)方法并不存在,on和emit兩個(gè)方法名字一致即可
69 bus.$on("editName", (name) => {
70 this.name = name;
71
72 });
73 }
74 },
75 created() {
76 this.myfn();
77 }
78 });
79 let vm = new Vue({
80 el: '#app',
81 components: {
82 'likename': x1,
83 'likewords': x2
84 }
85
86
87 })
88
89
90
通過例6-1中,我們通過一個(gè)空的Vue實(shí)例,來做中間容器,組件1輸入名字,點(diǎn)擊按鈕觸發(fā)Vue實(shí)例中的$on監(jiān)聽的方法 ,注意,$on和$emit后面的方法名字要一致,有同學(xué)會(huì)問,但是這個(gè)方法并不存在,這個(gè)方法的作用是用來保證on和emit監(jiān)聽和發(fā)送雙方的一致,所以該方法可以不存在但是必須保持一致。
6.1.2 第二種方式props和event
兄弟傳值也可以借助于同一個(gè)父組件,把兩個(gè)自組建的內(nèi)容都傳給父組件,通過父組件來實(shí)現(xiàn)數(shù)據(jù)交流。
接下來我們把上面的例子進(jìn)行改造,實(shí)現(xiàn)使用props和event方法兄弟傳值。
例6-2 Demo0602.html
1
2
3
4
5
6
7
8
兄弟組件傳值9
10
16
表白墻
17
18
19
20
21
22
23
24
25
30
31
32
33
34
{{myname}}
35
你在我心中最美!
36
37
38
39
40
41
42
43 // 確定名字組件
44 let x1 = Vue.extend({
45 template: "#x1",
46 data() {
47 return {
48 username: ""
49 }
50 },
51 methods: {
52 getName() {
53 this.$emit("getx1", this.username)
54 }
55 }
56
57 });
58 //確定名字后的表白組件
59 let x2 = Vue.extend({
60 props: ['myname'],
61 template: "#x2",
62 methods: {
63 },
64
65 });
66 let vm = new Vue({
67 el: '#app',
68 data: {
69 myname: ""http://用來接受組件1傳過來的值,然后再傳給組件2
70 },
71 components: {
72 'likename': x1,
73 'likewords': x2
74 },
75 methods: {
76 //把這個(gè)方法傳給組件1,在組件1中就可以觸發(fā)這個(gè)方法
77 getx1(name) {
78 this.myname = name;
79 }
80 }
81
82
83 })
84
85
86
程序的運(yùn)行結(jié)果如下:
圖 6- 2 使用父組件作為容器進(jìn)行兄弟傳值
通過例6-2中,我們先通過自定義事件,把組件1的值傳給父組件,然后父組件使用props把獲取的值傳給組件2,這樣也能夠?qū)崿F(xiàn)兄弟傳值。
6.1.3 第三種方式使用parent、children和refs
除了使用Vue空實(shí)例,以及父子傳值我們還可以使用Vue實(shí)例的三個(gè)屬性,分別是parent,children和refs,接下來我們來看這三種屬性如何使用:
This.$parent //獲取父組件
This.$children //獲取子組件
This.$refs.子組件ref的名字 //獲取子組件
1、ref為子組件指定一個(gè)索引名稱,通過索引來操作子組件;
2、this.$parent 可以直接訪問該組件的父實(shí)例或組件;
3、父組件也可以通過this.$children 訪問它所有的子組件; 需要注意 $children 并不保證順序,也不是響應(yīng)式的。
接下來我們來看案例中具體使用:
例6-3 Demo0603.html
1
2
3
4
5
6
7
8
兄弟傳值9
10
16
表白墻
17
18
19
20
21
22
23
24
25
30
31
32
33
34
{{name}}
35
你在我心中最美!
36
37
38
39
40
41
42
43 // 確定名字組件
44 let x1 = Vue.extend({
45 template: "#x1",
46 data() {
47 return {
48 username: ""
49 }
50 },
51 methods: {
52 getName() {
53 this.$parent.getx1(this.username);
54 }
55 }
56
57 });
58 //確定名字后的表白組件
59 let x2 = Vue.extend({
60 template: "#x2",
61 data() {
62 return {
63 name: '夏利'
64 }
65 },
66 methods: {
67 sonName(val) {
68 this.name = val;
69 },
70 },
71
72 });
73 let vm = new Vue({
74 el: '#app',
75 components: {
76 'likename': x1,
77 'likewords': x2
78 },
79 data: {
80
81 },
82 methods: {
83 //該方法調(diào)用組件2的方法給name賦值
84 //但是該方法會(huì)在組件1中調(diào)用,這樣就把組件1中username->sanme->組件2
85 getx1(sname) {
86 this.$refs.szj.sonName(sname);
87 },
88
89 }
90
91 })
92
93
94
程序的運(yùn)行結(jié)果與上面兩個(gè)案例效果相同。
下面我們來看代碼解析:
組件2使用ref加入索引:
父組件中提供宮組件1調(diào)用的方法:
methods: {
//該方法調(diào)用組件2的方法給name賦值
//但是該方法會(huì)在組件1中調(diào)用,這樣就把組件1中username->sanme->組件2
getx1(sname) {
this.$refs.szj.sonName(sname);
},
}
組件1中點(diǎn)擊確定按鈕,則把組件1中的名字傳值給父組件中的方法:
methods: {
getName() {
this.$parent.getx1(this.username);
}
}
例6-3中,我們也可以使用$children替換$refs,但是父組件有多個(gè)子組件,使用的時(shí)候要使用下標(biāo)說明調(diào)用的是哪個(gè)子組件。
methods: {
//該方法調(diào)用組件2的方法給name賦值
//但是該方法會(huì)在組件1中調(diào)用,這樣就把組件1中username->sanme->組件2
getx1(sname) {
console.log(this);
this.$children[1].sonName(sname);
},
}
6.2 跨級(jí)傳值
在Vue中,有時(shí)需要實(shí)現(xiàn)通信的兩個(gè)組件不是直接的父子組件,而是祖父和孫子,或者是跨越了更多層級(jí)的父子組件,這種時(shí)候就不可能由子組件一級(jí)一級(jí)的向上傳遞參數(shù),特別是在組件層級(jí)比較深,嵌套比較多的情況下,需要傳遞的事件和屬性較多,會(huì)導(dǎo)致代碼很混亂。這時(shí)就需要用到 vue 提供的更高階的方法:provide/inject。
這對(duì)選項(xiàng)需要一起使用,以允許一個(gè)祖先組件向其所有子孫后代注入一個(gè)依賴,不論組件層次有多深,并在起上下游關(guān)系成立的時(shí)間里始終生效。
provide/inject:簡單來說就是在父組件中通過provider來提供變量,然后在子組件中通過inject來注入變量,不管組件層級(jí)有多深,在父組件生效的生命周期內(nèi),這個(gè)變量就一直有效。
先看使用步驟:
provide() {
// 它的作用就是將 **name** 這個(gè)變量提供給它的所有子組件。
name: 'Jack'
},
methods: {
changeName() {
this.name = 'Lily'
}
}
子組件:
inject: ['name'], // 注入了從父組件中提供的name變量
mounted () {
console.log(this.name); // Jack
}
接下來演示完整案例:
例6-4 Demo0604.html
1
2
3
4
5
6
7
8
兄弟傳值9
10
16
父組件
17
18
19
20
21
22
23
24
25
26
27
兒子
28 兒子接受的值====>{{username}}
29
30
31
32
33
34 孫子接受的值===>{{username}}
35
36
37
38
39
40
41
42
43 //孫子組件
44 let sz = Vue.extend({
45 template: "#sz",
46 inject: ['username']
47
48 });
49 // 兒子組件
50 let ez = Vue.extend({
51 template: "#ez",
52 inject: ['username'],
53 components: { sz }
54
55 });
56 let vm = new Vue({
57 el: '#app',
58 components: {
59 ez
60 },
61 data: {
62 username: "你好世界"
63
64 },
65 provide() {
66 return {
67 username: "你好世界"
68 }
69 },
70
71 })
72
73
74
程序的運(yùn)行結(jié)果如下:
圖 6- 3 把父組件的值傳給兒子和孫子
例6-4中,該案例中的值不是相應(yīng)式的,也就是說如果父組件中的文本框內(nèi)的數(shù)據(jù)發(fā)生變化,兒子和孫子接受的值不是不會(huì)跟著變化的,如果想要響應(yīng)式變化我們可以使用如下代碼:
父組件容器:
// 父組件
......
data() {
return {
name: "Jack"
};
},
provide() {
return {
parentObj: this //提供祖先組件的實(shí)例
};
},
methods: {
changeName() {
this.name = 'Lily'
}
}
孫子容器:
export default {
inject:['parentObj']
例6-5 Demo0605.html
1
2 p
3
4
5
6
7
8
9
兄弟傳值10
11
17
父組件
18
19
20
21
22
23
24

25
26
27
28
兒子
29 兒子接受的值====>{{parentObj.username}}
30
31
32
33
34
35 孫子接受的值===>{{parentObj.username}}
36
37
38
39
40
41
42
43
44 //孫子組件
45 let sz = Vue.extend({
46 template: "#sz",
47 inject: ['parentObj']
48
49 });
50 // 兒子組件
51 let ez = Vue.extend({
52 template: "#ez",
53 inject: ['parentObj'],
54 components: { sz }
55
56 });
57 let vm = new Vue({
58 el: '#app',
59 components: {
60 ez
61 },
62 data: {
63 username: "你好世界"
64
65 },
66 provide() {
67 return {
68 parentObj: this
69 }
70 },
71
72 })
73
74
75
程序的運(yùn)行結(jié)果如下:
圖 6- 4 子孫組件的值會(huì)跟著父組件的變化而變化
以上是使用provide把父組件實(shí)例共享給子孫,子孫通過inject注入,就可以使用父組件的值。
6.3 綜合案例
有關(guān)組件的知識(shí),通過第五章和第六章我們已經(jīng)學(xué)習(xí)掌握,本節(jié)同通過實(shí)際操作來掌握有關(guān)父子傳值的知識(shí)。
6.3.1 效果和需求
效果
圖 6- 5 綜合案例效果圖
該案例實(shí)現(xiàn)了評(píng)論的增刪改查,以及模糊查詢和分頁查詢;
需求
? 實(shí)現(xiàn)所有評(píng)論的分頁查詢
? 實(shí)現(xiàn)模糊查詢
? 實(shí)現(xiàn)添加功能
? 實(shí)現(xiàn)修改功能
? 實(shí)現(xiàn)刪除功能
該案例綜合使用動(dòng)態(tài)組件、axios、以及組件傳值,希望大家通過練習(xí)該案例能夠掌握vue組件的基礎(chǔ)知識(shí)。
6.3.2 實(shí)際步驟
第一步:建立數(shù)據(jù)源
建立data.json,因?yàn)槲覀兊臄?shù)據(jù)最初是從json文件里面拿出來的,拿出來后存儲(chǔ)到本地中
1 {
2 "comments": [
3 {
4 "commentId": 1,
5 "content": "平凡的世界",
6 "comDate": "1999-09-09"
7 },
8 {
9 "commentId": 2,
10 "content": "白天與黑夜",
11 "comDate": "1999-09-09"
12 },
13 {
14 "commentId": 3,
15 "content": "這個(gè)很不錯(cuò)額",
16 "comDate": "1999-09-09"
17 },
18 {
19 "commentId": 4,
20 "content": "平凡的世界",
21 "comDate": "1999-09-09"
22 },
23 {
24 "commentId": 5,
25 "content": "平凡的世界",
26 "comDate": "1999-09-09"
27 }
28 ]
29 }
第二步:查詢建立頁面
在頁面上引入vue.js,bootstrap.csc、axios.js以及moment.js
其中moment.js 是用來時(shí)間格式化的。
1
2
3
4
5
6
7
8
評(píng)論案例9
10
18
19
20
21
22
23
評(píng)論案例24
25
33
34
35
編號(hào) | 36
內(nèi)容 | 37
日期 | 38
操作 | 39
---|
40
41
42 {{item.commentId}} 43 | 44
45 {{item.content}} 46 | 47
48 {{item.comDate}} 49 | 50
51 52 53 | 54
55
56
57
58
59
60
61
62
63
64 let vm = new Vue({
65 el: '#app',
66 data: {
67 coms: [],
68
69 },
70 methods: {
71 //獲取所有的評(píng)論
72 //先從本地獲取存儲(chǔ)中獲取評(píng)論,如果沒有則去data.json中獲取
73 allComs() {
74 let comments = JSON.parse(localStorage.getItem("comments") || "[]");
75 this.coms = comments;
76 if (comments.length === 0) {
77 axios.get("./data.json").then(resp => {
78 console.log(resp.data);
79 this.coms = resp.data.comments;
80 localStorage.setItem("comments", JSON.stringify(this.coms));
81 }, resp => {
82 console.log("error");
83 });
84 }
85
86
87 },
88 },
89 created() {
90 this.allComs();
91 },
92
93 })
94
95
96
97
程序運(yùn)行結(jié)果如下:
圖 6- 6 查詢所有評(píng)論
第四步:實(shí)現(xiàn)添加
添加的時(shí)候?qū)崿F(xiàn)評(píng)論id自增,通過計(jì)算屬性查詢出數(shù)組的最大值,在最大值的基礎(chǔ)上加1,在添加模板中,點(diǎn)擊添加按鈕,把最新添加的評(píng)論內(nèi)容添加到數(shù)組中和本地中。點(diǎn)擊添加按鈕的時(shí)候使用$parent調(diào)用父組件的方法。
寫添加模板:
1
2
3
14
15
添加的樣式:
1
2 .add {
3 width: 700px;
4 height: auto;
5 margin: 10px auto;
6 }
7
8
添加的時(shí)候,我們的編號(hào)是通過查找最大的編號(hào),然后在最大的編號(hào)的基礎(chǔ)上加1:
1 computed: {
2 num() {
3 let index = 1;
4 this.coms.forEach(item => {
5 let id = parseInt(item.commentId);
6 if (id > index) {
7 index = id;
8 }
9
10 });
11 return index;
12 }
13 }
14
添加模板中的方法:
1 let addCom = Vue.extend({
2 template: '#add',
3 data() {
4 return {
5 content: ""
6 }
7 },
8 methods: {
9 addItem() {
10 let obj = { content: this.content }
11 this.$parent.addCom(obj);
12 }
13 }
14
15 });
父組件中的添加方法:
1 //添加方法
2 addCom(item) {
3 item.commentId = this.num + 1;
4 let date = new Date();
5 let commentDate = moment(date).format('YYYY-MM-DD')
6 item.comDate = commentDate;
7 this.coms.push(item);
8 localStorage.setItem("comments", JSON.stringify(this.coms));
9
10 }
程序運(yùn)行如下:
圖 6- 7 實(shí)現(xiàn)添加評(píng)論
來看本地存儲(chǔ)中也添加了最新的數(shù)據(jù):
圖 6- 8 本地存儲(chǔ)添加最新數(shù)據(jù)
第五步:實(shí)現(xiàn)修改業(yè)務(wù);
點(diǎn)擊修改按鈕的時(shí)候,我們希望在添加的位置,顯示修改的模板,這個(gè)時(shí)候我們可以使用動(dòng)態(tài)組件component的is屬性,默認(rèn)顯示add組件。
1
2 .
3 .
4 .
5 data: {
6 coms: [],
7 addOrupdate: "add"
8
9 },
設(shè)置修改的模板,設(shè)置完畢模板后要在父組件中注冊:
1
2
3
18
點(diǎn)擊每一行的修改按鈕的時(shí)候要做以下事情:
? 表格上方改為修改模板
? 根據(jù)要修改的id找到這個(gè)數(shù)據(jù)
? 把該對(duì)象原來的數(shù)據(jù)傳到修改組件中
1 //點(diǎn)擊修改按鈕去修改
2 //1、在添加的位置顯示修改模板
3 //2、要修改的信息進(jìn)行回顯
4 toUpdate(id) {
5 this.addOrupdate = "update";
6 //根據(jù)id找到信息進(jìn)行回顯
7 let obj = {};
8 this.coms.some(c => {
9 if (c.commentId === id) {
10 obj = c;
11 return true;
12 }
13 });
14 this.upobj = obj;
15
16
17 },
現(xiàn)在把upobj傳給修改組件
1
2
3
4 //修改模板去接受
5 let updateCom = Vue.extend({
6 template: "#update",
7 props: ['upobj'],
8 });
由于使用props是單向向下的,只能父組件傳給子組件,但是子組件不能修改,所以我們要把props中的數(shù)據(jù)給data中的id和content,同時(shí)要監(jiān)視props數(shù)據(jù)的變化,一旦變化隨時(shí)傳值給data:
1 let updateCom = Vue.extend({
2 template: "#update",
3 props: ['upobj'],
4 data() {
5 return {
6 id: this.upobj.commentId,
7 content: this.upobj.content
8 }
9 },
10 watch: {
11 //監(jiān)聽父組件傳過來的值,只要傳過來的值發(fā)生變化,子組件的data中的數(shù)據(jù)也會(huì)跟著變化
12 upobj(val) {
13 this.id = val.commentId;
14 this.content = val.content;
15 }
16 }
17
18
19 });
20
程序運(yùn)行如下:
圖 6- 9 點(diǎn)擊修改按鈕數(shù)據(jù)回顯成功
點(diǎn)擊提交實(shí)現(xiàn)修改:
點(diǎn)擊提交,根據(jù)最新的數(shù)據(jù)生成一個(gè)對(duì)象,然后在子組件中調(diào)用父組件的修改方法,實(shí)現(xiàn)修改業(yè)務(wù):
1 //父組件中的修改的方法
2 update(obj) {
3 console.log(obj);
4 obj.comDate = moment(new Date()).format("YYYY-MM-DD");
5 this.coms.some(c => {
6 if (c.commentId === obj.commentId) {
7 c.content = obj.content;
8 c.comDate = obj.comDate;
9 return true;
10 }
11 });
12 //本地存儲(chǔ)做出修改
13 localStorage.setItem("comments", JSON.stringify(this.coms));
14 //修改頁面恢復(fù)為添加
15 this.addOrupdate = "add";
16
17 }
18 //修改子組件的方法
19 methods: {
20 //修改的方法
21 //把修改的數(shù)據(jù)覆蓋掉之前的數(shù)據(jù)
22 //在子組件中調(diào)用父組件的修改方法
23 upfn() {
24 let obj = {
25 commentId: this.id,
26 content: this.content
27 }
28 this.$parent.update(obj);
29
30 }
31
32 },
33
第六步:實(shí)現(xiàn)刪除
點(diǎn)擊刪除按鈕的時(shí)候,實(shí)現(xiàn)從data中的coms中刪除,同時(shí)跟localStorage保持一致:
1 //執(zhí)行刪除功能
2 //根據(jù)id查找,找到后刪除
3 del(id) {
4 this.coms.some((c, index) => {
5 if (c.commentId === id) {
6 this.coms.splice(index, 1);
7 return true;
8 }
9 });
10 localStorage.setItem("comments", JSON.stringify(this.coms));
11 }
12
第七步:實(shí)現(xiàn)搜索
定義搜索的模板,然后在父組件中注冊:
1
2
3
4
10
點(diǎn)擊查找按鈕,進(jìn)行調(diào)用父組件中的查找方法:
1 //搜索
2 let searchCom = Vue.extend({
3 template: "#search",
4 data() {
5 return {
6 keywords: ""
7 }
8 },
9 methods: {
10 searfn() {
11 this.$parent.search(this.keywords);
12
13 }
14 }
15 });
16
17 //父組件的搜索功能,scoms是在父組件中定義的專門用來存儲(chǔ)搜索后結(jié)果的數(shù)組,同時(shí)table遍歷改成使用scoms
18 search(kw) {
19 this.scoms = this.coms.filter(item => {
20 return item.content.includes(kw);
21 });
22 }
23 //最開是的查詢所有變成如下代碼
24 allComs() {
25 let comments = JSON.parse(localStorage.getItem("comments") || "[]");
26 this.coms = comments;
27 if (comments.length === 0) {
28 axios.get("./data.json").then(resp => {
29 console.log(resp.data);
30 this.coms = resp.data.comments;
31 localStorage.setItem("comments", JSON.stringify(this.coms));
32 }, resp => {
33 console.log("error");
34 });
35 }
36 this.scoms = this.coms;//把原來的數(shù)組給搜索的結(jié)果
37
38 },
程序運(yùn)行結(jié)果如下:
圖 6- 10 模糊查詢的功能
第八步:實(shí)現(xiàn)分頁
定義分頁模板:
11
12
13
思考:分頁組件中的總頁數(shù)是從父組件中傳過來的;
父組件定義計(jì)算屬性:
1 //計(jì)算總頁數(shù)
2 pagenum() {
3 return Math.ceil(this.scoms.length / this.pageSize);
4 }
把這個(gè)屬性傳值給分頁組件:
1
2
3
4 let page = Vue.extend({
5 template: "#page",
6 props: ['pagenum'],
7 data() {
8 return {
9 num: this.pagenum
10 }
11 },
12 watch: {
13 pagenum(val) {
14 this.num = val;
15
16 }
17 }
18 });
19
模板中循環(huán)頁碼:
1
2
3
4
11
接下來實(shí)現(xiàn)默認(rèn)顯示第一頁的內(nèi)容:
在這我們使用的是數(shù)組的slice方法可以截取某一個(gè)段,所以我們需要計(jì)算開始和結(jié)束位置:
12
1
2 //使用計(jì)算屬性計(jì)算截取的開始位置
3 start() {
4 return this.pageIndex * this.pageSize - this.pageSize;
5
6 },
7
8 //截取的結(jié)束位置
9 end() {
10 return this.pageIndex * this.pageSize;
11
12 }
模板變化:
1
2
3
10
實(shí)現(xiàn)點(diǎn)擊頁碼顯示相應(yīng)的內(nèi)容:
11 methods: {
1 //分頁組件的點(diǎn)擊頁碼事件
2 goto(n) {
3 this.$parent.changePageIndex(n);
4
5 }
6 }
7
8 //父組件的方法
9 //執(zhí)行顯示相應(yīng)的頁碼的內(nèi)容,本質(zhì)就是改變頁碼
10 changePageIndex(val) {
11 this.pageIndex = val;
12
13 }
14
實(shí)現(xiàn)上一頁下一頁的功能:
1 methods: {
1 //分頁組件的點(diǎn)擊頁碼事件
2 goto(n) {
3 this.$parent.changePageIndex(n);
4
5 },
6 //子組件的上一頁
7 prev() {
8 this.$parent.goUp();
9 },
10 //自組建的下一頁
11 next() {
12 this.$parent.goDown();
13 }
14 }
15
16 //父組件的上一頁下一頁
17 //上一頁
18 goUp() {
19 if (this.pageIndex === 1) {
20 alert("已經(jīng)是第一頁了");
21 } else {
22 this.pageIndex = this.pageIndex - 1;
23 }
24
25 },
26 //下一頁
27 goDown() {
28 if (this.pageIndex === this.pagenum) {
29 alert("已經(jīng)是最后一頁了");
30 } else {
31 this.pageIndex = this.pageIndex + 1;
32 }
33 }
6.3.3 完整案例
Data.json
1
2 {
3 "comments": [
4 {
5 "commentId": 1,
6 "content": "平凡的世界",
7 "comDate": "1999-09-09"
8 },
9 {
10 "commentId": 2,
11 "content": "白天與黑夜",
12 "comDate": "1999-09-09"
13 },
14 {
15 "commentId": 3,
16 "content": "這個(gè)很不錯(cuò)額",
17 "comDate": "1999-09-09"
18 },
19 {
20 "commentId": 4,
21 "content": "平凡的世界",
22 "comDate": "1999-09-09"
23 },
24 {
25 "commentId": 5,
26 "content": "人間失格",
27 "comDate": "1999-09-09"
28 },
29 {
30 "commentId": 6,
31 "content": "yyh",
32 "comDate": "1999-09-09"
33 },
34 {
35 "commentId": 7,
36 "content": "yyh當(dāng)當(dāng)",
37 "comDate": "1999-09-09"
38 }
39 ]
40 }
綜合案例.html
1
2
3
4
5
6
7
8
評(píng)論案例9
10
40
41
42
43
44
45
46
47
編號(hào) | 48
內(nèi)容 | 49
日期 | 50
操作 | 51
---|
52
53
54 {{item.commentId}} 55 | 56
57 {{item.content}} 58 | 59
60 {{item.comDate}} 61 | 62
63 64 65 | 66
67
68
69
70
71
72
73
74
75
76
77
88
89
90
91
92
93
106
107
108
109
110
116
117
118
119
120
127
128
129
130
131 //添加
132 let addCom = Vue.extend({
133 template: '#add',
134
135 data() {
136 return {
137 content: ""
138 }
139 },
140 methods: {
141 addItem() {
142 let obj = { content: this.content }
143 this.$parent.addCom(obj);
144 }
145 },
146
147
148
149 });
150 //修改
151 let updateCom = Vue.extend({
152 template: "#update",
153 props: ['upobj'],
154 data() {
155 return {
156 id: this.upobj.commentId,
157 content: this.upobj.content
158 }
159 },
160 methods: {
161 //修改的方法
162 //把修改的數(shù)據(jù)覆蓋掉之前的數(shù)據(jù)
163 //在子組件中調(diào)用父組件的修改方法
164 upfn() {
165 let obj = {
166 commentId: this.id,
167 content: this.content
168 }
169 this.$parent.update(obj);
170
171 }
172
173 },
174 watch: {
175 //監(jiān)聽父組件傳過來的值,只要傳過來的值發(fā)生變化,子組件的data中的數(shù)據(jù)也會(huì)跟著變化
176 upobj(val) {
177 this.id = val.commentId;
178 this.content = val.content;
179 }
180 }
181
182
183 });
184 //搜索
185 let searchCom = Vue.extend({
186 template: "#search",
187 data() {
188 return {
189 keywords: ""
190 }
191 },
192 methods: {
193 searfn() {
194 this.$parent.search(this.keywords);
195
196 }
197 }
198 });
199 //分頁
200 let page = Vue.extend({
201 template: "#page",
202 props: ['pagenum'],
203 data() {
204 return {
205 num: this.pagenum
206 }
207 },
208 watch: {
209 pagenum(val) {
210 this.num = val;
211
212 }
213 },
214 methods: {
215 //分頁組件的點(diǎn)擊頁碼事件
216 goto(n) {
217 this.$parent.changePageIndex(n);
218
219 },
220 //子組件的上一頁
221 prev() {
222 this.$parent.goUp();
223 },
224 //自組建的下一頁
225 next() {
226 this.$parent.goDown();
227 }
228 }
229 });
230 let vm = new Vue({
231 el: '#app',
232 data: {
233 coms: [],
234 addOrupdate: "add",
235 upobj: {},//保存被修改的對(duì)象
236 scoms: [],
237 pageSize: 3,//每頁顯示的條數(shù)
238 pageIndex: 1,//當(dāng)前頁碼
239
240 },
241 components: {
242 "add": addCom,
243 "update": updateCom,
244 "search": searchCom,
245 page
246 },
247 methods: {
248 //獲取所有的評(píng)論
249 //先從本地獲取存儲(chǔ)中獲取評(píng)論,如果沒有則去data.json中獲取
250 allComs() {
251 let comments = JSON.parse(localStorage.getItem("comments") || "[]");
252 this.coms = comments;
253 if (comments.length === 0) {
254 axios.get("./data.json").then(resp => {
255 console.log(resp.data);
256 this.coms = resp.data.comments;
257 localStorage.setItem("comments", JSON.stringify(this.coms));
258 }, resp => {
259 console.log("error");
260 });
261 }
262 this.scoms = this.coms;
263
264 },
265
266 //添加方法
267 addCom(item) {
268 item.commentId = this.num + 1;
269 let date = new Date();
270 let commentDate = moment(date).format('YYYY-MM-DD')
271 item.comDate = commentDate;
272 this.coms.push(item);
273 this.scoms = this.coms;
274 localStorage.setItem("comments", JSON.stringify(this.coms));
275
276 },
277 //點(diǎn)擊修改按鈕去修改
278 //1、在添加的位置顯示修改模板
279 //2、要修改的信息進(jìn)行回顯
280 toUpdate(id) {
281 this.addOrupdate = "update";
282 //根據(jù)id找到信息進(jìn)行回顯
283 let obj = {};
284 this.coms.some(c => {
285 if (c.commentId === id) {
286 obj = c;
287 return true;
288 }
289 });
290 this.upobj = obj;
291
292
293 },
294 //父組件中的修改的方法
295 update(obj) {
296 console.log(obj);
297 obj.comDate = moment(new Date()).format("YYYY-MM-DD");
298 this.coms.some(c => {
299 if (c.commentId === obj.commentId) {
300 c.content = obj.content;
301 c.comDate = obj.comDate;
302 return true;
303 }
304 });
305 this.scoms = this.coms;
306 //本地存儲(chǔ)做出修改
307 localStorage.setItem("comments", JSON.stringify(this.coms));
308 //修改頁面恢復(fù)為添加
309 this.addOrupdate = "add";
310
311 },
312 //執(zhí)行刪除功能
313 //根據(jù)id查找,找到后刪除
314 del(id) {
315 this.coms.some((c, index) => {
316 if (c.commentId === id) {
317 this.coms.splice(index, 1);
318 return true;
319 }
320 });
321 this.scoms = this.coms;
322 localStorage.setItem("comments", JSON.stringify(this.coms));
323 },
324 //父組件的搜索功能
325 search(kw) {
326
327 this.scoms = this.coms.filter(item => {
328 return item.content.includes(kw);
329 });
330 },
331 //執(zhí)行顯示相應(yīng)的頁碼的內(nèi)容,本質(zhì)就是改變頁碼
332 changePageIndex(val) {
333 this.pageIndex = val;
334
335 },
336 //上一頁
337 goUp() {
338 if (this.pageIndex === 1) {
339 alert("已經(jīng)是第一頁了");
340 } else {
341 this.pageIndex = this.pageIndex - 1;
342 }
343
344 },
345 //下一頁
346 goDown() {
347 if (this.pageIndex === this.pagenum) {
348 alert("已經(jīng)是最后一頁了");
349 } else {
350 this.pageIndex = this.pageIndex + 1;
351 }
352 }
353
354 },
355 created() {
356 this.allComs();
357 },
358 computed: {
359 num() {
360 let index = 1;
361 this.coms.forEach(item => {
362 let id = parseInt(item.commentId);
363 if (id > index) {
364 index = id;
365 }
366
367 });
368 return index;
369 },
370 //計(jì)算總頁數(shù)
371 pagenum() {
372 return Math.ceil(this.scoms.length / this.pageSize);
373 },
374 //截取的開始位置
375 start() {
376 return this.pageIndex * this.pageSize - this.pageSize;
377
378 },
379
380 //截取的結(jié)束位置
381 end() {
382 return this.pageIndex * this.pageSize;
383
384 }
385 }
386
387 })
388
389
390
391
6.4 本章小結(jié)
? 兄弟組件傳值有三種方式:空的Vue實(shí)例、props和event結(jié)合以及parent/children/refs;
? 跨級(jí)組件傳值使用provider在父組件中申明,使用inject在孫子組件中注入;
? 綜合案例掌握不同組件之間的數(shù)據(jù)通訊,以及axios的初步使用以及動(dòng)態(tài)組件的使用。
6.5 理論試題與實(shí)踐練習(xí)
1.思考題
1.1 請簡述如何使用空的Vue實(shí)例傳值;
1.2 請簡述如何使用props和event實(shí)現(xiàn)兄弟組件傳值;
1.3 請簡述parent/children/refs的使用;
1.4 請簡述跨級(jí)provicer/inject的使用步驟;
1.5 請簡述keep-alive的使用和以及鉤子函數(shù);
1.6 請簡述動(dòng)態(tài)組件如何傳值;
2.編程題
實(shí)現(xiàn)圖書管理的增刪改查以及分頁和模糊查詢
Vue
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。
亚洲高清在线观看|
国产亚洲高清不卡在线观看|
爱爱帝国亚洲一区二区三区|
avtt天堂网手机版亚洲|
亚洲色偷偷偷网站色偷一区|
亚洲视频精品在线|
亚洲欧洲日产国码久在线观看|
亚洲不卡视频在线观看|
亚洲成a人不卡在线观看|
亚洲白嫩在线观看|
亚洲国产高清视频在线观看|
亚洲激情校园春色|
亚洲一区免费在线观看|
亚洲卡一卡二卡乱码新区|
2020国产精品亚洲综合网|
亚洲日韩精品国产3区|
亚洲成熟丰满熟妇高潮XXXXX|
亚洲国产成人久久综合|
精品久久久久久亚洲综合网|
亚洲国产成人精品女人久久久|
亚洲国产精品人人做人人爱|
久久久无码精品亚洲日韩软件|
久久久无码精品亚洲日韩软件|
亚洲精品无码久久久久sm|
久久精品国产亚洲av麻|
亚洲性天天干天天摸|
久久久婷婷五月亚洲97号色|
亚洲国产成人久久|
亚洲午夜精品久久久久久app|
亚洲成a人无码亚洲成av无码|
偷自拍亚洲视频在线观看99|
亚洲麻豆精品国偷自产在线91|
亚洲日韩精品一区二区三区|
亚洲精品高清国产一久久|
亚洲小视频在线播放|
亚洲精品无码专区久久|
亚洲国产精品无码久久青草|
国产亚洲精品岁国产微拍精品|
久久狠狠高潮亚洲精品|
ASS亚洲熟妇毛茸茸PICS|
在线观看亚洲免费视频|