waahah 发表于 2023-11-18 20:12

vue组件问题求助大佬

求助**大佬**,我想把*audio*做成一个组件,*ulli*做成一个组件,*button*做成一个组件,其中*musicData*由ulli组件的created()钩子函数生成并挂载到vm实例data上,button组件为具名组件,该怎么写?最好有完整的代码,谢谢
```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script src="./js/v2.6.10/vue.js"></script>
    <style>
      *{
            padding: 0;
            margin: 0;
      }
      ul{
            list-style: none;
      }
      ul li{
            margin: 20px;
            padding: 10px 5px;
            border-radius: 3px;
      }
      ul li.active{
            background-color: #d2e2f3;
      }
    </style>
</head>
<body>
    <div id="app">
      <audio :src="currentMusicSrc" ref="audio" @pause="" @play="" @ended="handleNext(currentIndex)" autoplay controls ></audio>
      <div>
            <ul >
                <li :class="{active: index === currentIndex}" v-for="(item, index) in musicData" :key="item.id" @click="handleClick(item.songSrc, index)">
                  <h2>{{item.id}}-歌名:{{item.name}}</h2>
                  <p>{{item.author}}</p>
                </li>
            </ul>
            <button @click="handleNext(currentIndex)">>>下一首</button>
            <button @click="handleRandom()">随机播放</button>
            <button @click="handlePlay()">{{isPlaying ? '⏸' : '▶'}} </button>
            <button @click="handleLast(currentIndex)">上一首<<</button>
      </div>
    </div>

    <script>
      const musicData = [
            {
            id: 1,
            name: "于荣光 - 少林英雄",
            author: "于荣光",
            songSrc: "./static/于荣光 - 少林英雄.mp3",
            },
            {
            id: 2,
            name: "Joel Adams - Please Dont Go",
            author: "Joel Adams",
            songSrc: "./static/Joel Adams - Please Dont Go.mp3",
            },
            {
            id: 3,
            name: "MKJ - Time",
            author: "MKJ",
            songSrc: "./static/MKJ - Time.mp3",
            },
            {
            id: 4,
            name: "Russ - Psycho (Pt. 2)",
            author: "Russ",
            songSrc: "./static/Russ - Psycho (Pt. 2).mp3",
            },
      ];

      const vm = new Vue({
            el: "#app",
            data() {
                return {
                  musicData,
                  currentMusicSrc: musicData.songSrc,
                  currentIndex: 0,
                  isPlaying : true
                };
            },
            methods: {
                handleClick(src, index) {
                  this.currentMusicSrc = src;
                  this.currentIndex = index;
                },
                handleNext(currentIndex) {
                  currentIndex += 1;
                  if(currentIndex >= musicData.length) {
                        currentIndex = 0;
                  }
                  this.currentMusicSrc = musicData.songSrc;
                  this.currentIndex = currentIndex;
                },
                handleLast(currentIndex) {
                  currentIndex -= 1;
                  if(currentIndex < 0) {
                        currentIndex = musicData.length - 1;
                  }
                  this.currentMusicSrc = musicData.songSrc;
                  this.currentIndex = currentIndex;
                },
                selectFrom(startNumber, endNumber) {
                  const choice = endNumber - startNumber + 1;
                  return Math.floor(Math.random() * choice + startNumber)
                },
                handleRandom() {
                  const randomIndex = this.selectFrom(0, musicData.length - 1);
                  this.currentMusicSrc = musicData.songSrc;
                  this.currentIndex = randomIndex;
                  console.log(`随机index:${randomIndex}-${musicData.name}`);
                },
               
                paly: function() {
                  this.isPlaying = true;
                  //// 数据改变 DOM 还没有更新
                  this.$nextTick(() => {
                        //在修改数据之后立即使用这个方法,获取更新后的 DOM
                        this.$refs.audio.play();
                  })
                },
                pause: function() {
                  this.isPlaying = false;
                  this.$nextTick(() => {
                        this.$refs.audio.pause();
                  })
                },
                handlePlay() {
                  if(!this.isPlaying) {
                        this.paly();
                  } else {
                        this.pause();
                  }
                }
            }
      });
    </script>

</body>
</html>

```

yushuai033X 发表于 2023-11-18 20:38

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script src="./js/v2.6.10/vue.js"></script>
    <style>
      *{
            padding: 0;
            margin: 0;
      }
      ul{
            list-style: none;
      }
      ul li{
            margin: 20px;
            padding: 10px 5px;
            border-radius: 3px;
      }
      ul li.active{
            background-color: #d2e2f3;
      }
    </style>
