1.defineProps:传递props (子组件接收数据
如果我们正在构建一个博客,我们可能需要一个表示博客文章的组件。我们希望所有的博客文章分享相同的视觉布局,但有不同的内容。要实现这样的效果自然必须向组件中传递数据,例如每篇文章标题和内容,这就会使用到 props。
defineProps:子组建把属性暴露给父组件,父组件向子组件传值,子组件通过defineProps接收
案例一:
子组件:Comp.vue
子组件接收父组件传过来的title,然后渲染到页面
<template>
<h4 style='color:red'>{{ title }}</h4>
</template>
<script setup>
defineProps(['title'])
</script>
//或者写成
<template>
<h4 style='color:red'>{{ props.title }}</h4>
</template>
<script setup>
const props = defineProps(['title'])
</script>
父组件:
<template>
<Comp :title=mss></Comp>
</template>
<script setup>
import {ref} from 'vue'
import Comp from './Comp.vue'
const mss=ref(111)
</script>
案例二:
子组件:Comp.vue
子组件还可以加上类型的定义
<template>
<p>拿到父组件传过来的:{{ son2 }}</p>
</template>
<script setup>
//接收父组件传过来的
defineProps({
son2:String
})
</script>
父组件:
父组件传的值必须是string类型,否则会警告
<template>
<Comp :son2=son2></Comp>
</template>
<script setup>
import {ref} from 'vue'
import Comp from './Comp.vue'
const son2=ref('111')
</script>
案例三:
在实际应用中,我们可能在父组件中会有如下的一个博客文章数组
const posts = ref([
{ id: 1, title: 'My journey with Vue' },
{ id: 2, title: 'Blogging with Vue' },
{ id: 3, title: 'Why Vue is so fun' }
])
子组件:BlogPost.vue
<script setup>
defineProps(['title'])
</script>
<template>
<h4>{{ title }}</h4>
</template>
父组件:
<template>
<BlogPost
v-for="item in titleData"
:key="item.id"
:title="item.title"
></BlogPost>
</template>
<script setup>
import { ref } from 'vue'
import BlogPost from './BlogPost.vue'
const titleData = ref([
{ id: 1, title: 'My journey with Vue' },
{ id: 2, title: 'Blogging with Vue' },
{ id: 3, title: 'Why Vue is so fun' }
])
</script>
shopadmin:
到时候父组件可能会用到这些属性,用的时候传值给子组件
其实elementui自带的不是这种动态的,只不过封装起来方便使用,所以采用这种动态封装的方法
这些属性可以去翻阅elementui查看是干嘛的,是ui自带的,改成动态的了
2.defineExpose (子传父
使用 <script setup>
的组件是默认关闭的——即通过模板引用或者 $parent
链获取到的组件的公开实例,不会暴露任何在 <script setup>
中声明的绑定。所以需要把子组建的属性暴露出去。
defineExpose:把子组建的属性暴露出去(我的理解是方法
案例一:
子组件定义自己的属性:
<template>
<div>子组件helloword.vue</div>
</template>
<script setup>
import { ref } from 'vue'
const count = ref(123456)
defineExpose({
count
})
</script>
父组件接收:
在子组件上绑定ref(ref叫什么不重要,自定义的),然后初始值一般都传一个null,调用的时候调用子组件的value.属性就可以了
<template>
<div @click="helloClick">父组件</div>
<helloword ref="hello"></helloword>
</template>
<script setup>
import { ref } from 'vue'
import helloword from './components/HelloWorld.vue'
const hello = ref(null)
const helloClick = () => {
console.log(hello.value.count) // 123456
}
</script>
案例二:
子组件:MyComponent.vue
<template>
<div>
<slot name="a" :text="sonText" :count="5"></slot>
</div>
</template>
<script setup>
import {ref} from 'vue';
const sonText = ref('hello');
const ran=ref(0);
setInterval(()=>{
sonText.value="oh"+ran.value;
ran.value++;
},1000)
//给父组件传递
defineExpose({
sonText
})
</script>
这里补充一下slot,slot没有什么实质性意义,就是充当组件,接收模板片段。具有更多的属性,能够接收任意类型的 JavaScript 值作为 props。
组件的最大特性就是 重用 ,而用好插槽能大大提高组件的可重用能力
插槽的作用:父组件向子组件传递内容。
通俗的来讲,插槽无非就是在 子组件 中挖个坑,坑里面放什么东西由 父组件 决定
比如这里的name,text,count都是自定义的,写上slot就具有这个属性了。
defineEmits:子组件向父组件传递事件
子组件去绑定事件:
<el-button @click="$emit('edit')" />
//暴露出去
defineEmits(["edit"])
父组件调用:
<template>
<AsideList :active="activetab == item.id" v-for="(item, index) in tabList"
:key="index" @edit="handleEdit(item)">
//这里是edit是因为暴露出来的事件就叫edit,然后传进去item,这样点击之后能拿到item
{{ item.name }}
</AsideList>
</template>
<script setup>
import AsideList from './AsideList.vue';
//这样就能点击到子组件了
const handleEdit=(row)=>{
console.log(row)
console.log('点击')
}