Vue3复习和总结(Component)组件间四种数据传递的方式与插槽与祖孙组件间通信,props、emit、ref,Provide / Inject
代码全部放在->github仓库:https://github.com/zyugat/vue-review-all
前言:分为base、Component、router、Vuex、组合式API。5各部分。
base和Component中的例子不使用脚手架运行,需自行浏览器运行。位置->noCli
组件间四种数据传递的方式与插槽
props
字符串数组
-
父传子→
props
- props两种实现:一种是以字符串数组,一种是以对象实现。
1、父组件传入:chello="hello"
属性
2、子组件声明接收props: ['chello']
<div id="app">
<cpn :chello="hello"></cpn>
</div>
<!--<template id="cpn">-->
<!-- <h2>{{ chello }}</h2>-->
<!--</template>-->
<script>
const App = {
data() {
return {
hello: 'Hello',
}
}
}
const app = Vue.createApp(App)
app.component('cpn', {
// template: '#cpn',
template: `
<h2>{{ chello }}</h2>
`,
// 创建props
props: ['chello'],
})
app.mount('#app')
</script>
对象
props: {
// 1.类型限制
// cmessage: Array,
// chello: String,
// 2.提供一些默认值, 以及必传值
chello: {
type: String,
default: 'aaaaaaaa',
required: true
},
// 类型是对象或者数组时, 默认值必须是一个函数
cmessage: {
type: Array,
default () {
return []
}
}
},
emit
- 子传父→
$emit
第一步:子组件创建事件。第二步:按钮监听子组件事件。最后一步:获取信息。
更多扩展看下面->自定义事件与v-model
<div id="app">
<cpn2 @item-click="cpn2Click"></cpn2>
</div>
<script>
const App = {
methods: {
// 第三步:将按钮信息发送到控制台
cpn2Click(item) {
console.log('cpnClick', item)
},
},
}
const app = Vue.createApp(App)
app.component('cpn2', {
template: `
<button @click="btnClick">子传父</button>
`,
methods: {
btnClick(event) {
// 第一步:发射自定义事件
this.$emit('item-click', event)
},
},
})
app.mount('#app')
</script>
refs
父访问子→$refs
- 给组件绑定一个ID,然后使用
this.$refs.ID
调用。
<div id="app">
<button @click="btnClick" ref="test">refs获取</button>
</div>
<script>
const App = {
methods: {
btnClick() {
// 2.$refs => 对象类型
console.log(this.$refs.test)
},
},
}
const app = Vue.createApp(App)
app.mount('#app')
</script>
祖孙组件通信Provide / Inject
Provide / Inject
1、祖与孙组件间通信。
父组件使用 provide
选项来发送数据
后代组件使用 inject
选项来获取数据
app.component('grandfather', {
provide: {
user: 'John Doe',
},
template: `
<father />`,
components: {
'father': {
template: `
<son />`,
components: {
'son': {
inject: ['user'],
template: `son:{{user}}`,
},
},
},
},
})
2、如果想在 provide
中使用组件的实例 property
属性,则需要将 provide
转换为返回对象的函数。
provide() {
return {
user: this.num,
}
},
3、 provide/inject
的绑定不是响应式的,如果想修改todos的长度,则需要绑定组合式API computed
属性。
provide() {
return {
user: Vue.computed(() => this.num),
}
},
插槽
具名插槽
缩写:<template #header>
因为没有调用 右边 所以少了他。
<div id="app">
<cpn3><span slot="center">标题 </span></cpn3>
<cpn3><span slot="left">中间 </span></cpn3>
</div>
<template id="cpn3">
<div>
<slot name="left"><span>左边</span></slot>
<slot name="center"><span>中间</span></slot>
<slot name="right"><span>右边</span></slot>
</div>
</template>
作用域插槽
可以理解为:将外部内容放在子组件slot中。
<slot :item="item" :index="index" :another-attribute="anotherAttribute"> <span>{{ item }}</span> <span>-----{{ anotherAttribute }}</span> </slot>
这样看懂了把?
自定义项目的渲染方式。默认插槽不能和具名插槽混用
1、v-slot:default=""
或v-slot=""
,不带参数的 v-slot
被假定对应默认插槽。
2、在插槽中,绑定了item、index、anotherAttribute,如果需要用到某个属性则可以使用 slotProps.属性名
,进行调用。
slotProps可以替换为任何名字。
<div id="app">
<cpnslot>
<template v-slot:default="slotProps">
<span>{{ slotProps.item }}</span>
<span>-----{{ slotProps.anotherAttribute }}</span>
</template>
</cpnslot>
</div>
<script>
const App = {}
const app = Vue.createApp(App)
app.component('cpnslot', {
data() {
return {
items: [1, 2, 3, 4, 5],
anotherAttribute: 'slot-anotherAttribute',
}
},
template: `
<ul>
<li v-for="(item, index) in items">
<slot :item="item" :index="index"
:another-attribute="anotherAttribute"></slot>
</li>
</ul>
`,
})
app.mount('#app')
</script>
因为作用域插槽的内部工作原理是将你的插槽内容包括在一个传入单个参数的函数里,所以可以在里面使用JS表达式,如重命名:
将item重命名为todo
<todo-list v-slot="{ item: todo }">
动态插槽名
<template v-slot:[dynamicSlotName]>