父子组件传值
App.vue(父)
<template>
<div>父级</div>
<hr>
<waterFallVue ref="waterFall" @on-click="getName" :arr="[1,2,3]" :title="name"></waterFallVue>
</template>
<script setup lang="ts">
import {ref} from 'vue'
import waterFallVue from './components/water-fall.vue';
const waterFall = ref<InstanceType<typeof waterFallVue>>()
let name = '小满'
waterFall.value.open
// const getName = (name:string) => {
// console.log(name,'============>我是父组件')
// }
</script>
water-fall.vue(子)
<template>
<div>
子集
</div>
<!-- <button @click="send">给父组件传值</button> -->
</template>
<script setup lang="ts">
// 接收父组件传过来的defineProps
// ts 特有定义默认值 withDefaults
// 给父组件传值 defineEmits
// const emit = defineEmits(['on-click'])
/* const emit = defineEmits<{
(e:'on-click',name:string):void
}>()
const send = () => {
emit('on-click','小满')
} */
// withDefaults(defineProps<{
// title:string,
// arr:number[]
// }>(),{
// arr: () => [666]
// })
/* const props = defineProps({
title:{
type:String,
default:"默认值"
}
})
console.log(props.title) */
defineExpose({ //对外暴露,可通过vm(组件实例).value.$s(属性和方法)访问
name:'小满',
open:() => console.log(1)
})
</script>
瀑布布局实例
app.vue
<template>
<div>
<waterFall :list="list" />
</div>
</template>
<script setup lang="ts">
import waterFall from './components/water-fall.vue'
const list = [
{
height: 300,
background: 'red'
},
{
height: 400,
background: 'pink'
},
{
height: 500,
background: 'blue'
},
{
height: 350,
background: 'green'
},
{
height: 100,
background: 'palegreen'
},
{
height: 150,
background: 'paleturquoise'
},
{
height: 80,
background: 'purple'
},
{
height: 50,
background: 'yellowgreen'
},
{
height: 80,
background: 'red'
},
{
height: 160,
background: 'blue'
},
{
height: 90,
background: 'yellowgreen'
},
{
height: 220,
background: 'palegreen'
},
{
height: 170,
background: 'pink'
},
{
height: 360,
background: 'purple'
},
{
height: 410,
background: 'green'
},
{
height: 290,
background: 'yellowgreen'
},
]
</script>
waterFall.vue
<template>
<div class="wraps">
<div class="items" v-for="item in waterList" :style="{height:item.height + 'px',background:item.background,left:item.left + 'px',top:item.top + 'px'}"></div>
</div>
</template>
<script setup lang="ts">
import { onMounted,reactive } from 'vue'
const props = defineProps<{
list:any[]
}>()
const waterList = reactive<any[]>([])
const heightList:number[] = []
const init = () => {
const width = 130
const x = document.body.clientWidth
const column = Math.floor(x / width)
console.log(column)
for (let i = 0; i < props.list.length; i++) {
if (i < column) {
props.list[i].left = i * width + 20
props.list[i].top = 20
waterList.push(props.list[i])
heightList.push(props.list[i].height + 20)
}else{
let current = heightList[0];
let index = 0;
heightList.forEach((h,i) => {
if (current > h) {
current = h;
index = i;
}
})
props.list[i].top = current + 20
props.list[i].left = index * width + 20
heightList[index] = heightList[index] + props.list[i].height + 20
waterList.push(props.list[i])
console.log(index)
}
}
}
onMounted(() => {
init()
})
</script>
<style lang="scss" scoped>
.wraps{
position: relative;
.items{
position: absolute;
width: 120px;
}
}
</style>
运行结果
![](https://img-blog.csdnimg.cn/7c46219facb24af8ac057cdb05cd1737.png)