实现效果
成都大屏 —— 视频管理
左右两个都是组件,所以涉及到父组件向多个子组建传递数据
方法1 provide、inject
目录结构
父组件 index.vue
用provide传递数据和修改数据的方法
import { provide} from "vue";
provide("Provide_SelectedVideo", {
videoList,
selectedVideoFileName,
handleChangeVideoFileName,
});
完整代码:
<script setup>
import { provide, reactive, ref } from "vue";
import VideoList from "./VideoList.vue";
import VideoBox from "./VideoBox.vue";
const selectedVideoFileName = ref("video1.mp4");
const videoList = reactive([
{ name: "双永路", videoName: "video1.mp4" },
{ name: "环港路二段", videoName: "video2.mp4" },
{ name: "广牧路", videoName: "video3.mp4" },
{ name: "牧星路东段", videoName: "video4.mp4" },
{ name: "航志路", videoName: "video5.mp4" },
{ name: "航创路", videoName: "video6.mp4" },
]);
const handleChangeVideoFileName = (newVideoName) => {
selectedVideoFileName.value = newVideoName;
};
provide("Provide_SelectedVideo", {
videoList,
selectedVideoFileName,
handleChangeVideoFileName,
});
</script>
<template>
<h1>视频管理:</h1>
<div class="videomanmge">
<VideoList></VideoList>
<VideoBox></VideoBox>
</div>
</template>
<style scoped lang="scss">
.videomanmge {
display: flex;
width: 500px;
height: 300px;
border: 1px red solid;
}
</style>
子组件 VideoList.vue
- li标签添加点击事件
本质上是使用父组件的方法来修改数据,所以,子组件的函数就是给父组件的函数传数据
const handleClick = (newVideoName) => {
handleChangeVideoFileName(newVideoName);
};
- li标签添加动态样式
<li
@click="handleClick(item.videoName)"
v-for="(item, index) in videoList"
:key="item.name"
:class="{ active: selectedVideoFileName === item.videoName }"
>
{{ item.name }}
</li>
或者这样写也行
:class="item.videoName === selectedVideoFileName ? 'list-item selected-item' : 'list-item'"
- 通过inject接受数据
import { inject } from "vue";
const { videoList, selectedVideoFileName, handleChangeVideoFileName } = inject(
"Provide_SelectedVideo"
);
完整代码:
<script setup>
import { inject } from "vue";
const { videoList, selectedVideoFileName, handleChangeVideoFileName } = inject(
"Provide_SelectedVideo"
);
const handleClick = (newVideoName) => {
handleChangeVideoFileName(newVideoName);
};
</script>
<template>
<ul>
<li
@click="handleClick(item.videoName)"
v-for="(item, index) in videoList"
:key="item.name"
:class="{ active: selectedVideoFileName === item.videoName }"
>
{{ item.name }}
</li>
</ul>
</template>
<style scoped lang="scss">
.active {
background-color: red;
}
</style>
子组件 VideoList.vue 同理使用inject 完整代码:
<script setup>
import { inject } from "vue";
const { selectedVideoFileName } = inject("Provide_SelectedVideo");
</script>
<template>
<div class="videobox">
<div>{{ selectedVideoFileName }}</div>
</div>
</template>
<style scoped lang="scss">
.videobox {
width: 200px;
height: 300px;
border: 1px solid blue;
}
</style>
方法2 props、emit
index.vue
<script setup>
import { reactive, ref } from "vue";
import VideoList from "./VideoList.vue";
import VideoBox from "./VideoBox.vue";
const selectedVideoFileName = ref("video1.mp4");
const videoList = reactive([
{ name: "双永路", videoName: "video1.mp4" },
{ name: "环港路二段", videoName: "video2.mp4" },
{ name: "广牧路", videoName: "video3.mp4" },
{ name: "牧星路东段", videoName: "video4.mp4" },
{ name: "航志路", videoName: "video5.mp4" },
{ name: "航创路", videoName: "video6.mp4" },
]);
const handleChangeVideoFileName = (newVideoName) => {
selectedVideoFileName.value = newVideoName;
};
</script>
<template>
<h1>视频管理:</h1>
<div class="videomanmge">
<VideoList
:list="videoList"
:selectedVideoFileName="selectedVideoFileName"
@changeVideoFileName="handleChangeVideoFileName"
></VideoList>
<VideoBox
:list="videoList"
:selectedVideoFileName="selectedVideoFileName"
></VideoBox>
</div>
</template>
<style scoped lang="scss">
.videomanmge {
display: flex;
width: 500px;
height: 300px;
border: 1px red solid;
}
</style>
子组件 VideoList.vue
通过子组件的emit也可以通过调用父组件的方法来修改父组件的数据
<script setup>
import { defineProps } from "vue";
const props = defineProps({
list: {
type: Array,
default: null,
},
selectedVideoFileName: {
type: String,
default: null,
},
});
const emit = defineEmits(["changeVideoFileName"]);
const handleClick = (newVideoName) => {
emit("changeVideoFileName", newVideoName);
// handleChangeVideoFileName(newVideoName);
};
</script>
<template>
<ul>
<li
@click="handleClick(item.videoName)"
v-for="(item, index) in props.list"
:key="item.name"
:class="{ active: selectedVideoFileName === item.videoName }"
>
{{ item.name }}
</li>
</ul>
</template>
<style scoped lang="scss">
.active {
background-color: red;
}
</style>
子组件 VideoBox.vue
<script setup>
import { defineProps } from "vue";
const props = defineProps({
list: {
type: Array,
default: null,
},
selectedVideoFileName: {
type: String,
default: null,
},
});
</script>
<template>
<div class="videobox">
<div>{{ props.selectedVideoFileName }}</div>
</div>
</template>
<style scoped lang="scss">
.videobox {
width: 200px;
height: 300px;
border: 1px solid blue;
}
</style>