// 父组件 add-song.vue
// 添加歌曲模板 <template> <transition name="slide"> <div class="add-song" v-show="showFlag" @click.stop> <div class="header"> <h1 class="title">添加歌曲到列表</h1> <div class="close" @click="hide"> <i class="icon-close"></i> </div> </div> <div class="search-box-wrapper"> <search-box ref="searchBox" @query="onQueryChange" placeholder="搜索歌曲" ></search-box> </div> <div class="shortcut" v-show="!query"> <switches :switches="switches" :currentIndex="currentIndex" @switch="switchItem" ></switches> <div class="list-wrapper"> <scroll class="list-scroll" ref="songList" v-if="currentIndex===0" :data="playHistory" > <div class="list-inner"> <song-list :songs="playHistory" @select="selectSong"></song-list> </div> </scroll> <scroll class="list-scroll" ref="searchList" v-if="currentIndex===1" :data="searchHistory" > <div class="list-inner"> <search-list :searches="searchHistory" @select="addQuery" @delete="deleteSearchHistory" ></search-list> </div> </scroll> </div> </div> <div class="search-result" v-show="query"> <suggest :query="query" :showSinger="showSinger" @select="selectSuggest" @listScroll="blurInput" ></suggest> </div> <top-tip ref="topTip"> <div class="tip-title"> <i class="icon-ok"></i> <span class="text">1首歌曲已经添加到播放列表</span> </div> </top-tip> </div> </transition> </template> <script> // 搜索框组件 import SearchBox from ‘base/search-box/search-box‘ // 切换组价 import Switches from ‘base/switches/switches‘ // 滚动组件 import Scroll from ‘base/scroll/scroll‘ // 歌单 import SongList from ‘base/song-list/song-list‘ import {mapGetters, mapActions} from ‘vuex‘ import Song from ‘common/js/song‘ import SearchList from ‘base/search-list/search-list‘ // 搜素结果模板 import Suggest from ‘components/suggest/suggest‘ import TopTip from ‘base/top-tip/top-tip‘ export default{ data() { return { showFlag: false, currentIndex: 0, switches: [ {name: ‘最近播放‘}, {name: ‘最近搜索‘} ], query: ‘‘, // 不显示歌手 showSinger: false } }, computed: { ...mapGetters([ ‘playHistory‘, ‘searchHistory‘ ]) }, methods: { // 将search-box中的input给blur(失去焦点事件),隐藏输入框 blurInput() { // 父组件通过$refs调用子组件searchBox的blur()方法 this.$refs.searchBox.blur() }, // 保存搜索历史 saveSearch() { // 通过mapActions调用saveSearchHistory()来对state进行修改,完成存储 this.saveSearchHistory(this.query) }, // 选择搜索表中歌曲 selectSuggest() { // 保存搜索历史 this.saveSearch() // 提示框 this.$refs.topTip.show() }, // 监听search-box中query变化,并将变化值传递给add-song然后发送给suggest并请求数据 onQueryChange(query) { this.query = query }, // 将搜索历史加入搜索框 addQuery(query) { this.$refs.searchBox.setQuery(query) }, selectSong(song, index) { if (index !== 0) { // 此处song是从缓存中读取出来的,不是对象需要实例化也就是new this.insertSong(new Song(song)) this.$refs.topTip.show() } }, // 将索引传给currentIndex并传给子组件 switchItem(index) { this.currentIndex = index }, show() { this.showFlag = true // 点开页面时,刷新页面,scroll重新计算,然后就可以滚动了 if (this.currentIndex === 0) { this.$refs.songList.refresh() } else { this.$refs.searchList.refresh() } }, hide() { this.showFlag = false }, ...mapActions([ ‘insertSong‘, ‘deleteSearchHistory‘, ‘saveSearchHistory‘ ]) }, components: { SearchBox, Switches, Scroll, SongList, SearchList, Suggest, TopTip } } </script> <style lang="scss" scoped> @import "./add-song.scss"; </style>
// 子组件switches.vue
// 切换模块 <template> <ul class="switches"> <li class="switch-item" :class="{‘active‘ : currentIndex === index}" v-for="(item, index) in switches" @click="switchItem(index)" > <span>{{item.name}}</span> </li> </ul> </template> <script> export default{ props: { switches: { type: Array, default: [] }, currentIndex: { type: Number, default: 0 } }, methods: { switchItem(index) { // 将点击将索引发给父组件 this.$emit(‘switch‘, index) } } } </script> <style lang="scss" scoped> @import "./switches"; </style>
父传子:(本页数据存储一般放在data()中,接受的父组件的数据一般放在props)将data()中的switches数据通过数据绑定(左侧为绑定数据的名称):switches="switches”(右侧为绑定的数据)传给子组件switches,用props来接受数据(通过传来的数据名)
子传父:将点击开关模块对应的下角标传递给父组件,this.$emit(‘switch‘,index)通过emit发射switch事件,在父组件中通过(左侧为接受子组件发送过来的事件)@switch="switchItem"(右侧为父组件定义的方法名)
模块切换实现原理:
主要通过下角标来控制切换后的样式,事件
先将子组件要显示的switches数据通过绑定的方式传给子组件switches,v-for将数据渲染到页面并获得每个item的index,当点击每个item时,会获得当前点击item的下角标currentIndex,将currentIndex传给父组件,通过v-if ="currentIndex===0",v-if="currentIndex===1"来控制页面显示,将currentIndex通过数据绑定再传给子组件switches,通过class绑定的方法来控制样式的变化:class=“‘active’: currentIndex === index”(在样式scss中,先写好active样式)
// switches.scss样式
@import "~common/scss/variable";
.switches{
display: flex;
align-items: center;
width: 240px;
margin: 0 auto;
border: 1px solid $color-highlight-background;
border-radius: 5px;
.switch-item{
flex: 1;
padding: 8px;
text-align: center;
font-size: $font-size-medium;
color: $color-text-d;
&.active{
background: $color-highlight-background;
color: $color-text;
}
}
}