Vue3——組件傳值 & v-model & 異步組件 & teleport組件

一役耕、父子組件傳值

父組件通過props向子組件傳值,子組件通過emit觸發(fā)自定義事件傳遞新值給父組件里逆。
props:setup函數(shù)中第一個參數(shù)props用于接收父組件傳遞進來的參數(shù)肛根。注意:props參數(shù)中,只會接收props選項中接收的參數(shù) 活鹰。
context參數(shù):setup函數(shù)中的第二個參數(shù)是一個上下文對象context哈恰。context參數(shù)里面有三個對象:attrs,emit志群,slots着绷。

  • attrs:用于獲取沒有采用props選項接收的參數(shù)。
  • emit:用于觸發(fā)自定義事件锌云。
  • slots:返回的是插槽里面的虛擬DOM信息荠医。

虛擬DOM:就是vue實例所能識別的一個DOM信息對象。

父組件

<div class="parent">
  <h2>父組件</h2>
  <div>姓名:{{ name }}</div>
  <div>年齡:{{ age }}</div>
  <div>年齡:{{ sex }}</div>
  <Son1 :name="name" :age="age" :sex="sex" @updateData="updateData">
      <!-- 這里是具名插槽 -->
      <template v-slot:top>
          <div class="box">這里頂部</div>
          <div class="box">
              <button>這里頂部</button>
          </div>
      </template>
      <!-- #是v-slot:的簡寫 -->
      <template #bottom="scope">
          <div class="box">這里底部
              <ul>
                  <li>{{scope.car.name}}</li>
                  <li>{{scope.car.price}}</li>
              </ul>
          </div>
      </template>
  </Son1>
</div>
import {ref} from 'vue'
import Son1 from "./Son1.vue";
export default {
  name: "Parent",
  setup() {
      let name = ref('張三')
      let age = ref(20)
      let sex = ref('男')
      let updateData = (e)=>{   
          name.value = e.myName
          age.value = e.myAge
          sex.value = e.mySex
      }
      return {
          name,
          age,
          sex,
          updateData
      }
  },
  /* data() {
      return {
          name:'張三',
          age:20
      }
  },
  methods: {
      updateData(e){
          this.name = e.myName
          this.age = e.myAge
      }
  }, */
  components: {
    Son1,
  },
};

子組件

<div class="son1">
  <!-- 插槽宾抓,定義多個插槽時子漩,需要給插槽定義名稱:具名插槽 -->
  <slot name="top"></slot>
  <h2>Son1</h2>
  <div>姓名:{{ myName }}</div>
  <div>年齡:{{ myAge }}</div>
  <div>性別:{{ mySex }}</div>
  <div><button @click="updateData">修改數(shù)據</button></div>
  <!-- 可以通過插槽傳遞一份數(shù)據給插槽的使用者,這樣的插槽稱為作用域插槽 -->
  <slot name="bottom" :car="car"></slot>
</div>
import {ref,reactive} from 'vue';
export default {
  name: "Son1",
  //接收父組件的傳值
  props: ["name", "age"],
  // setup的第一個參數(shù)石洗,用于獲取父組件的傳值
  // 注意:props選項接收了幾個參數(shù)幢泼,setup函數(shù)的第一個參數(shù)就只能獲取幾個參數(shù)。
  // setup的第二個參數(shù)讲衫,是一個上下文對象缕棵;它里面一個方法是emit,用于觸發(fā)自定義事件
  // props選項沒有接收的傳值涉兽,在setup里面通過上下文對象的attrs屬性接收
  setup(props,{emit,attrs,slots}) {
      // slots對象返回的是插槽里面的虛擬DOM信息
      console.log(slots.top());
      // 中轉props里面的數(shù)據招驴,因為props是只讀的
      let myName = ref(props.name)
      let myAge = ref(props.age)
      let mySex = ref(attrs.sex)
      let car = reactive({
        name:'奔馳',
        price:20
      })
      let updateData = ()=>{
          myName.value = '李四'
          myAge.value = 30
          mySex.value = '女'
          // 觸發(fā)自定義事件
          emit('updateData',{myName:myName.value,myAge:myAge.value,mySex:mySex.value})
      }
      return {
          myName,
          myAge,
          mySex,
          updateData,
          car
      }
  }
  /* data() {
      return {
          myName:this.name,
          myAge:this.age
      }
  },
  methods: {
      updateData(){
          this.myName = '李四'
          this.myAge = 30
          this.$emit('updateData',{myName:this.myName,myAge:this.myAge})
      }
  }, */
};

二、祖孫組件傳值

祖級組件通過provide將指定的數(shù)據添加為依賴數(shù)據枷畏,讓后代組件可以直接使用别厘。孫代組件通過inject注入祖級組件中設置為依賴的數(shù)據。

