vue中的組件以及父子組件間通信傳值

文章結(jié)構(gòu).png

前言

您將在本文當(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做比較

image

實(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)而不是隱藏

image

原生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);
            }
          }
})

如下圖效果所示


image

從上面的示例代碼中涉及到幾個(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í)是:

  1. 用在模板中的自定義元素的名稱

  2. 包含了這個(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.
  1. 使用 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內(nèi)置方法實(shí)現(xiàn)的,vm.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ā)事件的方式,當(dāng)點(diǎn)擊子組件的時(shí)候,在該子組件綁定點(diǎn)擊click事件方法,在該子組件methods方法內(nèi),通過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ù)

而反過來,在子組件想要向父組件通信傳值,通過emit自定義事件向外觸發(fā)的方式,并且可以攜帶參數(shù),然后在父組件的引用子組件中進(jìn)行自定義事件的綁定涤伐,改變子組件,通過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)之處,歡迎路過的老師多提意見和指正

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末器净,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子当凡,更是在濱河造成了極大的恐慌山害,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件沿量,死亡現(xiàn)場(chǎng)離奇詭異浪慌,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)朴则,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門权纤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人乌妒,你說我怎么就攤上這事汹想。” “怎么了撤蚊?”我有些...
    開封第一講書人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵古掏,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我侦啸,道長(zhǎng)槽唾,這世上最難降的妖魔是什么丧枪? 我笑而不...
    開封第一講書人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮夏漱,結(jié)果婚禮上豪诲,老公的妹妹穿的比我還像新娘。我一直安慰自己挂绰,他們只是感情好牍疏,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著迁客,像睡著了一般檀何。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上践付,一...
    開封第一講書人閱讀 48,970評(píng)論 1 284
  • 那天秦士,我揣著相機(jī)與錄音,去河邊找鬼永高。 笑死隧土,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的命爬。 我是一名探鬼主播曹傀,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼饲宛!你這毒婦竟也來了皆愉?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤艇抠,失蹤者是張志新(化名)和其女友劉穎幕庐,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體家淤,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡异剥,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了媒鼓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片届吁。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖绿鸣,靈堂內(nèi)的尸體忽然破棺而出疚沐,到底是詐尸還是另有隱情,我是刑警寧澤潮模,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布亮蛔,位于F島的核電站,受9級(jí)特大地震影響擎厢,放射性物質(zhì)發(fā)生泄漏究流。R本人自食惡果不足惜辣吃,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望芬探。 院中可真熱鬧神得,春花似錦、人聲如沸偷仿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽酝静。三九已至节榜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間别智,已是汗流浹背宗苍。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留薄榛,地道東北人讳窟。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像敞恋,于是被迫代替她去往敵國(guó)和親挪钓。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 這篇筆記主要包含 Vue 2 不同于 Vue 1 或者特有的內(nèi)容耳舅,還有我對(duì)于 Vue 1.0 印象不深的內(nèi)容。關(guān)于...
    云之外閱讀 5,045評(píng)論 0 29
  • vue概述 在官方文檔中倚评,有一句話對(duì)Vue的定位說的很明確:Vue.js 的核心是一個(gè)允許采用簡(jiǎn)潔的模板語法來聲明...
    li4065閱讀 7,187評(píng)論 0 25
  • 1.安裝 可以簡(jiǎn)單地在頁面引入Vue.js作為獨(dú)立版本浦徊,Vue即被注冊(cè)為全局變量,可以在頁面使用了天梧。 如果希望搭建...
    Awey閱讀 10,995評(píng)論 4 129
  • 隨著慧穎的駕到盔性,新進(jìn)的大長(zhǎng)腿小朋友們所呈現(xiàn)的特質(zhì)愈發(fā)明朗化,適應(yīng)小集體呢岗,與老師默契冕香,與同學(xué)們建立友誼指日可待~善良...
    青冥浩蕩不見底閱讀 408評(píng)論 4 0
  • 001 不要沉陷如何解決問題,而是透過問題思考本質(zhì)后豫,或者換個(gè)思路 開會(huì)時(shí)投影儀壞了悉尾,A同事到處去找人維修,會(huì)議時(shí)間...
    禮小禮er閱讀 82評(píng)論 0 5