【Vue3 從入門到實戰(zhàn) 進階式掌握完整知識體系】014-探索組件的理念:父子組件如何通過事件進行通信

5近速、父子組件如何通過事件進行通信

子組件調用的方法讓父組件處理

子組件調用父組件的方法來改變父組件的數(shù)據(jù)囤采。子組件無法改變父組件傳過來的數(shù)據(jù)悲没,可以通過此方法請求父組件來進行改變够傍!

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>hello vue</title>
  <!-- 引入Vue庫 -->
  <script src="https://unpkg.com/vue@next"></script>
</head>

<body>
  <div id="root"></div>
</body>

<script>
  const app = Vue.createApp({
    data(){
      return{
        count: 1
      }
    },
    methods:{
      // 在這里寫一個 handleAddOne() 方法
      handleAddOne(){
        this.count ++;
      }
    },
    // 父組件監(jiān)聽子組件要調用的方法畜挥,指向一個方法
    // 注意這里的 addOne 最好寫成 add-one
    template: `
        <div>
          <test :count="count" @add-one="handleAddOne()" />
        </div>
    `
  });

  
  app.component('test',{
    props:['count'],
    methods:{
      // 我們知道在這里我們不能修改 count 的值仔粥,因為它來自父組件
      // 但有時候我們確實需要修改這個值,我們就告訴父組件讓父組件修改它
      // 也就是子組件告訴父組件自己想要調用一個方法
      // 注意蟹但,這里的 addOne 不能帶 () 括號
      addOne(){
        this.$emit('addOne')
      }
    },
    template: `
        <div @click="addOne()">{{count}}</div>
    `
  })

  const vm = app.mount('#root');
</script>

</html>

運行結果

image-20210613145446569.png

子組件調用父組件的方法并傳參數(shù)

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>hello vue</title>
  <!-- 引入Vue庫 -->
  <script src="https://unpkg.com/vue@next"></script>
</head>

<body>
  <div id="root"></div>
</body>

<script>
  const app = Vue.createApp({
    data(){
      return{
        count: 1
      }
    },
    methods:{
      // 在這里寫一個 handleAdd() 方法
      handleAdd(param){
        this.count += param;
      }
    },
    // 父組件監(jiān)聽子組件要調用的方法躯泰,指向一個方法
    // 注意這里的 handleAdd 不能帶 () ,因為帶括號就意味著明確沒有傳參數(shù)
    template: `
        <div>
          <test :count="count" @add="handleAdd" />
        </div>
    `
  });

  
  app.component('test',{
    props:['count'],
    methods:{
      // 我們知道在這里我們不能修改 count 的值华糖,因為它來自父組件
      // 但有時候我們確實需要修改這個值麦向,我們就告訴父組件讓父組件修改它
      // 也就是子組件告訴父組件自己想要調用一個方法
      // 注意,這里的 add 不能帶 () 括號
      // 可以傳多個參數(shù)客叉,父組件事件中使用對應數(shù)量的參數(shù)接收即可
      add(){
        this.$emit('add', 5)
      }
    },
    template: `
        <div @click="add()">{{count}}</div>
    `
  })

  const vm = app.mount('#root');
</script>

</html>

運行結果

image-20210613150236756.png

在子組件中計算出來后上傳給父組件參數(shù)

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>hello vue</title>
  <!-- 引入Vue庫 -->
  <script src="https://unpkg.com/vue@next"></script>
</head>

<body>
  <div id="root"></div>
</body>

<script>
  const app = Vue.createApp({
    data(){
      return{
        count: 1
      }
    },
    methods:{
      // 在這里寫一個 handleAdd() 方法
      handleAdd(param){
        this.count = param;
      }
    },
    // 父組件監(jiān)聽子組件要調用的方法诵竭,指向一個方法
    // 注意這里的 handleAdd 不能帶 () ,因為帶括號就意味著明確沒有傳參數(shù)
    template: `
        <div>
          <test :count="count" @add="handleAdd" />
        </div>
    `
  });

  
  app.component('test',{
    props:['count'],
    methods:{
      // 我們知道在這里我們不能修改 count 的值十办,因為它來自父組件
      // 但有時候我們確實需要修改這個值秀撇,我們就告訴父組件讓父組件修改它
      // 也就是子組件告訴父組件自己想要調用一個方法
      // 注意,這里的 add 不能帶 () 括號
      add(){
        this.$emit('add', this.count + 3)
      }
    },
    template: `
        <div @click="add()">{{count}}</div>
    `
  })

  const vm = app.mount('#root');
</script>

</html>

運行結果

image-20210613150548226.png

校驗子組件對外觸發(fā)的事件

在子組件里面寫一個 emits: ['方法名'] 來實現(xiàn)校驗向族,因為當子組件里面的內容太多的話就影響可讀性呵燕,把對外觸發(fā)的事件全寫在這里面有助于閱讀!

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>hello vue</title>
  <!-- 引入Vue庫 -->
  <script src="https://unpkg.com/vue@next"></script>
</head>

<body>
  <div id="root"></div>
</body>

