1. 父组件给子组件传值
父组件App.vue
<template>
<div>
父级
</div>
<waterFallVue :title="name"></waterFallVue>
</template>
<script setup lang="ts">
import waterFallVue from './components/waterFall.vue'
let name = 'uzi'
</script>
<style lang="scss" scoped></style>
子组件waterFall.vue
<template>
<div>
子级
</div>
<div>
接收值:{{ title }}
</div>
<div>
接收数组:{{ arr }}
</div>
</template>
<script setup lang="ts">
// 1.不使用ts
//接受父组件传过来的值,没有传入则使用默认值
// const props = defineProps({
// title: {
// type: String,
// default: '默认值'
// }
// })
// // console.log(title); 直接使用会报错
// console.log(props.title);//使用props接受才可以使用传入的值
// 2.使用ts
//接受父组件传过来的值,没有传入则使用默认值
//ts特有定义默认值 withDefaults函数,接收definProps和默认值对象
withDefaults(defineProps<{
title: string,
arr: number[]
}>(),{
arr:()=> [666]
})
</script>
<style lang="scss" scoped></style>
2. 子组件给父组件传值
父组件App.vue
<template>
<div>
父级
</div>
<waterFallVue @on-click="getName" :title="name"></waterFallVue>
</template>
<script setup lang="ts">
import waterFallVue from './components/waterFall.vue'
let name = 'zitai'
const getName = (name:string) => {
console.log(name, '==> 子组件传值给父组件');
}
</script>
<style lang="scss" scoped></style>
子组件waterFall.vue
<template>
<div>
子级
</div>
<button @click="send">给父组件传值</button>
</template>
<script setup lang="ts">
//不用ts
//给父组件传值 defineEmits
// const emit = defineEmits(['on-click'])
// const send = () => {
// emit('on-click', 'uzi')
// }
//用ts
//给父组件传值 defineEmits
const emit = defineEmits<{
(e: "on-click", name: string): void
}>()
const send = () => {
emit('on-click', 'uzi')
}
</script>
<style lang="scss" scoped></style>
3. 子组件给父组件暴露方法或者属性
父组件App.vue
<template>
<div>
父级
</div>
<waterFallVue ref="waterFall"></waterFallVue>
</template>
<script setup lang="ts">
import { ref,onMounted } from 'vue';
import waterFallVue from './components/waterFall.vue'
const waterFall = ref<InstanceType<typeof waterFallVue>>()
// setup 函数在组件生命周期中是在组件实例创建之前执行的,因此为了避免name和open出现undefined,需将他们挂载到onMounted中
onMounted(() => {
console.log(waterFall.value?.name);
const openFunc = waterFall.value?.open
openFunc()
})
</script>
<style lang="scss" scoped></style>
子组件waterFall.vue
<template>
<div>
子级
</div>
</template>
<script setup lang="ts">
defineExpose({
name:'xiaohu',
open:()=>console.log('暴露方法')
})
</script>
<style lang="scss" scoped></style>
4. 小案例(封装瀑布流组件)
父组件App.vue
<template>
<waterFallVue :list="list"></waterFallVue>
</template>
<script setup lang='ts'>
import waterFallVue from './components/waterFall.vue';
const list = [
{
height: 300,
background: 'red'
},
{
height: 400,
background: 'pink'
},
{
height: 500,
background: 'blue'
},
{
height: 200,
background: 'green'
},
{
height: 300,
background: 'gray'
},
{
height: 400,
background: '#CC00FF'
},
{
height: 200,
background: 'black'
},
{
height: 100,
background: '#996666'
},
{
height: 500,
background: 'skyblue'
},
{
height: 300,
background: '#993366'
},
{
height: 100,
background: '#33FF33'
},
{
height: 400,
background: 'skyblue'
},
{
height: 200,
background: '#6633CC'
},
{
height: 300,
background: '#666699'
},
{
height: 300,
background: '#66CCFF'
},
{
height: 300,
background: 'skyblue'
},
{
height: 200,
background: '#CC3366'
},
{
height: 200,
background: '#CC9966'
},
{
height: 200,
background: '#FF00FF'
},
{
height: 500,
background: '#990000'
},
{
height: 400,
background: 'red'
},
{
height: 100,
background: '#999966'
},
{
height: 200,
background: '#CCCC66'
},
{
height: 300,
background: '#FF33FF'
},
{
height: 400,
background: '#FFFF66'
},
{
height: 200,
background: 'red'
},
{
height: 100,
background: 'skyblue'
},
{
height: 200,
background: '#33CC00'
},
{
height: 300,
background: '#330033'
},
{
height: 100,
background: '#0066CC'
},
{
height: 200,
background: 'skyblue'
},
{
height: 100,
background: '#006666'
},
{
height: 200,
background: 'yellow'
},
{
height: 300,
background: 'yellow'
},
{
height: 100,
background: '#33CCFF'
},
{
height: 400,
background: 'yellow'
},
{
height: 400,
background: 'yellow'
},
{
height: 200,
background: '#33FF00'
},
{
height: 300,
background: 'yellow'
},
{
height: 100,
background: 'green'
}
]
</script>
<style lang='less'>
#app,
html,
body {
height: 100%;
}
* {
padding: 0;
margin: 0;
}
</style>
子组件waterFall.vue
<template>
<div class="wraps">
<div :style="{ height: item.height + 'px', background: item.background, top: item.top + 'px', left: item.left + 'px' }"
v-for="item in waterList" class="items"></div>
</div>
</template>
<script setup lang='ts'>
import { reactive, onMounted } from 'vue'
const props = defineProps<{
list: any[]
}>()
const waterList = reactive<any[]>([])
const init = () => {
const heightList: any[] = []
const width = 130;
const x = document.body.clientWidth
const column = Math.floor(x / width)
for (let i = 0; i < props.list.length; i++) {
if (i < column) {
props.list[i].top = 10;
props.list[i].left = i * width;
heightList.push(props.list[i].height + 10)
waterList.push(props.list[i])
} else {
let current = heightList[0]
let index = 0;
heightList.forEach((h, inx) => {
if (current > h) {
current = h;
index = inx;
}
})
console.log(current, 'c')
props.list[i].top = (current + 20);
console.log(props.list[i].top, 'top', i)
props.list[i].left = index * width;
heightList[index] = (heightList[index] + props.list[i].height + 20);
waterList.push(props.list[i])
}
}
console.log(props.list)
}
onMounted(() => {
window.onresize = () => init()
init()
})
</script>
<style scoped lang='less'>
.wraps {
position: relative;
height: 100%;
.items {
position: absolute;
width: 120px;
}
}
</style>