前言
您將在本文當(dāng)中了解到,往網(wǎng)頁中添加數(shù)據(jù),從傳統(tǒng)的dom操作過渡到數(shù)據(jù)層操作,實(shí)現(xiàn)同一個(gè)目標(biāo),兩種不同的方式.以及什么是組件,如何定義和使用組件,父子組件之間如何進(jìn)行簡(jiǎn)單的通信傳值...
對(duì)于vuejs,我也只是個(gè)初學(xué)者,很多人都覺得簡(jiǎn)單,但我覺得是它并不容易的,就像JQuery的,常用的API也就那些,但是遇到一些炫酷的效果,就是寫不來。
在切換到寫Vuejs代碼中,你不需要去關(guān)注dom層操作,更多的精力是放在處理數(shù)據(jù)上,數(shù)據(jù)是什么,就讓頁面顯示什么,操作數(shù)據(jù)功戚,就是在操做view(視圖),這與JQuery是不一樣的,編程思路是需要進(jìn)行轉(zhuǎn)化的
單純的vuejs其實(shí)是不足以撼動(dòng)jQuery的地位的,它的強(qiáng)大之處在于它的生態(tài)系統(tǒng)非常豐富,路由,模型,UI組件等各個(gè)部分的鉤子等令vuejs風(fēng)靡國(guó)內(nèi)外,借鑒了Angular中指令,React中組件化等,上手相對(duì)而言比較容易
如今jQuery時(shí)代真是江河日下了,這里我并不是說它不重要,它仍然是非常優(yōu)秀而重要的,只是任何技術(shù)都有輝煌和落幕的時(shí)候,時(shí)代在進(jìn)步,技術(shù)也在不斷更新迭代..
從github上的star數(shù)看得出,vue勢(shì)頭略蓋過react,甩angular幾條街,已形成三足鼎立趨勢(shì),凡是react,angular能做的,無論是pc,移動(dòng)端,甚至webapp,pwa應(yīng)用(lavas=vue+pwa),小程序(wepy),vue幾乎無孔不入了
在vue的使用過程中,從開始學(xué)習(xí)單純的引入script標(biāo)簽加載vuejs腳本形式到最終使用vue-cli腳手架搭建出來的項(xiàng)目,它又換成另外一種編程思路
前一種方式更多是對(duì)vuejs中的一些API學(xué)習(xí)的驗(yàn)證,還是可以的,它是把html,js和各種邏輯耦合在一起進(jìn)行編碼,類似于jQuery的風(fēng)格.它也能搞事,但是這與腳手架搭建起的應(yīng)用是不同的
后一種使用腳手架方式卻是我們常用的方式,它是以一種單文件組件方式,也就是以.vue后綴名文件就是一個(gè)組件,這個(gè)單文件組件定義包含了模板,邏輯和它的樣式,它做了一個(gè)非常好的組件封裝.
在vuejs中組件與組件之間的通信,關(guān)聯(lián)操作,數(shù)據(jù)共享,路由狀態(tài)的切換變更,UI組件的嵌套,插件與主程序的額外拓展等,如果你覺得處理他們起來覺得很簡(jiǎn)單,那才是真簡(jiǎn)單..
本文并不是什么高大上的內(nèi)容,首次分享vue學(xué)習(xí)筆記心得,關(guān)于vue的知識(shí)特別多,也特別雜,旨在記錄自己學(xué)習(xí)過程中的一些困惑和理解,如果你是大神,就直接忽略吧娶眷,也歡迎路過的老師多提意見和指正
vuejs是什么?
它只關(guān)注視圖層的view,是構(gòu)建用戶界面的漸進(jìn)式框架
數(shù)據(jù)驅(qū)動(dòng),聲明式渲染(模板,插值表達(dá)式),模塊化,組件化,客戶端路由(vue-router),數(shù)據(jù)狀態(tài)管理(vuex),構(gòu)建工具(vue-cli)
vue中核心點(diǎn)
響應(yīng)式數(shù)據(jù)綁定,當(dāng)數(shù)據(jù)(model層)發(fā)生改變,它會(huì)自動(dòng)更新視圖(view),內(nèi)部實(shí)現(xiàn)原理是利用Es5中的Object.definedProperty中的setter/getter代理數(shù)據(jù),監(jiān)控對(duì)數(shù)據(jù)的操作
視圖組件,UI界面對(duì)應(yīng)的每個(gè)功能模塊,可視為組件,劃分組件是為了更好管理,維護(hù),實(shí)現(xiàn)代碼的復(fù)用,減少代碼之間的依賴,也就是逼格高一詞,高內(nèi)聚,低耦合
虛擬DOM:運(yùn)行js的速度是很快的,大量的操作DOM就會(huì)很慢,時(shí)常在更新數(shù)據(jù)后會(huì)重新渲染頁面,這樣造成在沒有改變數(shù)據(jù)的地方也重新渲染了DOM節(jié)點(diǎn),這樣就造成了很大程度上的資源浪費(fèi),用內(nèi)存中生成與真實(shí)DOM與之對(duì)應(yīng)的數(shù)據(jù)結(jié)構(gòu),這個(gè)在內(nèi)存中生成的結(jié)構(gòu)稱為虛擬DOM,當(dāng)model中數(shù)據(jù)發(fā)生變化時(shí),Vue會(huì)將模板編譯成虛擬 DOM 渲染函數(shù),并結(jié)合響應(yīng)系統(tǒng),在應(yīng)用狀態(tài)改變時(shí),vuejs能夠智能地計(jì)算出重新渲染組件,并以最小代價(jià)并應(yīng)用到DOM操作上
MVVM模式:其中M:model數(shù)據(jù)模型,V:view視圖模板,而VM(觀察者,vue幫我們實(shí)現(xiàn)了的):view model負(fù)責(zé)業(yè)務(wù)處理,對(duì)數(shù)據(jù)進(jìn)行加工,處理,之后交給視圖,它是通過在摸板中指令與數(shù)據(jù)進(jìn)行關(guān)聯(lián)控制的疫铜,使用mvvm模式,編碼的重點(diǎn)是在于view層和model層,以前是面對(duì)DOM開發(fā)(MVP),現(xiàn)在更多的是面向數(shù)據(jù)編程
上面羅列出來的呢,只是一些抽象的概念,具體的理解,必須得通過代碼才能體會(huì)的,在以后的文章的中都會(huì)一一的去探索和感受
vuejs的使用
方式1:獨(dú)立引用(本地方式),通過script標(biāo)簽形式(本篇示例先已這種方式)
方式2:線上引用,bootcdn(直接引入或者下載到本地都可以)
方式3:npm方式(npm install vue),獲取最新穩(wěn)定版本
方式4:命令行方式(vue-cli腳手架工具)
原生js實(shí)現(xiàn)一dom需求操作
往頁面中插入一個(gè)button按鈕茂浮,和一內(nèi)容,并且點(diǎn)擊按鈕時(shí),改變它自身的顏色,實(shí)現(xiàn)內(nèi)容的顯示和隱藏的效果:實(shí)例效果如下,例子很簡(jiǎn)單,旨在于與vue做比較
實(shí)現(xiàn)方式1:利用原生js
css代碼
body {
margin:0;
text-align:center;
}
button {
width:100px;
height:50px;
margin-top:50px;
background:green;
color:#fff;
outline:none;
border:none;
border-radius:5px;
cursor:pointer;
margin-bottom:10px;
}
JavaScript代碼
*
MVP:模式,原生js操作dom
1. 獲取dom元素節(jié)點(diǎn),創(chuàng)建元素
2. 添加元素dom操作
3. 添加事件操作,邏輯處理
*/
window.onload = function(){
var oBody = document.getElementsByTagName("body")[0], // 獲取dom節(jié)點(diǎn)
oDiv = document.createElement("div"), // 創(chuàng)建div元素
oBtn = document.createElement("button"),// 創(chuàng)建button元素
onOff = true; // 切換狀態(tài)
oDiv.setAttribute("class","content"); // 給div元素添加一個(gè)content類
oBtn.setAttribute("id","btn"); // 給button按鈕添加一個(gè)id為btn
oBtn.innerHTML = "點(diǎn)我按鈕"; // dom操作,添加內(nèi)容
oDiv.innerHTML = "我是川川"; // 同上
oBody.appendChild(oBtn);// 把節(jié)點(diǎn)元素添加到dom中
oBody.appendChild(oDiv);
// 添加事件
oBtn.onclick = function(){// 添加事件,改變樣式,執(zhí)行邏輯
if(onOff){
this.style.backgroundColor="red";
oDiv.style.display = "none";
// hide()
}else{
this.style.backgroundColor="green";
oDiv.style.display = "block";
// show()
}
//onOff==true?hide():show();
onOff = !onOff;
}
// 可以把里面的代碼封裝一下
// 隱藏
/*function hide(){
oBtn.style.backgroundColor="red";
oDiv.style.display = "none";
}
// 顯示
function show(){
oBtn.style.backgroundColor="green";
oDiv.style.display = "block";
}*/
}
實(shí)現(xiàn)方式2:jQuery
css代碼:并沒有什么多大的改變,只是添加來類名
body{
margin:0;
text-align:center;
}
.btn{
width:100px;
height:50px;
margin-top:50px;
background:green;
color:#fff;
outline:none;
border:none;
border-radius:5px;
cursor:pointer;
margin-bottom:10px;
}
.activeBtn{
background:red;
}
jQuery代碼
$(function(){
var $body = $("body"),
$btn = $("<button id='btn' class='btn'>點(diǎn)我按鈕</button>"),
$div = $("<div class='div'>我是川川</div>"),
onOff = true;
$body.append($btn);
$body.append($div);
$btn.click(function(){
if(onOff){
$(this).addClass('activeBtn');
$div.css("display","none");
}else{
$(this).removeClass('activeBtn');;
$div.css("display","block");
}
onOff = !onOff;
})
})
實(shí)現(xiàn)方式3:vue
css代碼同上:
html代碼,模板
<div id="app">
<button id="btn" class="btn" v-bind:class="status?defaultClass:activeClass" v-on:click="btnFun">{{btnMsg}}</button>
<div v-if="status" class="content">{{descMsg}}</div>
</div>
使用vuejs代碼
var vm = new Vue({
el: "#app",
data: {
btnMsg: "點(diǎn)我按鈕",
descMsg: "我是川川",
status:true,
defaultClass:"btn",
activeClass:"activeBtn"
},
methods:{
btnFun:function(){
this.status = !this.status;
}
}
})
上面的代碼也可以整合成這樣
var data = {
btnMsg: "點(diǎn)我按鈕",
descMsg: "我是川川",
status:true,
defaultClass:"btn",
activeClass:"activeBtn"
}
var methodsObj = {
btnFun:function() {
this.status = !this.status;
}
}
var vm = new Vue({
el: "#app",
data:data,
methods:methodsObj
})
三種方法對(duì)比:
共同點(diǎn):實(shí)現(xiàn)同一個(gè)效果,但是底層邏輯都是一致的
不同點(diǎn)::用原生js,jQuery這兩種方式在于操作DOM,怎么創(chuàng)建,獲取,遍歷元素等,添加事件,需借助原生方法或者jQuery提供的方法操作dom,而vuejs,它關(guān)注點(diǎn)是數(shù)據(jù),數(shù)據(jù)是什么,就讓頁面顯示什么,并通過在模板中綁定指令,屬性的方式與數(shù)據(jù)進(jìn)行關(guān)聯(lián),數(shù)據(jù)與方法進(jìn)行分離,數(shù)據(jù)驅(qū)動(dòng)實(shí)現(xiàn)頁面的渲染
在上面的vuejs代碼中,涉及到的知識(shí)有:vue實(shí)例化的屬性和方法,模板,插值表達(dá)式({{表達(dá)式}}),指令,屬性的綁定,事件方法監(jiān)聽綁定,條件渲染v-if,動(dòng)態(tài)綁定class:
其中el:實(shí)例選項(xiàng),值的類型是字符串或者實(shí)際html元素對(duì)象,邊界管理,掛載點(diǎn),確定vue的作用域范圍
data:實(shí)例選項(xiàng),數(shù)據(jù)壳咕,值的類型可以是Object或者函數(shù),注意在定義子組件時(shí),只接受function methods:實(shí)例選項(xiàng),方法,值是一個(gè)對(duì)象,注意,不要使用箭頭函數(shù)定methods函數(shù),例如:btn:()=>tthis.status = !this.status,箭頭函數(shù)綁定來父級(jí)作用域的上下文,所以這個(gè)this將不會(huì)指向這個(gè)vue實(shí)例,this.status將是undefined
插值表達(dá)式:雙大括號(hào)語法{{表達(dá)式}}這是數(shù)據(jù)綁定最常見的形式顽馋,其中雙大括號(hào)里面的表達(dá)式,不僅僅可以是變量,還可以進(jìn)行簡(jiǎn)單邏輯(加減..判斷)運(yùn)算谓厘,注意表達(dá)式若在雙大括號(hào)之外,它是不起作用的,大括號(hào)相當(dāng)于是聲明了具備了vue的執(zhí)行壞境
v-html:值的類型是string,它是在html標(biāo)簽內(nèi)聯(lián)中寫的,v-html="",雙大括號(hào)會(huì)將數(shù)據(jù)解釋為純文本,并不是HTML ,為了渲染輸出真正的 HTML 寸谜,你需要使用 v-html 指令,被插入的內(nèi)容都會(huì)被當(dāng)做 HTML竟稳,數(shù)據(jù)綁定會(huì)被忽略
注意,你不能使用 v-html 來復(fù)合局部模板熊痴,因?yàn)?Vue 不是基于字符串的模板引擎他爸。組件更適合擔(dān)任 UI 重用與復(fù)合的基本單元
網(wǎng)站上動(dòng)態(tài)渲染的任意 HTML 可能會(huì)非常危險(xiǎn),因?yàn)樗苋菀讓?dǎo)致 XSS 攻擊果善。應(yīng)該對(duì)可信內(nèi)容使用 HTML 插值诊笤,絕不要對(duì)用戶提供的內(nèi)容插值,例如表單之類的巾陕,正常情況下,都是用插值表達(dá)式雙大括號(hào)方式
v-text:值的類型是string,例如:v-html="",更新元素文本內(nèi)容,與插值表達(dá)式是等價(jià)的,與v-html區(qū)別是,它不會(huì)渲染解析html標(biāo)簽,會(huì)原樣當(dāng)做字符串輸出
v-on:指令:綁定事件監(jiān)聽器,事件的類型由參數(shù)指定,可縮寫@符號(hào),值的類型:函數(shù)(方法),它是寫在內(nèi)聯(lián)元素html標(biāo)簽上的,可以攜帶參數(shù),v-on:click=“方法名"
注意:用在普通元素上,只能監(jiān)聽原生DOM事件,用在自定義元素組件上時(shí),也可以監(jiān)聽子組件觸發(fā)的自定義事件(這在子組件向父組件傳值的時(shí)候,子組件通過$emit內(nèi)置的實(shí)例方法觸發(fā)自定義事件,這個(gè)自定義事件是寫綁定在父組件上的,這個(gè)特別重要)
v-bind:綁定內(nèi)聯(lián)html標(biāo)簽元素的屬性(style,class,id,src,title,alt,width,height等),值的類型任何,可簡(jiǎn)寫為冒號(hào):,例如v-bind:href="";v-bind:class="",:title="",動(dòng)態(tài)地綁定一個(gè)或多個(gè)特性讨跟,或一個(gè)組件 prop到表達(dá)式,綁定自定義屬性
v-if:值的類型任何,根據(jù)表達(dá)式的值的真假條件渲染元素,表達(dá)式中的值為false是,該元素會(huì)從dom中移除
官方解釋:在切換時(shí)元素及它的數(shù)據(jù)綁定 / 組件被銷毀并重建。如果元素是 <template> 鄙煤,將提出它的內(nèi)容作為條件塊晾匠。當(dāng)條件變化時(shí)該指令觸發(fā)過渡效果
v-show:當(dāng)表達(dá)式的值為false,只是表現(xiàn)形式的隱藏(display:none),根據(jù)表達(dá)式之真假值梯刚,切換元素的CSS中的display屬性,如果頻繁切換時(shí)就用v-show,如果是一次的話,那么就用v-if,在性能上,v-show要優(yōu)于v-if,因?yàn)椴皇穷l繁的改變dom結(jié)構(gòu),而從代碼冗余結(jié)構(gòu)上:v-if要比v-show要少
共同點(diǎn):都是控制元素的顯示和隱藏,若是需要頻繁切換時(shí),就用v-show,若是使用頻率較低,那么就用v-if
數(shù)據(jù):基本數(shù)據(jù)類型(Number,string,null,undefined,boolean,symbol)和非基本數(shù)據(jù)類型(函數(shù),對(duì)象)凉馆,上面的data里面定義的屬性就是數(shù)據(jù)了
其實(shí)對(duì)于數(shù)據(jù)理解,無論是網(wǎng)頁或者app上我們能看到的東西都可視為數(shù)據(jù),宏觀上:內(nèi)容html結(jié)構(gòu)作為數(shù)據(jù)的載體容器,層疊樣式(css)修飾元素標(biāo)簽外觀展示,行為動(dòng)作(javascript)相應(yīng)的業(yè)務(wù)邏輯,請(qǐng)求,事件操作等,對(duì)應(yīng)的就是資源(包括圖片,文字),其實(shí)能夠承載信息的載體都可視為數(shù)據(jù)(上面代碼中的狀態(tài),數(shù)值等)
什么是組件亡资?
[圖片上傳失敗...(image-c452a-1533190200954)]
通俗一點(diǎn):頁面上的某一個(gè)部分,是對(duì)應(yīng)用模塊的一種抽象,它往往可以具有獨(dú)立的邏輯和功能頁面,同時(shí)又能根據(jù)規(guī)定的接口規(guī)則進(jìn)行相互融合,編寫成一個(gè)完整的應(yīng)用,它好比是電腦中的每一個(gè)元器件(如鍵盤,硬盤,鼠標(biāo)澜共,顯示器等),而在網(wǎng)頁中,對(duì)應(yīng)的是導(dǎo)航欄,側(cè)邊欄,底部,列表,彈窗,下拉菜菜單,時(shí)間選擇器等
形式上:通過自定義標(biāo)簽元素,它是對(duì)原生一些html的拓展,封裝可重用性代碼,也可以是原生 HTML 元素的形式,以is特性進(jìn)行擴(kuò)展(在文檔中DOM模板解析有說明,主要解決的是在標(biāo)準(zhǔn)html標(biāo)簽內(nèi)嵌套自定義標(biāo)簽出現(xiàn)莫名的bug問題)
頁面只不過是這些組件的容器,也可以理解為一個(gè)大的應(yīng)用(網(wǎng)站,app等)是由很多部分組成,每個(gè)部分就可以看成一個(gè)小組件,通過組件的自由組合可形成的功能完整的界面,當(dāng)不需要某個(gè)組件或者要替換某個(gè)組件時(shí),可以隨時(shí)進(jìn)行替換和刪除,而不影響整個(gè)應(yīng)用的運(yùn)行,這就是組件式開發(fā)
前端組件化的核心思路就是將一個(gè)巨大復(fù)雜的東西拆分成若干個(gè)粒度合理的小東西
[圖片上傳失敗...(image-c4564e-1533190200954)]
使用組件化的好處
提高的開發(fā)效率(A,B沟于,C,D前端小伙伴可同時(shí)進(jìn)行,根據(jù)功能模塊獨(dú)立開發(fā))
方便重復(fù)使用,簡(jiǎn)化調(diào)試步驟,方便單元測(cè)試
提升整個(gè)項(xiàng)目的可維護(hù)性,便于團(tuán)隊(duì)成員的協(xié)同開發(fā),團(tuán)隊(duì)中的前端leader給成員劃分功能模塊,每個(gè)模塊,由誰負(fù)責(zé),最后拼接起來成一個(gè)完整的應(yīng)用(不懂技術(shù)的產(chǎn)品都是紙上談兵)
組件化的特性
高內(nèi)聚(也就是說組件的功能必須是完整的,例如要實(shí)現(xiàn)下拉菜單功能,那在下拉菜單這個(gè)組件中,就把下拉菜單所需要的所有功能全局實(shí)現(xiàn),那些第三方UI(例如iview,elemUI)就是如此)
低耦合(通俗點(diǎn)說,功能邏輯代碼要獨(dú)立,不能和項(xiàng)目中的其他代碼發(fā)生沖突,在實(shí)際項(xiàng)目中,避免不了要涉及團(tuán)隊(duì)協(xié)作,傳統(tǒng)方式是按照業(yè)務(wù)去編寫代碼,業(yè)務(wù)邏輯和數(shù)據(jù)耦合在一起,這就很容易發(fā)生相互沖突,所以運(yùn)用組件化方式就可大大避免這種沖突的存在)
每一個(gè)組件都應(yīng)該有自己清晰的邏輯,職責(zé),完整的功能,較低的耦合便于單元測(cè)試和重復(fù)利用
頁面上每個(gè)獨(dú)立的可視/可交互區(qū)域都可以視為一個(gè)組件
每個(gè)組件對(duì)應(yīng)的是一個(gè)工程目錄,組件所需要的各種資源在這個(gè)目錄下就近維護(hù)(也就是模板(內(nèi)容),數(shù)據(jù),樣式)
當(dāng)內(nèi)容結(jié)構(gòu)樣式相似時(shí),頁面中重復(fù)出現(xiàn)多次,那么就可以把它拆分出一個(gè)組件(什么時(shí)候該拆分成一個(gè)組件,將一個(gè)大組件分成若干個(gè)小組件)
組件的組成
一個(gè)完整的組件,應(yīng)該包括模板(內(nèi)容結(jié)構(gòu)html),層疊樣式(css),行為動(dòng)作(邏輯,javascript代碼)咳胃,數(shù)據(jù),在你用腳手架搭建一個(gè)項(xiàng)目的時(shí)候,一個(gè)單文件組件.vue文件就是一個(gè)組件,它就包含了模板,數(shù)據(jù),樣式
組件可以層層嵌套,理論上是可以無限制的拆分,但是也不可盲目拆分,應(yīng)當(dāng)遵循上面提到的組件化原則,什么時(shí)候該拆分一個(gè)組件,得根據(jù)實(shí)際情況由前端代碼的你來決定的,組件層次嵌套多了,意味著結(jié)構(gòu)復(fù)雜,那么對(duì)應(yīng)的數(shù)據(jù)傳遞也會(huì)變得復(fù)雜
[圖片上傳失敗...(image-1e4a0a-1533190200954)]
怎么理解父組件與子組件,兄弟組件,非父子組件
剛開始看vue官方文檔時(shí)候,對(duì)于理解父子組件真的很懵逼,迷迷糊糊的,父組件與子組件其實(shí)是一個(gè)相對(duì)的概念,你可以把它理解包含與被包含的關(guān)系,被包含的自定義標(biāo)簽元素稱為子組件,根實(shí)例下的模板的內(nèi)容是父組件,可以對(duì)比以前寫html的時(shí)候,元素嵌套那種層級(jí)關(guān)系。
而通過全局注冊(cè)(Vue.component(tagName, options))或者局部注冊(cè),自定義標(biāo)簽元素的是子組件,在根實(shí)例的作用域范圍內(nèi),父實(shí)例的模塊中以自定義元素 調(diào)用子組件進(jìn)行使用,要注意的是確保在初始化根實(shí)例之前,注冊(cè)了子組件
兄弟組件:同級(jí)關(guān)系的自定義標(biāo)簽元素在父模板中進(jìn)行使用稱為為兄弟組件
非父子組件:非同級(jí)關(guān)系自定義標(biāo)簽元素(可以通過總線的方式,本篇不涉及此內(nèi)容,以后在總結(jié))
[圖片上傳失敗...(image-3c7717-1533190200954)]
沒有代碼的實(shí)際演示,是理解不了上圖他們之間怎么通信傳值的,組件之間的通信傳值是一塊硬骨頭,邏輯比較繞,遠(yuǎn)比函數(shù)傳參復(fù)雜得多,為來更好的理解父子組件間傳值,下面以一個(gè)todolist的經(jīng)典例子
同樣,我會(huì)一步一步從原生js,jQuery在到vuejs,并且實(shí)現(xiàn)父子元素的通信,實(shí)現(xiàn)效果如下圖所示:
輸入框內(nèi)輸入值,點(diǎn)擊添加按鈕,將表單中的值添加到頁面中,同時(shí),又可以刪除列表項(xiàng)內(nèi)容,注意是刪除列表項(xiàng)而不是隱藏
原生js實(shí)現(xiàn)todolist
css代碼:
body{
margin:0;
text-align:center;
padding-top:30px;
width:-moz-fit-content;
width:-webkit-fit-content;// 子元素有浮動(dòng)時(shí),仍然想要子元素水平居中旷太,配合margin:auto;
width:fit-content;
margin:0 auto;
}
input{
width:400px;
height:30px;
outline:none;
float:left;
}
#btn{
width:50px;
height:35px;
display:inline-block;
float:left;
background:red;
color:#fff;
outline:none;
border:none;
cursor:pointer;
}
.clearfix:after{
content:"";
height:0;
display:block;
clear:both;
overflow:hidden;
}
ul li{
text-align:left;
cursor:pointer;
}
html代碼
<div class="clearfix">
<input type="text" id="input" value="" placeholder="請(qǐng)輸入內(nèi)容進(jìn)行添加" />
<button id="btn">添加</button>
</div>
<ul id="list"></ul>
avascript代碼
// 獲取元素
var oInput = document.querySelector("#input"),
oBtn = document.querySelector("#btn"),
oList = document.querySelector("#list");
// 元素上添加事件
oBtn.onclick = function(){
var oInputVal = oInput.value;
var oLis =document.getElementsByTagName("li");
if(oInputVal == ""){
alert("輸入內(nèi)容為空,請(qǐng)輸入內(nèi)容...");
} else {
//console.log(oInputVal);
oList.innerHTML += "<li>"+oInputVal+"</li>";
oInput.value = "";
for(let i = 0;i<oLis.length;i++){
// 通過addEventListener事件綁定監(jiān)聽
oLis[i].addEventListener('click',function(){
this.parentNode.removeChild(this);
})
}
}
}
使用jQuery方式實(shí)現(xiàn)
css,html代碼省略,與上面一致
$(function(){
var $input = $("#input"),
$btn = $("#btn"),
$ul = $("#list");
// 添加事件
$btn.click(function(){
var oInputValue = $input.val();
if(oInputValue == ""){
alert("輸入內(nèi)容為空,請(qǐng)輸入內(nèi)容...");
}else{
$ul.append("<li>"+oInputValue+"</li>");
$("#input").val('');
}
})
/*$("#list").delegate('li','click',function(){
console.log(this);
$(this).remove();
})
*/
// 通過on綁定監(jiān)聽事件
$("#list").on('click','li',function(){
console.log(this);
$(this).remove();//從DOM中刪除所有匹配的元素
})
})
/*
bind() 方法向被選元素添加一個(gè)或多個(gè)事件處理程序展懈,以及當(dāng)事件發(fā)生時(shí)運(yùn)行的函數(shù)销睁。
live() 方法為被選元素附加一個(gè)或多個(gè)事件處理程序,并規(guī)定當(dāng)這些事件發(fā)生時(shí)運(yùn)行的函數(shù)存崖。
通過 live() 方法附加的事件處理程序適用于匹配選擇器的當(dāng)前及未來的元素(比如由腳本創(chuàng)建的新元素,這個(gè)方法在最新的JQuery版本中移除了的,不推薦使用
delegate() 方法為指定的元素(屬于被選元素的子元素)添加一個(gè)或多個(gè)事件處理程序冻记,并規(guī)定當(dāng)這些事件發(fā)生時(shí)運(yùn)行的函數(shù)。
使用 delegate() 方法的事件處理程序適用于當(dāng)前或未來的元素(比如由腳本創(chuàng)建的新元素来惧,要注意與on寫法上的區(qū)別
on() 方法在被選元素及子元素上添加一個(gè)或多個(gè)事件處理程序,使用on方法時(shí),注意使用on()方法時(shí)冗栗,添加的事件處理程序適用于當(dāng)前及未來的元素(比如由腳本創(chuàng)建的新元素)如果移除事件處理程序,則使用off()方法,要綁定在父級(jí)元素上供搀,而且在低jQuery版本中不支持這個(gè)方法
remove方法不會(huì)把匹配的元素從jQuery對(duì)象中刪除隅居,因而可以在將來再使用這些匹配的元素。但除了這個(gè)元素本身得以保留之外葛虐,其他的比如綁定的事件胎源,附加的數(shù)據(jù)等都會(huì)被移除
empty:刪除匹配的元素集合中所有的子節(jié)點(diǎn),清空的是內(nèi)容
*/
對(duì)于上面的jQuery使用on對(duì)元素進(jìn)行事件監(jiān)聽綁定的時(shí)候,有一個(gè)坑就是,要格外注意的是:要綁定在想要操作元素的父級(jí)元素身上,否則會(huì)不起作用,其實(shí)它是利用了事件委托冒泡的機(jī)制
而在低jQuery版本中,沒有on這個(gè)方法,若使用它,則會(huì)報(bào)錯(cuò),而對(duì)于on方法取而代之的是delegate()這個(gè)方法,這里要注意與on方法寫法的區(qū)別,總體來說,on方法已經(jīng)替代了其他方法了的
使用vue實(shí)現(xiàn)
怎么定義組件,注冊(cè)組件屿脐?
父組件怎么向子組件傳值涕蚤?
子組件怎么向父組件通信?
[圖片上傳失敗...(image-3a32d8-1533190200954)]
你將在以下看到,我先不使用組件方式實(shí)現(xiàn)todolist,然后轉(zhuǎn)化為組件的方式進(jìn)行編寫,添加內(nèi)容實(shí)現(xiàn)父組件傳值給子組件,刪除列表項(xiàng),子組件怎么觸發(fā)父組件進(jìn)行通信,感受數(shù)據(jù)驅(qū)動(dòng)影響視圖,這里使用vue的方式暫且先通過script標(biāo)簽?zāi)_本注入的方式進(jìn)行使用,與引用jQuery庫方式?jīng)]有什么區(qū)別
未組件化實(shí)現(xiàn)todolist
css代碼省略與上面的一致
html代碼(模板):內(nèi)容結(jié)構(gòu)上最外層包裹了一個(gè)根元素app
<div id="app">
<div class="clearfix">
<input type="text" name="" placeholder="請(qǐng)輸入內(nèi)容進(jìn)行添加" v-model="inputVal">
<button type="button" id="btn" @click="addBtn">{{addCon}}</button>
</div>
<ul id="list">
<li v-for="(item,index) in list" @click="deleteList(index)">{{item}}</li>
</ul>
</div>
javascript代碼
var app = new Vue({
el:"#app",
data:{
addCon:"添加",
inputVal:"",
list:[]
},
methods:{
// 點(diǎn)擊添加按鈕添加
addBtn:function(){
if(this.inputVal == ""){
alert("請(qǐng)輸入框內(nèi)輸入內(nèi)容..");
}else{
this.list.push(this.inputVal);
this.inputVal = "";
}
},
// 刪除列表子項(xiàng)
deleteList:function(index){
this.list.splice(index,1);
}
}
})
如下圖效果所示
從上面的示例代碼中涉及到幾個(gè)知識(shí)點(diǎn):v-model指令,v-for循環(huán)列表的诵,通過先前學(xué)過的內(nèi)聯(lián)樣式中綁定事件方法@(v-on)万栅,在根實(shí)例app中的metods方法中操作數(shù)據(jù),實(shí)現(xiàn)我們想要的功能,其實(shí)vue只是幫我們做了vmodel層的事情,具體的業(yè)務(wù)邏輯,仍然是離不開原生js的,例如操作數(shù)組添加,刪除,截取,拼接等一些方法的
v-model:在表單控件或者組件上創(chuàng)建雙向數(shù)據(jù)綁定
v-for:循環(huán)展示數(shù)據(jù),使用該指令時(shí),必須使用特定的語法,alias in expression:alias表示的是expression中別名,而expression表示的當(dāng)前遍歷元素的對(duì)象,例如:v-for="item in Array"而在模板中使用{{item}}
注意在使用v-for的時(shí)候,要加上一個(gè):key=""它會(huì)提升頁面渲染性能西疤,這個(gè)key值是唯一的,v-for默認(rèn)行為試著不改變整體烦粒,而是替換元素。迫使其重新排序的元素瘪阁,你需要提供一個(gè)key的特殊屬性
其實(shí)使用index做列表的key值也不是一個(gè)最好的選擇,如果不需要給列表進(jìn)行排序進(jìn)行額外的操作撒遣,如果頻繁的需要跟列表進(jìn)行變更的時(shí)候,使用index是存在問題的,一般都是后臺(tái)返回的字段中,寫入一個(gè)唯一的標(biāo)識(shí)符,例如:id,關(guān)于key詳細(xì)內(nèi)容,可以移步官方文檔閱讀
可以循環(huán)渲染數(shù)組,對(duì)象管跺,數(shù)字,字符串义黎,上面的示例代碼中in或者of 前面的item代表的是數(shù)組每一項(xiàng)值,而index代表的是索引,in 后面的是數(shù)據(jù)中的數(shù)組名
從上面的效果中看出,在我們每次進(jìn)行表單輸入值,點(diǎn)擊添加按鈕添加事件操作時(shí),頁面中都會(huì)新增出現(xiàn)一條列表項(xiàng),而且每個(gè)列表項(xiàng)在結(jié)構(gòu)樣式上都是相似的,那么我們就可以把這個(gè)列表項(xiàng)封裝成一個(gè)組件的,封裝好的組件在頁面上可以隨處使用
定義組件豁跑,使用組件
全局定義組件:通過Vue提供的內(nèi)置方法,Vue.compontent('組件名稱',配置選項(xiàng)對(duì)象)廉涕, Vue.component('my-component-name', { 選項(xiàng)/* ... */ }),其中第一個(gè)參數(shù)表示的是組件的名字,第二個(gè)參數(shù)是配置選項(xiàng)對(duì)象(可包括數(shù)據(jù)data,template,props,methods等實(shí)例選項(xiàng))
這里要注意的是,當(dāng)直接在DOM中使用一個(gè)組件(而不是在字符串模板template或者單文件組件的時(shí)候),官方推薦w3c標(biāo)準(zhǔn)自定義組件名(字母全小寫且必須包含一個(gè)連字符,烤串式寫法) 例如下面全局注冊(cè)component-a,component-b,component-c組件
Vue.component('component-a', { /* ... */ })
Vue.component('component-b', { /* ... */ })
Vue.component('component-c', { /* ... */ })
而在DOM中引用組件時(shí)
<div id="app">
<component-a></component-a>
<component-b></component-b>
<component-c></component-c>
</div>
當(dāng)然命名組件時(shí)也可以是駝峰式艇拍,它們?cè)谧?cè)之后可以用在任何新創(chuàng)建的Vue根實(shí)例 (new Vue) 的模板中
局部定義: 在根實(shí)例外自定義組件名稱,并且在根實(shí)例中通過components方式進(jìn)行注冊(cè),全局注冊(cè)組件官方是不推薦使用的,在后續(xù)的利用vue-cli搭建的單文件組件里,都是使用局部注冊(cè)組件的方式
通過一個(gè)普通javascript對(duì)象來定義組件
var ComponentA = { 配置選項(xiàng)對(duì)象/* ... */ }
var ComponentB = { 配置選項(xiàng)對(duì)象/* ... */ }
var ComponentC = { 配置選項(xiàng)對(duì)象/* ... */ }
然后在components選項(xiàng)中定義你想要使用的組件
new Vue({
el: '#app'
components: {
'component-a': ComponentA,
'component-b': ComponentB
}
})
對(duì)于 components 對(duì)象中的每個(gè)屬性來說狐蜕,其屬性名就是自定義元素的名字,其屬性值就是這個(gè)組件的選項(xiàng)對(duì)象
在以后的vue-cli模塊系統(tǒng)中,通過 Babel 和 webpack 使用 ES2015 模塊卸夕,需要這么寫
下面的import和export default都是Es6中模塊系統(tǒng),如果不清楚的話,可以閱讀Es6中的模塊化Module,導(dǎo)入(import)導(dǎo)出(export)
Es6中模塊(Module)的默認(rèn)導(dǎo)入導(dǎo)出及加載順序這兩篇文章
import ComponentA from './ComponentA.vue'
export default {
components: {
ComponentA
}
}
上面的是Es6的寫法,在對(duì)象中放一個(gè)類似 ComponentA 的變量名其實(shí)是 ComponentA: ComponentA 的縮寫层释,即這個(gè)變量名同時(shí)是:
用在模板中的自定義元素的名稱
包含了這個(gè)組件選項(xiàng)的變量名
注意:定義組件名大小寫問題
定義組件名的方式有兩種:
使用 kebab-case(字母全小寫,連字符)
Vue.component('my-component-name', { /* ... */ })
當(dāng)使用kebab-case(短橫線分隔命名)定義一個(gè)組件時(shí),你也必須在引用這個(gè)自定義元素時(shí)使用 kebab-case,例如 <my-component-name>,也就是要一一對(duì)應(yīng)關(guān)系快集,否則就會(huì)報(bào)錯(cuò)
did you register the component correctly? For recursive components, make sure to provide the "name" option.
- 使用 PascalCase(駝峰式),遇到多個(gè)單詞時(shí),首字母大寫
Vue.component('MyComponentName', { /* ... */ })
當(dāng)使用PascalCase(駝峰式命名)定義一個(gè)組件時(shí),你在父模板中引用這個(gè)自定義元素時(shí)兩種命名法(kebab-case與PascalCase)都可以使用,也就是在DOM中使用<my-component-name>和<MyComponentName>都是可以接受的,但是要注意的是,直接在DOM(即非字符串的模板)中時(shí)只有kebab-case是有效的
定義組件時(shí),避免混淆,個(gè)人推薦使用PascalCase(駝峰式)方式,而在模板中引用該自定義元素組件時(shí),使用kebab-case(連字符方式),但是別人在模板中引用組件時(shí),若寫了PascalCase(駝峰式)格式,至少得明白怎么回事
兩者比較:
共同點(diǎn):都可以定義注冊(cè)組件贡羔,在模板中使用
不同點(diǎn):若在vue-cli,webpack構(gòu)建的項(xiàng)目里,若使用全局注冊(cè)所有的組件,這意味著如果你已經(jīng)不使用一個(gè)組件了,它仍然會(huì)被包含在你最終的構(gòu)建項(xiàng)目中廉白。這會(huì)造成用戶下載的JavaScript 的無謂的增加,也就是全局注冊(cè)的組件不會(huì)被銷毀.
下面通過全局注冊(cè)組件和局部注冊(cè)組件的方式父組件傳值給子組件的方式實(shí)現(xiàn)添加操作
html代碼
<div id="app">
<div class="clearfix">
<input type="text" name="" placeholder="請(qǐng)輸入內(nèi)容進(jìn)行添加" v-model="inputVal">
<button type="button" id="btn" @click="addBtn">{{addCon}}</button>
</div>
<ul id="list">
<!-- <li v-for="(item,index) in list" @click="deleteList(index)">{{item}}</li> -->
<todo-list v-for="(item,index) in list" v-bind:content="item" :key="index"></todo-list>
</ul>
</div>
JavaScript代碼
/* 注冊(cè)全局組件通過Vue.component('自定義組件名稱',配置選項(xiàng)對(duì)象) */
Vue.component('TodoList',{ // 第一個(gè)參數(shù)為組件名字
props:["content"], // 用props接收父組件傳過來的content是在父組件里用v-bind自定義的一個(gè)變量用于接收父組件攜帶的實(shí)參值
template:'<li>{{content}}</li>' // template模板,要渲染的具體內(nèi)容
})
var app = new Vue({
el:"#app",
data:{
addCon:"添加",
inputVal:"",
list:[]
},
methods:{
// 點(diǎn)擊添加按鈕添加
addBtn:function(){
if(this.inputVal == ""){
alert("請(qǐng)輸入框內(nèi)輸入內(nèi)容..");
}else{
console.log(this.list,this.list.length); // 沒有進(jìn)行push之前
this.list.push(this.inputVal);
this.inputVal = "";
console.log(this.list,this.list.length); // 進(jìn)行了push之后
}
}
}
注意上面全局注冊(cè)組件是在根實(shí)例之外操作的,與局部注冊(cè)代碼進(jìn)行比較
下面是局部注冊(cè)的代碼
/* 注冊(cè)局部組件,通過一個(gè)普通javascript對(duì)象來定義組件 */
var TodoList = {
props:["content"],
template:'<li>{{content}}</li>'
}
var app = new Vue({
el:"#app",
components:{ // 在根組件中進(jìn)行注冊(cè)
TodoList // 等價(jià)于TodoList:TodoList
},
data:{
addCon:"添加",
inputVal:"",
list:[]
},
methods:{
// 點(diǎn)擊添加按鈕添加
addBtn:function(){
if(this.inputVal == ""){
alert("請(qǐng)輸入框內(nèi)輸入內(nèi)容..");
}else{
console.log(this.list,this.list.length); // 沒有進(jìn)行push之前
this.list.push(this.inputVal);
this.inputVal = "";
console.log(this.list,this.list.length); // 進(jìn)行了push之后
}
}
}
})
下面來分析下上面代碼是怎么進(jìn)行父組件傳值到子組件中的,將數(shù)據(jù)渲染到頁面中去的
首先要理解父組件和子組件,他們是一個(gè)相對(duì)的概念
在上述示例代碼中,根組件(app)模板內(nèi)的代碼都屬于父組件,而通過Vue.compont()或者局部注冊(cè)的組件都是子組件
所謂的父組件向子組件傳值,這個(gè)值傳遞其實(shí)就是數(shù)據(jù),特定的是實(shí)參數(shù)
在上述代碼中,input框被包裹在父組件中,input框中輸入的值是數(shù)據(jù),通過v-model進(jìn)行雙向數(shù)據(jù)綁定,通過inputVal這個(gè)變量保存,經(jīng)過按鈕的點(diǎn)擊操作后,它是保存在父組件中的list數(shù)組中,是直接掛載根實(shí)例下的,通過按鈕的添加操作,將每次新添加的值渲染到指定頁面位置當(dāng)中去
父組件中的數(shù)據(jù)是無法直接的在子組件中使用的,所以在父組件引用的子組件中,通過v-bind指令綁定自定義屬性值的方式,父組件中的數(shù)據(jù),可以通過v-for循環(huán)列表拿到數(shù)據(jù)
在上面的時(shí)例代碼中,通過自定義一個(gè)content變量屬性用來接收父組件中的數(shù)據(jù),v-bind:content="item",這個(gè)item是父組件中l(wèi)ist數(shù)組中的列表項(xiàng),它是把list中的每一項(xiàng)值賦值給item,然后通過這個(gè)item,通過v-bind的方式傳給這個(gè)todo-list組件,通過content這個(gè)變量來傳的.
光這樣是不夠的,還需要在子組件里去接收父組件自定義的這個(gè)content變量,在子組件中是通過props這個(gè)屬性來接收父組件的數(shù)據(jù),后面的值可以是數(shù)組,也可以是對(duì)象,對(duì)象允許配置高級(jí)選項(xiàng),如類型檢測(cè)乖寒、自定義校驗(yàn)和設(shè)置默認(rèn)值
其實(shí)這個(gè)content變量是一個(gè)prop值, prop是你可以在組件上注冊(cè)的一些自定義特性猴蹂。當(dāng)一個(gè)值傳遞給一個(gè) prop 特性的時(shí)候,它就變成了那個(gè)組件實(shí)例的一個(gè)屬性,本質(zhì)上這個(gè)prop的類型是由父組件傳過來的值決定的,當(dāng)然在寫法上這個(gè)prop要注意大小寫問題,具體可查看文檔的
在子組件的模板中使用props接收的值,這樣的話,就達(dá)到父組件傳給子組件了,為了更好的理解,我畫一張圖把這個(gè)過程屢一下的
[圖片上傳失敗...(image-433b12-1533190200954)]
上面示例代碼中,實(shí)現(xiàn)父組件向子組件傳值添加操作,那么現(xiàn)在我想點(diǎn)擊每個(gè)列表項(xiàng)的時(shí)候,能進(jìn)行逐條刪除操作,該怎么實(shí)現(xiàn)呢,這就涉及到子組件向父組件傳值的問題了
子組件向父組件傳值通信
通過以上示例看出,當(dāng)父組件根實(shí)例app里面data的list數(shù)據(jù)發(fā)生變化時(shí),子組件TodoList也會(huì)發(fā)生變化,也就是說父組件里面的數(shù)據(jù)會(huì)影響子組件的顯示,那么問題來了,現(xiàn)在我想要點(diǎn)擊列表刪除該項(xiàng)
既然子組件的渲染結(jié)果是由父組件決定的,想要?jiǎng)h除子組件,就必須要更改父組件的數(shù)據(jù),所以在刪除子組件的時(shí)候,我們需要點(diǎn)擊該子組件,子組件需要把對(duì)應(yīng)的內(nèi)容傳給父組件,讓父組件去改變數(shù)據(jù)楣嘁,讓父組件的數(shù)據(jù)改變了的磅轻,隨之子組件便會(huì)跟著消失或者增加
子組件向父組件傳值是通過vue提供的emit("eventName自定義事件名稱",攜帶的附加參數(shù)),觸發(fā)當(dāng)前實(shí)例上的事件。附加參數(shù)都會(huì)傳給監(jiān)聽器回調(diào)
以下是具體代碼
html代碼:
<div id="app">
<div class="clearfix">
<input type="text" name="" placeholder="請(qǐng)輸入內(nèi)容進(jìn)行添加" v-model="inputVal">
<button type="button" id="btn" @click="addBtn">{{addCon}}</button>
</div>
<ul id="list">
<!-- <li v-for="(item,index) in list" @click="deleteList(index)">{{item}}</li> -->
<todo-list v-for="(item,index) in list" v-bind:content="item" v-bind:index="index" v-on:deleteitem="deleteItemFun" :key="index"></todo-list>
</ul>
</div>
javascript代碼
/* 注冊(cè)局部組件,通過一個(gè)普通javascript對(duì)象來定義組件 */
var TodoList = {
props:["content","index"],
template:'<li @click="deleteList">{{content}}</li>',
methods: {
deleteList: function(index){
//alert(1);
this.$emit('deleteitem',this.index);// 第一個(gè)參數(shù)是觸發(fā)父組件自定義delete事件,第二個(gè)是子組件參數(shù),向父組件傳遞
}
}
}
var app = new Vue({
el:"#app",
components:{ // 在根組件中進(jìn)行注冊(cè)
TodoList // 等價(jià)于TodoList:TodoList
},
data:{
addCon:"添加",
inputVal:"",
list:[]
},
methods:{
// 點(diǎn)擊添加按鈕添加
addBtn:function(){
if(this.inputVal == ""){
alert("請(qǐng)輸入框內(nèi)輸入內(nèi)容..");
}else{
console.log(this.list,this.list.length); // 沒有進(jìn)行push之前
this.list.push(this.inputVal);
this.inputVal = "";
console.log(this.list,this.list.length); // 進(jìn)行了push之后
}
},
// 刪除列表項(xiàng)
deleteItemFun: function(index){
//alert(1);
this.list.splice(index,1);
}
}
})
上面的代碼中,子組件向父組件傳值,通過emit向外觸發(fā)一個(gè)自定義事件
在父組件創(chuàng)建子組件的同時(shí)可以去監(jiān)聽父組件@deletelist="deleteItemFun",在父組件的這個(gè)模板當(dāng)中,創(chuàng)建子組件的同時(shí)也監(jiān)聽了子組件deletelist這個(gè)事件逐虚,一旦刪除事件deleteitemFun被觸發(fā)的時(shí)候就會(huì)執(zhí)行父組件實(shí)例下掛載的deleteItemFun這個(gè)方法
當(dāng)點(diǎn)擊列表項(xiàng)的時(shí)候,父組件監(jiān)聽到子組件deleteitem時(shí)候就會(huì)到父組件的methods中執(zhí)行deleteitemFun這個(gè)方法聋溜,執(zhí)行相應(yīng)的邏輯,這里的自定義事件是deleteitem
注意:如果你直接將this.list = []的話,那么點(diǎn)擊一項(xiàng)時(shí),整個(gè)都會(huì)刪除,明顯不符合需求,所以同樣需要有個(gè)索引值,那么同樣,父組件傳遞給子組件一個(gè)索引值就可以了的,通過props進(jìn)行傳遞,而子組件觸發(fā)父組件時(shí),在$emit第二個(gè)參數(shù),通過攜帶索引值參數(shù),這個(gè)參數(shù)也會(huì)隨之的被傳入到父組件中去
注意點(diǎn):
子組件內(nèi)定義的事件方法或者數(shù)據(jù)是無法在父組件中使用的,反過來也是如此,也就是說,組件與組件之間,擁有獨(dú)立的數(shù)據(jù),data,模板template,還有方法methods等其他實(shí)例選項(xiàng)(例如:computed叭爱,生命周期等)
同樣勤婚,畫一張圖屢一下思路的
[圖片上傳失敗...(image-e3fa47-1533190200955)]
小結(jié):
到這里的話,父組件和子組件之間的簡(jiǎn)單傳值就已經(jīng)結(jié)束了,在寫vue代碼的時(shí)候,不要直接去操作dom,而是通過數(shù)據(jù)的改變讓頁面自動(dòng)變化,父組件向子組件傳值,在父組件中通過v-on綁定自定義屬性方式存儲(chǔ)父組件中的數(shù)據(jù),然后通過props在子組件中接收,這樣就可以拿到父組件中的數(shù)據(jù)
而反過來,在子組件想要向父組件通信傳值,通過emitf方法通知父組件,從而改變父組件掛載的數(shù)據(jù),間接的操作了子組件
其實(shí),別看官網(wǎng)或者網(wǎng)上的一些文章簡(jiǎn)單的提到這兩種方式的,在實(shí)際中,可以看出是得做了不少工作的,那張父子組件傳值圖雖然簡(jiǎn)單粗暴,但是內(nèi)部涉及的知識(shí)卻是不少的
總結(jié):
文章到這里就結(jié)束了,如果您能堅(jiān)持讀完,相信您對(duì)父子組件傳值有所感受,整篇文章信息量比較大,從認(rèn)識(shí)vue是什么,vue中的核心點(diǎn),以及vue的使用,原生js實(shí)現(xiàn)一dom操作,分別從原生js缨称,jQuery,在到vue,他們實(shí)現(xiàn)的方式有什么不同,什么是組件,使用組件化的好處,組件化的特性,組件的組成,怎么理解父組件與子組件,兄弟組件,非父子組件,最后實(shí)現(xiàn)todolist,分別用原生js凝果,jQuery,Vue逐一實(shí)現(xiàn)的,使用原生js,JQuery,主要是感受比較他們與vuejs的差異
例子雖然比較簡(jiǎn)單,但是它囊括了很多知識(shí)...
vuejs雖然強(qiáng)大,但是底層核心邏輯依然是是不變的,有些事情仍然是需要我們自己做的,只不過是原生js,jQuery是面向DOM編程,而vuejs可以理解為面向數(shù)據(jù)編程,它關(guān)注的是數(shù)據(jù)層model
其中重點(diǎn)是在于理解父子組件間的簡(jiǎn)單通信,關(guān)于組件的內(nèi)容,比較多,也比較雜,理解組件之間的通信非常重要,反正我覺得這是一道坎睦尽,有些內(nèi)容比較繞..遇到具體哪個(gè)知識(shí)不熟悉的,一定要左手代碼,右手查文檔...文章若有不足和誤導(dǎo)之處,歡迎路過的老師多提意見和指正