祖級組件

import {ref,provide} from 'vue'
import Son from './components/Son.vue'
export default {
  name: 'App',
  setup() {
    let name = ref('張三')
    let age = ref(20)
    // 通過provide()方法拥诡,定義依賴數(shù)據触趴,從此它的子組件氮发,就可以獲取這些數(shù)據了
    provide('name',name)
    provide('age',age)
    return {
      name,
      age
    }
  },
  components: {
    Son
  }
  /* data() {
    return {
      name:'張三',
      age:20
    }
  },
  methods: {
    // 修改數(shù)據的方法
    updateData(name,age){
      this.name = name
      this.age = age
    }
  },
  // 定義依賴數(shù)據
  provide(){
    return {
      name:this.name,
      age:this.age,
      updateData:this.updateData
    }
  }, */
}

孫級組件

<div class="subSon">
  <h2>SubSon</h2>
  <ul>
      <li>姓名:{{name}}</li>
      <li>年齡:{{age}}</li>
      <li>
          <button @click="update">修改信息</button>
      </li>
  </ul>
</div>
import {inject} from 'vue'
export default {
  name: "SubSon",
  setup() {
      // inject()方法,用于注入父級中依賴的數(shù)據
      let name = inject('name')
      let age = inject('age')
      let update = ()=>{
          name.value = '李四'
          age.value = 30
      }
      return {
          name,
          age,
          update
      }
  }
  /* inject:['name','age','updateData'],
  data() {
      return {
          myName:this.name,
          myAge:this.age
      }
  },
  methods: {
      update(){
          this.myName = '李四'
          this.myAge = 30
          this.updateData('李四',30)
      }
  }, */
};

三冗懦、v-model

在Vue3中爽冕,父組件中可以通過v-model指令實現(xiàn)對多個數(shù)據的雙向綁定。注意:vue3取消了sync修飾符披蕉,它將v-model指令和sync修飾符進行了合并颈畸。
子組件中,自定義事件名稱必須命名為update:屬性名没讲,就可以實現(xiàn)對父組件中指定屬性的雙向綁定眯娱。

父級組件

<div class="app">
  <h2>App</h2>
  <!-- 在vue3中子定義組件時,v-model可以使用多次食零,實現(xiàn)對多個數(shù)據的雙向綁定-->
  <Son3 v-model:planeName="planeName"  v-model:planePrice="planePrice" v-model:planeAddress="planeAddress" />
