今天的教程内容有点多 我慢慢缕下
要实现的功能: 右边的字母表点击后右边的城市列表页会自动切换到相对应的首字母去
所以列表组件需要知道右边的字母列表的点击事件所对应的元素字母。这就需要兄弟组件的数据传递的实现了
1. 兄弟组件间的数据传递。因为层级结构简单。所以采用的是子组件传递数据给父组件,然后父组件再传递数据给子组件
先说子组件将点击事件发生后对应的字母传递给父组件。
<template>
<ul class="list">
<li
class="item"
v-for="item of letters"
:key="item"
//绑定click事件执行handleLetterClick函数
@click="handleLetterClick"
>
{{item}}
</li>
</ul>
</template>
// 其他就不写 就写这个函数
methods: {
//事件触发后会传递一个event对象。其中包含了点击标签的内容
handleLetterClick (e) {
//发送'change'信号给父组件。带上了标签文本内容
this.$emit('change', e.target.innerText)
}
}
接着父组件接收数据并且传递给list组件。一个转发功能
<template>
<div>
<city-header></city-header>
<city-search></city-search>
<city-list
:cities = "cities"
:hot = "hotCities"
//3. 然后再传递给子组件
:letter = "letter"
></city-list>
<city-alphabet
:cities="cities"
//1. 其他不管就这个。监听change事件,调用handleLetterChange函数
@change="handleLetterChange"
></city-alphabet>
</div>
</template>
data () {
return {
cities: {},
hotCities: [],
letter: ''
}
}
//2. 将子组件的数据复制给letter变量
handleLetterChange (letter) {
this.letter = letter
}
list子组件接收到数据之后进行跳转即可完成:
props: {
hot: Array,
cities: Object,
// 1. 就这货接收数据
letter: String
},
mount
//2. 然后使用监听函数watch 监听letter的变化。一旦发生变化就滚动到对应元素的位置
watch: {
letter () {
if (this.letter) {
//4. 根据letter的值跳转到对应ref的标签对象。
const element = this.$refs[this.letter][0]
//5. 利用scrollToElement方法跳转到对应的元素即跳转完成
this.scroll.scrollToElement(element)
}
}
}
<div class="area"
v-for="(item, key) of cities"
:key="key"
//3. 这里将标签对象与key值做绑定
:ref="key"
>
2. 这个是点击字母进行跳转。 还有一种需求是拇指按住字母表滑动,左边的list组件自动跳转。
首先我们要做到监听使用者的手指,啥时候开始点击字母列表、啥时候离开字母列表和啥时候开始滚动。
使用事件监听:
<template>
<ul class="list">
<li
class="item"
//6. 这里改成letters 而不是cities了
v-for="item of letters"
:key="item"
:ref="item"
//1. 手指开始触碰字母列表
@touchstart="handleTouchStart"
//2. 字母开始移动字母列表
@touchmove="handleTouchMove"
//3.字母离开屏幕
@touchend="handleTouchEnd"
//这个是前面的那个监听事件不管他
@click="handleLetterClick"
>
{{item}}
</li>
</ul>
</template>
//4. 使用计算函数 给字母表生成一个数组。等下再定位字母的时候会用到
//同时 template页面也要跟着改
computed: {
letters () {
const letters = []
for (let i in this.cities) {
letters.push(i)
}
return letters
}
},
// 监听的函数具体实现:
data () {
return {
用来判断拇指是否接触了字母列表
touchStatus: false
}
}
handleTouchStart () {
this.touchStatus = true
},
handleTouchMove (e) {
if (this.touchStatus) {
// 7. 先获取到A字母的标签与Header.vue组件下沿的距离
const startY = this.$refs['A'][0].offsetTop
// 8. 然后获取到拇指接触屏幕的高度减去Header.vue组件的高度 获得Header.vue组件下沿与拇指的高度
const touchY = e.touches[0].clientY - 79
// 9. 现货的这两个元素的高度距离之后除以每个字母标签的高度 并去除小数点。 获得字母列表的所在顺序
const index = Math.floor((touchY - startY) / 20)
// 10. 判断字母是不是已经跑出字母表之外了
if (index >= 0 && index < this.letters.length) {
// 11. 将字母列表的所在顺序当做letters的下标 触发兄弟组件传递。完成
this.$emit('change', this.letters[index])
}
}
},
handleTouchEnd () {
this.touchStatus = false
}