<script>
  const app = Vue.createApp({
    data(){
      return{
        count: 1
      }
    },
    methods:{
      handleAdd(param){
        this.count = param;
      }
    },
    template: `
        <div>
          <test :count="count" @add="handleAdd" />
        </div>
    `
  });

  
  app.component('test',{
    props:['count'],
    // 在這里寫一個 add 不會報錯
    // 但沒有寫 add 而是寫了一個 addOne 就會警告
    // 如果存在 emits 屬性件相,那么對外觸發(fā)的時候都要寫進來再扭,否則會警告
    emits: ['addOne'],
    methods:{
      add(){
        this.$emit('add', this.count + 3)
      }
    },
    template: `
        <div @click="add()">{{count}}</div>
    `
  })

  const vm = app.mount('#root');
</script>

</html>

運行結果

image-20210613154043173.png

更多的校驗

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>hello vue</title>
  <!-- 引入Vue庫 -->
  <script src="https://unpkg.com/vue@next"></script>
</head>

<body>
  <div id="root"></div>
</body>

<script>
  const app = Vue.createApp({
    data(){
      return{
        count: 1
      }
    },
    methods:{
      handleAdd(param){
        this.count = param;
      }
    },
    template: `
        <div>
          <test :count="count" @add="handleAdd" />
        </div>
    `
  });

  
  app.component('test',{
    props:['count'],
    // 在這里寫一個 add 不會報錯
    // 但沒有寫 add 而是寫了一個 addOne 就會警告
    // 如果存在 emits 屬性,那么對外觸發(fā)的時候都要寫進來夜矗,否則會警告
    emits: {
      // 檢驗參數(shù)
      add: (count) => {
        if(count > 0){
          return true;
        }else{
          return false;
        }
      }
    },
    methods:{
      add(){
        this.$emit('add', this.count + 3)
      }
    },
    template: `
        <div @click="add()">{{count}}</div>
    `
  })

  const vm = app.mount('#root');
</script>

</html>

運行結果

image-20210613154340970.png

父子組件之間的”雙向綁定“

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>hello vue</title>
  <!-- 引入Vue庫 -->
  <script src="https://unpkg.com/vue@next"></script>
</head>

<body>
  <div id="root"></div>
</body>

<script>
  const app = Vue.createApp({
    data(){
      return{
        count: 1
      }
    },
    template: `
        <div>
          <test v-model="count" />
        </div>
    `
  });

  
  app.component('test',{
    // modelValue 是固定寫法
    props:['modelValue'],
    methods:{
      add(){
        // 固定寫法
        this.$emit('update:modelValue', this.modelValue + 3)
      }
    },
    template: `
        <div @click="add()">{{modelValue}}</div>
    `
  })

  const vm = app.mount('#root');
</script>

</html>

運行結果

image-20210613154959373.png

自定義modelValue

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>hello vue</title>
  <!-- 引入Vue庫 -->
  <script src="https://unpkg.com/vue@next"></script>
</head>

<body>
  <div id="root"></div>
</body>

<script>
  const app = Vue.createApp({
    data(){
      return{
        count: 1
      }
    },
    template: `
        <div>
          <test v-model:app="count" />
        </div>
    `
  });

  
  app.component('test',{
    // modelValue 是固定寫法
    props:['app'],
    methods:{
      add(){
        // 固定寫法
        this.$emit('update:app', this.app + 3)
      }
    },
    template: `
        <div @click="add()">{{app}}</div>
    `
  })

  const vm = app.mount('#root');
</script>

</html>

運行結果

image-20210613155101659.png
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末泛范,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子紊撕,更是在濱河造成了極大的恐慌罢荡,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件对扶,死亡現(xiàn)場離奇詭異区赵,居然都是意外死亡,警方通過查閱死者的電腦和手機浪南,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門笼才,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人络凿,你說我怎么就攤上這事骡送“合郏” “怎么了?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵摔踱,是天一觀的道長虐先。 經(jīng)常有香客問我,道長派敷,這世上最難降的妖魔是什么赴穗? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮膀息,結果婚禮上般眉,老公的妹妹穿的比我還像新娘。我一直安慰自己潜支,他們只是感情好甸赃,可當我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著冗酿,像睡著了一般埠对。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上裁替,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天项玛,我揣著相機與錄音,去河邊找鬼弱判。 笑死襟沮,一個胖子當著我的面吹牛,可吹牛的內容都是我干的昌腰。 我是一名探鬼主播开伏,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼遭商!你這毒婦竟也來了固灵?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤劫流,失蹤者是張志新(化名)和其女友劉穎巫玻,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體祠汇,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡仍秤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了座哩。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片徒扶。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡粮彤,死狀恐怖根穷,靈堂內的尸體忽然破棺而出姜骡,到底是詐尸還是另有隱情,我是刑警寧澤屿良,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布圈澈,位于F島的核電站,受9級特大地震影響尘惧,放射性物質發(fā)生泄漏康栈。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一喷橙、第九天 我趴在偏房一處隱蔽的房頂上張望啥么。 院中可真熱鬧,春花似錦贰逾、人聲如沸悬荣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽氯迂。三九已至,卻和暖如春言缤,著一層夾襖步出監(jiān)牢的瞬間嚼蚀,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工管挟, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留轿曙,地道東北人。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓僻孝,卻偏偏與公主長得像拳芙,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子皮璧,可洞房花燭夜當晚...
    茶點故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內容