</head>
<body>
    <div id="app">
      <audio-player :src="currentMusicSrc"></audio-player>
      <music-list :musicData="musicData" :currentIndex="currentIndex" @select-music="handleClick"></music-list>
      <button-bar @next="handleNext" @last="handleLast" @random="handleRandom" @play="handlePlay" :isPlaying="isPlaying"></button-bar>
    </div>
   
    <template id="audio-player">
      <audio :src="src" ref="audio" @pause="" @play="" @ended="handleNext(currentIndex)" autoplay controls ></audio>
    </template>
   
    <template id="music-list">
      <ul>
            <li :class="{active: index === currentIndex}" v-for="(item, index) in musicData" :key="item.id" @click="handleClick(item.songSrc, index)">
                <h2>{{item.id}}-歌名:{{item.name}}</h2>
                <p>{{item.author}}</p>
            </li>
      </ul>
    </template>
   
    <template id="button-bar">
      <div>
            <button @click="$emit('next')">>>下一首</button>
            <button @click="$emit('random')">随机播放</button>
            <button @click="$emit('play')">{{isPlaying ? '⏸' : '▶'}} </button>
            <button @click="$emit('last')">上一首<<</button>
      </div>
    </template>

    <script>
      const musicData = [
            {
            id: 1,
            name: "于荣光 - 少林英雄",
            author: "于荣光",
            songSrc: "./static/于荣光 - 少林英雄.mp3",
            },
            {
            id: 2,
            name: "Joel Adams - Please Dont Go",
            author: "Joel Adams",
            songSrc: "./static/Joel Adams - Please Dont Go.mp3",
            },
            {
            id: 3,
            name: "MKJ - Time",
            author: "MKJ",
            songSrc: "./static/MKJ - Time.mp3",
            },
            {
            id: 4,
            name: "Russ - Psycho (Pt. 2)",
            author: "Russ",
            songSrc: "./static/Russ - Psycho (Pt. 2).mp3",
            },
      ];

      Vue.component('audio-player', {
            template: '#audio-player',
            props: ['src'],
            methods: {
                handleNext(currentIndex) {
                  currentIndex += 1;
                  if(currentIndex >= musicData.length) {
                        currentIndex = 0;
                  }
                  this.$refs.audio.src = musicData.songSrc;
                  this.$emit('next', currentIndex);
                }
            }
      });

      Vue.component('music-list', {
            template: '#music-list',
            props: ['musicData', 'currentIndex'],
            methods: {
                handleClick(src, index) {
                  this.$emit('select-music', src, index);
                }
            }
      });

      Vue.component('button-bar', {
            template: '#button-bar',
            props: ['isPlaying'],
            methods: {
                handleNext() {
                  this.$emit('next');
                },
                handleLast() {
                  this.$emit('last');
                },
                handleRandom() {
                  this.$emit('random');
                },
                handlePlay() {
                  this.$emit('play');
                }
            }
      });

      const vm = new Vue({
            el: "#app",
            data() {
                return {
                  musicData,
                  currentMusicSrc: musicData.songSrc,
                  currentIndex: 0,
                  isPlaying : true
                };
            },
            methods: {
                handleClick(src, index) {
                  this.currentMusicSrc = src;
                  this.currentIndex = index;
                },
                handleNext(currentIndex) {
                  currentIndex += 1;
                  if(currentIndex >= musicData.length) {
                        currentIndex = 0;
                  }
                  this.currentMusicSrc = musicData.songSrc;
                  this.currentIndex = currentIndex;
                },
                handleLast(currentIndex) {
                  currentIndex -= 1;
                  if(currentIndex < 0) {
                        currentIndex = musicData.length - 1;
                  }
                  this.currentMusicSrc = musicData.songSrc;
                  this.currentIndex = currentIndex;
                },
                selectFrom(startNumber, endNumber) {
                  const choice = endNumber - startNumber + 1;
                  return Math.floor(Math.random() * choice + startNumber)
                },
                handleRandom() {
                  const randomIndex = this.selectFrom(0, musicData.length - 1);
                  this.currentMusicSrc = musicData.songSrc;
                  this.currentIndex = randomIndex;
                  console.log(`随机index:${randomIndex}-${musicData.name}`);
                },

                paly: function() {
                  this.isPlaying = true;
                  //// 数据改变 DOM 还没有更新
                  this.$nextTick(() => {
                        //在修改数据之后立即使用这个方法,获取更新后的 DOM
                        this.$refs.audio.play();
                  })
                },
                pause: function() {
                  this.isPlaying = false;
                  this.$nextTick(() => {
                        this.$refs.audio.pause();
                  })
                },
                handlePlay() {
                  if(!this.isPlaying) {
                        this.paly();
                  } else {
                        this.pause();
                  }
                }
            }
      });
    </script>

</body>
</html>

在上面的代码中,我创建了三个组件:audio-player用于播放音频,music-list用于显示音乐列表,button-bar用于显示操作按钮。
audio-player组件接收一个src属性,用于指定音乐的地址。当音乐播放结束时,会触发ended事件并调用handleNext方法切换到下一首音乐。
music-list组件接收两个属性:musicData用于显示音乐列表,currentIndex用于标记当前选中的音乐。当点击某一首音乐时,会调用handleClick方法并触发select-music事件,将选中的音乐地址和索引传递给父组件。
button-bar组件接收一个isPlaying属性,用于标记当前音乐是否正在播放。当点击不同的按钮时,会分别触发next、last、random、play事件,将操作类型传递给父组件。
在App组件中,我使用了这三个组件,并在对应的事件处理方法中更新了currentMusicSrc和currentIndex的值。

abigmiu 发表于 2023-11-18 22:55

yushuai033X 发表于 2023-11-18 20:38





这是用 gpt 生成的?
页: [1]
查看完整版本: vue组件问题求助大佬