一、背景需求
在城市列表页面中,我们希望通过导航条完成以下2项功能:
1、 点击字母,定位到以该字母开头的城市区域
2、 在垂直方向拖动导航条,根据鼠标(手指)所在的字母 定位到相应区域
页面的静态布局如下图:
二、兄弟组件的数据传递
字母导航条所在的子组件为 Alphabet,城市列表所在的子组件为 List
想要通过点击字母、定位到相应区域
就需要 Alphabet 传递数据给 List
由于他们具有相同的父组件(即页面根组件)
因此我们采用子组件->父组件->子组件的路径传递数据
具体的实现思路如下:
1、为导航条绑定点击事件
// Alphabet.vue模板
<template>
<ul class="list">
<li class="item"
v-for="item of letters"
:key="item"
:ref="item"
@click="handleLetterClick"
>
{{item}}
</li>
</ul>
</template>
2、当导航条被点击时,向外触发change事件,并以字符串形式传递被点击的字母
methods: {
handleLetterClick (event) {
this.$emit('change', event.target.innerText)
}
3、父组件监听change事件
// 父组件模板
<template>
<div>
<city-header></city-header>
<city-search></city-search>
<city-list
:cities="cities"
:hotCities="hotCities"
:letter="letter"
></city-list>
<city-alphabet
:cities="cities"
@change="handleLetterChange"
></city-alphabet>
</div>
</template>
4、当监听到change事件时,将接收的数据传递给城市列表所在的子组件
// 父组件脚本
export default {
name: 'City',
components: {
CityHeader,
CitySearch,
CityList,
CityAlphabet
},
data () {
return {
cities: {},
hotCities: [],
letter: ''
}
},
methods: {
handleLetterChange (letter) {
this.letter = letter
}
}
}
5、城市列表所在的子组件接收数据,通过scrollToElement方法定位
// List子组件脚本
<script>
import BScroll from 'better-scroll'
export default {
name: 'CityList',
props: {
cities: Object,
hotCities: Array,
letter: String
},
mounted () {
this.scroll = new BScroll(this.$refs.wrapper)
},
watch: {
letter () {
if (this.letter) {
const element = this.$refs[this.letter][0]
this.scroll.scrollToElement(element)
}
}
}
}
</script>
第二项功能的实现请参考下一篇文章