組件注冊
組件注冊有兩種方式:
- 全局注冊
可以使用Vue應用實例的.component()
方法,讓組件在當前Vue應用中全局可用,.component()
方法可以被鏈式調用。全局注冊的組件可以在此應用的任意組件的模版中使用。import { createApp } from 'vue' import { MyComponent } from './MyComponent.vue'const app = createApp({ }) app.component('MyComponent',MyComponent)
- 局部注冊
局部注冊的組件需要在它的父組件中顯示導入,并且只能在父組件中使用,依賴關系更加明確。<script> import MyComponent from './MyComponent'export default{components:{MyComponent} } </script><template><MyComponent /> </template>s
Props
一個組件需要顯示聲明它所接受的props。聲明props的方式有兩種:
- 字符串數組
export default{props:['animal','zoo'],created(){//props 會暴露到 this 上console.log(this.animal);console.log(this.zoo);} }
- 對象的形式
export default{props:{title:string,age:number} }
靜態Prop、動態Prop
- 靜態Prop傳參形式
<child-component title="this is title" />
- 動態Prop傳參形式,使用
v-bind
或縮寫:
來進行動態綁定<child-component :title="自定義的變量"/>
事件
觸發與監聽事件
- 觸發(子組件):在組件模版表達式中,可以直接使用
$emit
方法觸發自定義事件//1. 第一種觸發方式 <button @click="$emit('click')">觸發click事件</button> //2. 第二種觸發方式,函數觸發, this.$emit export default{methods:{submit(){this.$emit('click');}} }
- 父組件可以通過
v-on
或@
來監聽事件//1. 觸發 <child-component @click="alert(1)" /> //2. 事件監聽器也支持 .once 修飾符 <child-component @click.once="alert(1)" />
事件參數
可以給觸發的事件傳入參數,父組件可以處理傳入的參數
- 子組件傳入參數
<button @click="emit('click',1,2)">傳入參數給父組件</button>
- 父組件處理參數
<child-component @click="fun1"/>//處理參數的方法 methods:{fun1:function(var1,var2){console.log(var1);console.log(var2);} }
插槽 Slots
- 父組件傳入,插槽內容可以是任意合法的模版內容,不局限于文本,可以傳入多個HTML元素,甚至組件
<child-component>傳入內容 </child-component>
- 子組件插槽占位
<h1><slot></slot> </h1>
插槽渲染作用域
插槽可以訪問到父組件的數據作用域,因為插槽內容本身是在父組件中定義的。插槽無法訪問子組件的數據。
插槽默認內容
如果父組件沒有提供任何內容,可以為插槽指定默認內容
<button><slot>默認內容</slot>
</button>
具名插槽
- 子組件為插槽指定名稱,沒有提供
name
的<slot>
會隱式地命名為default<div><slot name="header"></slot><slot name="footer"></slot><slot></slot> </div>
- 父組件指定插槽名稱傳入內容,
v-slot
簡寫#
<child-component><template #header>This is header</template><template #footer>This is footer</template><template #default>This is default</template> </child-component>
動態插槽名
可以使用動態的插槽名,傳給子組件內容
<child-component><template v-slot:[defineSlotName]></template><template #[defineSlotName]></template>
</child-component>
作用域插槽
某些場景下插槽的內容想要同時使用父組件域內和子組件域內的數據,子組件可以在渲染時將一部份數據提供給插槽
- 默認插槽
//子組件插槽插入數據 <div><slot :name="zqq" :age="18"></slot> </div> //父組件使用 <child-component v-slot="vslot">{{ vsolt.name }} {{ vsolt.age }} </child-component>
- 具名作用域插槽
//子組件插槽傳入數據,name是vue特別保留的attribute,不會作為props傳遞給插槽 <slot name="header" message="hello"> </slot> //父組件使用 <child-component><template #header="data">{{ data s}}</template> </child-component>
依賴注入
一個父組件相當于其所有的后代組件,會作為依賴提供者。任何后代的組件樹,無論層級多深,都可以注入由父組件提供給整條鏈路的依賴。關鍵字:provide
和inject
。
- provide(提供),為后代組件提供數據
//為后代組件提供數據 export default{privode:{message:'hello'} } //為后代組件提供data()定義的數據屬性,以函數形式使用provide export default{data(){return{message:'hello'}},provide:(){return{message:this.message;}} }//在應用層為全部組件提供依賴 import { createApp } from 'vue'const app = createApp({}) // message是注入的名稱,hello是值 app.provide('message','hello');
- Inject(注入),子組件注入父組件(隔代父組件也可以)提供的依賴
export default{inject:['message'],data(){return{//注入會在組件自身狀態之前被解析,可以通過this訪問注入的值localMessage:this.message}} }
注入別名和默認值
export{inject:{// localMessage是自定義的本地別名,后續訪問注入的內容,使用this.localMessagelocalMessage:{from:'message',default:'default' //可以指定默認值}}
}
和響應式數據配合使用
為了保證注入方和供給方之間的響應性鏈接,需要使用computed()函數提供一個計算屬性
import default{data(){return{message:'hello'}}provide(){return{message:computed(() => this.message)}}}
}
異步組件
在大型項目中,我們可能需要拆分應用為更小的塊,并僅在需要時再從服務器加載相關組件,Vue提供了defineAsyncComponent
方法來實現
const AsyncComp = defineAsynComponet(() => {return new Promise(() =>{//...從服務器獲取組件resolve(/*獲取到的組件*/);})
})
導入Vue單文件組件
import { defineAsyncComponent } from 'vue'const AsyncComp defineAsyncComponent(() => import('./components/MyComponent.vue'))
最后得到的AsyncComp
是一個外層包裝過的組件,僅在頁面需要它渲染時才會調用加載內部實際組件的函數。它會將受到的props和插槽傳給內部組件,所以可以使用這個異步的包裝組件無縫地替換原始組件,同時實現延遲加載。
異步組件注冊
- 全局注冊
app.component('MyComponent',defineAsyncComponent(() => import('./components/MyComponent.vue'))
- 局部注冊
<script> impoty { defineAsyncComponent } from 'vue'export default{components{MyComponent:defineAsyncComponent(() = import('./components/MyComponent.vue'))} } </script>
加載與錯誤狀態
const AsyncComp = defineAsyncComponent({//加載組件函數loader:() => import(',MyComponent'),//展示加載組件的延遲時間,默認200msdelay:200,//加載失敗后展示的組件errorComponent:ErrorComponent,//加載組件超時時間,默認沒有超時時間,如果超市,會顯示 加載失敗展示的組件timeOut: 3000
})