Left and right linkage provide, inject+props, emit

Achieve results

Chengdu Big Screen – Video Management
Both the left and right are components, so it involves the parent component passing data to multiple child components.

Method 1 provide, inject

Directory Structure

Parent component index.vue
Methods to pass data and modify data using provide

import {<!-- --> provide} from "vue";
provide("Provide_SelectedVideo", {<!-- -->
  videoList,
  selectedVideoFileName,
  handleChangeVideoFileName,
});

Complete code:

<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: "Shuangyong Road", videoName: "video1.mp4" },
  {<!-- --> name: "Huangang Road Section 2", videoName: "video2.mp4" },
  {<!-- --> name: "Guangmu Road", videoName: "video3.mp4" },
  {<!-- --> name: "Eastern Section of Muxing Road", videoName: "video4.mp4" },
  {<!-- --> name: "Hangzhi Road", videoName: "video5.mp4" },
  {<!-- --> name: "Hangchuang Road", videoName: "video6.mp4" },
]);
const handleChangeVideoFileName = (newVideoName) => {<!-- -->
  selectedVideoFileName.value = newVideoName;
};

provide("Provide_SelectedVideo", {<!-- -->
  videoList,
  selectedVideoFileName,
  handleChangeVideoFileName,
});
</script>

<template>
  <h1>Video management:</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>

Child component VideoList.vue

  1. Add click event to li tag
    Essentially, the method of the parent component is used to modify the data. Therefore, the function of the child component is to pass data to the function of the parent component.
const handleClick = (newVideoName) => {<!-- -->
  handleChangeVideoFileName(newVideoName);
};
  1. Add dynamic style to li tag
 <li
      @click="handleClick(item.videoName)"
      v-for="(item, index) in videoList"
      :key="item.name"
      :class="{ active: selectedVideoFileName === item.videoName }"
    >
      {<!-- -->{<!-- --> item.name }}
    </li>

Or you can write it like this
:class="item.videoName === selectedVideoFileName ? 'list-item selected-item' : 'list-item'"

  1. Accept data through inject
import {<!-- --> inject } from "vue";

const {<!-- --> videoList, selectedVideoFileName, handleChangeVideoFileName } = inject(
  "Provide_SelectedVideo"
);

Complete code:







The sub-component VideoList.vue uses inject in the same way. The complete code:

<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>

Method 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: "Shuangyong Road", videoName: "video1.mp4" },
  {<!-- --> name: "Huangang Road Section 2", videoName: "video2.mp4" },
  {<!-- --> name: "Guangmu Road", videoName: "video3.mp4" },
  {<!-- --> name: "Eastern Section of Muxing Road", videoName: "video4.mp4" },
  {<!-- --> name: "Hangzhi Road", videoName: "video5.mp4" },
  {<!-- --> name: "Hangchuang Road", videoName: "video6.mp4" },
]);
const handleChangeVideoFileName = (newVideoName) => {<!-- -->
  selectedVideoFileName.value = newVideoName;
};
</script>

<template>
  <h1>Video management:</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>

Child component VideoList.vue
Through the emit of the child component, you can also modify the data of the parent component by calling the method of the parent component.

<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>

Child component 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>