</div>
import {ref,provide} from 'vue'
import Son3 from './components/Son3.vue'
export default {
  name: 'App',
  setup() {
    //定義飛機的相關數(shù)據
    let planeName = ref('波音747')
    let planePrice = ref(100)
    let planeAddress = ref('美國')

    return {
      // 返回飛機相關信息
      planeName,
      planePrice,
      planeAddress
    }
  },
  components: {
    Son3
  }

子級組件

<div class="son3">
  <h2>Son3</h2>
  <ul>
    <li>飛機名稱:{{ planeName }}</li>
    <li>飛機價格:{{ planePrice }}</li>
    <li>飛機產地:{{ planeAddress }}</li>
    <li>
      <button @click="updatePlaneName">修改飛機名稱</button>
    </li>
    <li>
      <button @click="updatePlanePrice">修改飛機價格</button>
    </li>
    <li>
      <button @click="updatePlaneAddress">修改飛機產地</button>
    </li>
  </ul>
</div>
export default {
  name: "Son3",
  //接收父組件傳遞過來的數(shù)據
  props: ["planeName", "planePrice", "planeAddress"],
  setup(props, { emit }) {
    let updatePlaneName = () => {
      // 注意:事件方法必須是update:prop困乒,如果父組件中采用的是v-model:prop
      // 此時寂屏,父組件就可以實現(xiàn)對prop的雙向數(shù)據綁定贰谣。
      emit("update:planeName", "長城1號");
    };
    let updatePlanePrice = () => {
      emit("update:planePrice", 200);
    };
    let updatePlaneAddress = () => {
      emit("update:planeAddress", "中國");
    };
    return {
      updatePlaneName,
      updatePlanePrice,
      updatePlaneAddress,
    };
  },
};

四、異步組件

suspense內置組件:用于在渲染異步組件時迁霎,添加Loading效果吱抚。
使用 <suspense></suspense> 包裹所有異步組件相關代碼。
<suspense></suspense> 下 <template #default></template> 插槽包裹異步組件考廉。
<suspense></suspense> 下 <template #fallback></template> 插槽包裹渲染異步組件之前的內容秘豹。
注意:異步加載的組件可以用suspense,也可以不用昌粤。不用suspense組件既绕,會失去異步的作用;但是涮坐,如果組件中setup的返回值是一個Promise對象凄贩,該組件必須要用suspense。

定義組件

<div class="son4">
  <h2>Son4</h2>
  <ul>
    <li>商品名稱:{{ goodsName }}</li>
    <li>商品價格:{{ goodsPrice }}</li>
    <li>
        <input type="text" v-model="goodsName">
    </li>
  </ul>
</div>
import { ref } from "vue";
export default {
  name: "Son4",
  setup() {
    let goodsName = ref("小米電視");
    let goodsPrice = ref(2000);
    //setup方法的返回值袱讹,可以是一個Promise對象
    return new Promise((resolve,reject)=>{
        setTimeout(() => {
            resolve({
                goodsName,
                goodsPrice,
                show
            })
        }, 2000);
    })

    // return {
    //     goodsName,
    //     goodsPrice,
    // }
  },
};

使用

<div class="app">
  <h2>App</h2>
  <!-- suspense內置組件疲扎,用于在渲染異步組件時,添加Loading效果 -->
  <suspense>
    <!-- default插槽里面放置異步組件 -->
    <template #default>
      <Son4/>
    </template>
    <!-- fallback插槽里面放置組件沒有加載完成時顯示的內容 -->
    <template #fallback>
      Loading...
    </template>
  </suspense>
</div>
// defineAsyncComponent組合式API捷雕,用于定義異步組件
import {defineAsyncComponent} from 'vue'
// 異步導入組件
const Son4 = defineAsyncComponent(()=>import('./components/Son4.vue'))

五椒丧、teleport組件

Vue 3.0 新增了一個內置組件 teleport ,主要是為了解決以下場景:有時組件模板的一部分邏輯上屬于該組件救巷,而從技術角度來看壶熏,最好將模板的這一部分移動到 DOM 中 Vue app 之外的其他位置。
teleport組件:瞬移浦译。通過to屬性確定里面的元素移動到哪棒假。to屬性的屬性值是指定的選擇器俄占。

例如:在下面的案例中,box盒子邏輯上屬于son4盒子淆衷,但是為了使box盒子設置的相對定位缸榄,不受其他父級元素的影響,我們將box盒子瞬移到body下祝拯。

<div class="son4">
  <h2>Son4</h2>
  <button @click="show=true">顯示</button>
  <!-- teleport組件:瞬移甚带。通過to屬性確定里面的元素移動到哪。
  to屬性的屬性值是指定的選擇器 -->
  <teleport to="body">
      <div v-show="show" class="box">
          <ul>
              <li>商品名稱:{{ goodsName }}</li>
              <li>商品價格:{{ goodsPrice }}</li>
          </ul>
          <button @click="show=false">關閉</button>
      </div>
  </teleport>
</div>
.box{
    width: 200px;
    height: 200px;
    border: 1px solid black;
    padding: 10px;
    background: lightblue;
    /* 絕對定位 */
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    margin: auto;
}

使用teleport瞬移后佳头,box盒子的結構是在body下鹰贵,與#app平級。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末康嘉,一起剝皮案震驚了整個濱河市碉输,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌亭珍,老刑警劉巖敷钾,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異肄梨,居然都是意外死亡阻荒,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門众羡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來侨赡,“玉大人,你說我怎么就攤上這事粱侣⊙蛞迹” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵齐婴,是天一觀的道長油猫。 經常有香客問我,道長尔店,這世上最難降的妖魔是什么眨攘? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮嚣州,結果婚禮上鲫售,老公的妹妹穿的比我還像新娘。我一直安慰自己该肴,他們只是感情好情竹,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著匀哄,像睡著了一般秦效。 火紅的嫁衣襯著肌膚如雪雏蛮。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天阱州,我揣著相機與錄音挑秉,去河邊找鬼。 笑死苔货,一個胖子當著我的面吹牛犀概,可吹牛的內容都是我干的。 我是一名探鬼主播夜惭,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼姻灶,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了诈茧?” 一聲冷哼從身側響起产喉,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎敢会,沒想到半個月后曾沈,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡走触,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年晦譬,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片互广。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖卧土,靈堂內的尸體忽然破棺而出惫皱,到底是詐尸還是另有隱情,我是刑警寧澤尤莺,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布旅敷,位于F島的核電站,受9級特大地震影響颤霎,放射性物質發(fā)生泄漏媳谁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一友酱、第九天 我趴在偏房一處隱蔽的房頂上張望晴音。 院中可真熱鬧,春花似錦缔杉、人聲如沸锤躁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽系羞。三九已至郭计,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間椒振,已是汗流浹背昭伸。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留澎迎,地道東北人勋乾。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像嗡善,于是被迫代替她去往敵國和親辑莫。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內容