整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          Vue進階(六):組件之間的數據傳遞

          Vue 的組件作用域都是孤立的,不允許在子組件的模板內直接引用父組件的數據。必須使用特定的方法才能實現組件之間的數據傳遞。

          首先用腳手架工具 vue-cli 創建一個項目,其中 App.vue 是父組件,components 文件夾下都是子組件。

          一、父組件向子組件傳遞數據

          Vue 中,父組件可以使用 props 向子組件傳遞數據。

          子組件部分:

          這是 header.vueHTML 部分,logo 是在 data 中定義的變量。

          如果需要從父組件獲取 logo 的值,就需要使用props: ['logo']。


          props 添加了元素之后,就不需要在 data 中再添加變量了。

          父組件部分:

          在調用組件的時候,使用 v-bind 將 logo 的值綁定為 App.vue 中定義的變量 logoMsg。

          然后就能將App.vuelogoMsg 的值傳給 header.vue 了:

          二、子組件向父組件傳遞數據

          子組件主要通過事件傳遞數據給父組件。

          子組件部分:

          這是 login.vue HTML 部分,當<input>的值發生變化的時候,將 username 傳遞給 App.vue。

          首先聲明一個方法setUser,用change事件來調用 setUser。

          setUser 中,使用了 $emit 來遍歷 transferUser 事件,并傳參this.username

          其中transferUser是一個自定義的事件,功能類似于一個中轉,this.username將通過這個事件傳遞給父組件。

          父組件部分:

          在父組件 App.vue 中,聲明了一個方法 getUser,用 transferUser 事件調用 getUser 方法,獲取到從子組件傳遞過來的參數 username

          getUser方法中的參數 msg 就是從子組件傳遞過來的參數username

          三、子組件向子組件傳遞數據

          Vue 沒有直接子對子傳參的方法,建議將需要傳遞數據的子組件,都合并為一個組件。如果一定需要子對子傳參,可以先從子組件傳到父組件,再傳到子組件。

          為了便于開發,Vue 推出了一個狀態管理工具 Vuex(詳參博文《Vue進階(五):與 Vuex 的第一次接觸》),可以很方便實現組件之間的參數傳遞。

          附 Prop校驗

          子組件用Props接收父組件傳來的消息有多種形式:

          1.數組形式

          props: [data1, data2]

          數組形式相當于直接接收消息,不做任何校驗,一般來說,不太建議使用數組形式。

          2.簡單對象形式

           props: { data1: String, data2: Array}

          簡單對象形式對父組件傳遞的值進行了類型校驗,如果傳過來的值類型不一致,控制臺會報錯。

          3.復雜對象形式

           props: { 
            data1: {
              type: String, //設定類型
              required: true, //是否必須
              default: 'default value', //默認值  
              validator (value) {   return (value.length < 5)  } }, //校驗規則 
            data2: {  
              type: Array,
              required: true,
              default: () => ['', '', ''] 
           }}

          復雜對象形式的情況下,作為對象屬性參數可以寫為對象形式,參數對象含有4個屬性,

          • type: 設定參數類型,當傳入參數類型與type不相符時,控制臺會報錯;
          • required:設定參數是否是必傳,當設為true時,不傳該參數會報錯;
          • default:設定默認值,當參數類型為復雜類型時,需使用工廠模式生成默認值,否則Vue會在控制臺拋出警告;
          • validator:校驗器,是一個函數,擁有一個代表傳入值的形參,可以自定義各種校驗,當返回false時,會報錯,表示沒通過校驗。

          注意:prop 會在一個組件實例創建之前進行驗證,所以實例的屬性 (如 data、computed 等) 在 defaultvalidator 函數中是不可用的。

          類型檢查

          type 可以是下列原生構造函數中的一個:

          String、Number、Boolean、Array、Object、Date、Function、Symbol

          type 還可以是一個自定義的構造函數,并且通過 instanceof 來進行檢查確認。

          例如,給定下列現成的構造函數:

          function Person (firstName, lastName) {
            this.firstName = firstName
            this.lastName = lastName
          }

          你可以使用:

          Vue.component('blog-post', {
            props: {
              author: Person
            }
          })

          來驗證 author prop 的值是否是通過 new Person 創建的。

          我們可能聽過C語言中的傳值和傳指針,在其他語言中,也有傳引用一說,那么他們到底有什么區別呢?如果你還不能準確地分辨,就該好好了解一下了。

          傳值

          我們在初學C語言的時候就被老師教過,下面的方式是無法交換a和b的值的:

          #include<stdio.h>
          void swap(int a,int b)
          {
           int temp = a;
           a = b;
           b = temp;
           printf("swap a = %d,b = %d\n",a,b);
          }
          int main(void)
          {
           int a = 10;
           int b = 20;
           printf("before swap:a = %d,b = %d\n",a,b);
           swap(a,b);
           printf("after swap:a = %d,b = %d\n",a,b);
           return 0;
          }
          

          運行結果如下:

          before swap:a = 10,b = 20 
          internal swap a = 20,b = 10 
          after swap:a = 10,b = 20 
          

          可以看到,a和b的值最終并沒有被交換。開始時a,b的值為10,20,而最終還是同樣的值。

          為什么呢?因為函數參數在傳遞的時候,都是傳原數據的副本,也就是說,swap內部使用的a和b只是最初始a和b的一個副本而已,所以無論在swap函數內部對a和b做任何改變,都不會影響初始的a和b的值。

          正因如此,我們常常被告知,不要把直接把結構體直接作為參數,這樣效率會很低。由于結構體本身占用字節數較大,如果直接作為參數,那么將會產生一個較大的”副本“,如此一來,效率也就很低了。

          我們再結合下面的圖來理解:

          值傳遞

          首先圖中方框中的上部分a和b代表了main函數中的a和b,即原始數據,而方框中的下部分a和b代表了函數的參數a和b,即原始數據的“副本”。(后面的圖都是如此,上部分代表原始值,下部分代表函數參數值)。

          調用swap函數前后的情形如下:

          調用swap前后

          由于在swap中永遠只是對a和b的副本進行操作,因此完全不影響原始的a和b的值。最終也不可能達到交換a和b的值的目的。

          傳指針

          那么為解決上面的問題,我們知道,需要傳指針。其代碼如下:

          #include<stdio.h>
          void swap(int *a,int *b)
          {
           int temp = *a;
           *a = *b;
           *b = temp;
           printf("swap a = %d,b = %d\n",*a,*b);
          }
          int main(void)
          {
           int a = 10;
           int b = 20;
           printf("before swap:a = %d,b = %d\n",a,b);
           swap(&a,&b);
           printf("after swap:a = %d,b = %d\n",a,b);
           return 0;
          }
          

          運行結果:

          before swap:a = 10,b = 20 
          swap a = 20,b = 10 
          after swap:a = 20,b = 10 
          

          可以看到在這種情況下,a,b的值才是真正交換了。

          為什么又有傳值,又有傳指針

          看到這里,不知道你是否會疑惑,為什么給函數傳遞參數的時候,一會是傳值,一會是傳指針呢?為什么傳指針就能改變參數的值呢?實際上,C語言里,參數傳遞都是值傳遞!也就是說,你認為的傳指針也是傳值,只不過它的值是指針類型罷了。

          我們再通過圖來理解前面為什么傳指針就可以交換a,b的值:

          傳指針

          從圖中可以看出,雖然傳遞給函數的是指向a和b的指針的副本,但是它的副本同樣也是指向a和b,因此雖然不能改變指針的指向,但是能改變參數a和b指向的內容,即改變原始a和b的值。

          再看傳指針

          如果是為指針p申請一段內存,下面的代碼能達到目的嗎?

          #include<stdio.h>
          #include<stdlib.h>
          void getMemery(int *p)
          {
           /*申請1024個int大小*/
           p = malloc(sizeof(int)*1024);
           if(NULL == p)
           {
           printf("malloc failed\n");
           p = NULL;
           }
          }
          int main(void)
          {
           int *p = NULL;
           getMemery(p);
           printf("address of p is %p\n",p);
           return 0;
          }
          

          通過前面的內容分析,肯定是達不到預期效果的。

          運行結果:

          address of p is (nil)
          

          這是為什么呢?我們還是利用前面所知來分析,由于傳遞給getMemory函數的參數都是一個副本,因此函數內的p也是外部p的一個副本,因此即便在函數內部,將p指向了一塊新申請的內存,仍然不會改變外面p的值,即p還是指向NULL。

          如何修改呢?我們需要傳入p的地址,即指向int類型指針的指針。

          #include<stdio.h>
          #include<stdlib.h>
          void getMemery(int **p)
          {
           /*申請1024個int大小*/
           *p = malloc(sizeof(int)*1024);
           if(NULL == *p)
           {
           printf("malloc failed\n");
           *p = NULL;
           }
          }
          int main(void)
          {
           int *p = NULL;
           getMemery(&p);
           printf("address of p is %p\n",p);
           free(p);
           p = NULL;
           return 0;
          }
          

          運行結果如下:

          address of p is 0x144f010
          

          從運行結果可以看到,p的值被改變了。

          可配合下面的圖進行理解:

          總結

          本文總結如下:

          • 函數的形參都是原數據的“副本”,因此在函數內無法改變原數據
          • 函數中參數都是傳值,傳指針本質上也是傳值
          • 如果想要改變入參內容,則需要傳該入參的地址(指針和引用都是類似的作用),通過解引用修改其指向的內容
          • 以上結論不限于C語言

          本文原地址:https://www.yanbinghu.com/2019/06/20/53981.html

          思考

          • 如何實現不借助第三個變量,交換兩個整數的值?
          • 結合本文,理解C++/Java中所謂的傳引用

          微信公眾號【編程珠璣】:專注但不限于分享計算機編程基礎,Linux,C語言,C++,數據結構與算法,工具,資源等編程相關[原創]技術文章,號內包含大量經典電子書和視頻學習資源。歡迎一起交流學習,一起修煉計算機“內功”,知其然,更知其所以然。

          JavaScript 類似,要在 TypeScript 中將函數作為參數傳遞,定義一個函數期望接收回調函數的參數,然后在父函數內部觸發回調函數。 例如,請注意我們在以下示例中調用 foo 函數時如何將 bar 作為回調函數傳遞:

          但是,此代碼存在問題。如果復制此代碼到 JavaScript 文件中,不會出現任何語法錯誤,因為我們沒有使用任何 TypeScript 類型。此外,我們遇到了傳遞任何參數值的可能性,這意味著我們可以提供非函數的任意類型作為 foo 的參數,而不會“出錯”,直到代碼執行。因為這里callback被默認解釋為any類型。

          使用Function定義函數參數類型

          現在我們把 callback 指定為函數類型,

          如果我們再傳入非函數,就會報錯了!

          定義從 Function 類型返回的期望值

          使用 Function 類型是防止由于 JavaScript 中缺少類型定義而導致的常見錯誤的一大步。 但是,使用 Function 類型仍然會為邏輯中的潛在錯誤留下空間。

          如果接收回調函數的函數使用回調函數的返回值來運行額外的進程怎么辦? 為了使這個假設更清楚,讓我們對 foo 函數進行更改。

          注意 foo 函數不僅調用回調函數,而且還使用回調函數返回的值來獲取該值的平方根,假設回調函數返回的值是一個數字。如果你回顧返回函數的定義,如果這個函數沒有返回任何東西,默認返回值是undefined。

          它返回undefined

          因此,如果我們將 bar 作為 foo 的回調函數傳遞,在運行時可能可能會出現意外行為。

          所以,我們可以通過定義回調函數的返回值的類型來防止 TypeScript 中出現這種意外行為。 于是我們就不能在這里繼續使用Function類型。 相反,使用返回類型的箭頭函數表達式來提供有效的類型定義。 讓我們再修改一下 foo 函數的定義來理解這個概念,

          現在我們定義了函數參數的返回值類型,所以現在的bar函數將不再滿足,因為它返回是undefined, 自然它就會報錯。

          我們修改一下bar函數,讓它滿足callback的函數簽名,就可以解決了?,F在運行代碼就安全多了。


          主站蜘蛛池模板: 亚洲一区二区三区在线观看网站| 波多野结衣AV无码久久一区| 香蕉在线精品一区二区| 2014AV天堂无码一区| 国产女人乱人伦精品一区二区 | 亚洲av无一区二区三区| 无遮挡免费一区二区三区| 亚洲欧美国产国产一区二区三区| 国产高清不卡一区二区| 亚洲国产精品成人一区| 日韩精品一区二区午夜成人版| 国产精品一区二区久久精品涩爱| 水蜜桃av无码一区二区| 国模私拍一区二区三区| 国产精品一区二区av| 国精产品一区一区三区| 日韩AV无码一区二区三区不卡毛片| 一级特黄性色生活片一区二区| 卡通动漫中文字幕第一区| 国产一区二区在线|播放| 无遮挡免费一区二区三区| 亚洲国产专区一区| 国产在线精品一区免费香蕉 | 97久久精品无码一区二区天美 | 亚洲国产一区在线| 少妇激情一区二区三区视频| 搡老熟女老女人一区二区| 日韩人妻无码一区二区三区99| 91亚洲一区二区在线观看不卡| 精品无码一区二区三区爱欲| 91在线精品亚洲一区二区| 国产精品99精品一区二区三区| 精品一区二区三人妻视频| 国产人妖视频一区二区破除 | 麻豆AV无码精品一区二区| 无码人妻aⅴ一区二区三区| 无码8090精品久久一区| 国产AV午夜精品一区二区三| 国产精品一区二区久久国产| 亚洲一区在线观看视频| 久久精品成人一区二区三区|