先放效果图咯~
思路:如果是同层级兄弟组件B与C之间传值的话,我们可以不用采用bus方法,通过B先向父组件A传值,然后A再向子组件C传值就可以实现。子组件向父组件传值是通过this.$emit('事件名',要传递的参数值)发出事件,然后父组件监听这个事件并进入事件处理程序;父组件向子组件传值是通过属性传值,直接在父组件绑定一个属性,然后子组件在props中接收这个属性参数,就可以进行相应的事件处理了。
- 在开发城市选择页的时候,我想要实现点击右侧字母列表中的字母就可以让左边的城市列表进入对应的字母项,这个时候就用到了兄弟组件的数据传递。
- 好啦!第一步实现上述功能后,接下来要继续实现另一个功能啦~我们想实现在右侧字母表上滑动鼠标时,左侧的城市列表项也会滑到对应字母块的列表项。
思路:我们需要根据鼠标滑动到哪个位置来计算此时鼠标停留的位置对应的字母是什么,因此我们需要计算第一个字母‘A’所在的位置高度startY以及鼠标停留位置的高度touchY,然后通过计算两者之差除以每个字母的高度Math.floor((touchY - this.startY) / 20)即可得到一个位置索引Index,最后根据这个索引就可以去List组件中找到对应项进行显示。
首先在字母列表组件上绑定touchstart、touchmove、touchend三个事件来分别处理鼠标滑动不同状态下的响应。对此,我们需要定义一个标识类 touchStatus,当它值为true的时候才去进行touchMove的一些处理。为了能更方便地获取到字母,我们在计算属性中对cities进行for...in遍历从而得到字母数组letters:['A','B','C',...'Z']。
具体代码实现如下:
<template>
<ul class="list">
<li class="item"
v-for="item of letters"
:key="item"
:ref="item"
@click="handleLetterClick"
@touchstart="handleTouchStart"
@touchmove="handleTouchMove"
@touchend="handleTouchEnd"
>{{item}}</li>
</ul>
</template>
<script>
export default {
name: 'CityAlphabet',
props:{
cities: Object,
},
//for..in遍历输出的就是对象中所有的属性,在这里可以理解为键名
computed:{
letters () {
const letters = [ ]
for( let i in this.cities ) {
letters.push(i)
}
return letters
}
},
data () {
return{
touchStatus: false, //定义一个标识类,当它值为true的时候才去进行touchMove的一些处理
startY :0,
timer:null,
}
},
updated(){
this.startY=this.$refs['A'][0].offsetTop//offsetTop是首字母A距离.list元素顶部的距离
},
methods:{
handleLetterClick (e) {
this.$emit('change', e.target.innerText)
},
handleTouchStart(){
this.touchStatus = true
},
handleTouchMove(e){
if(this.touchStatus ){
if(this.timer){ //函数节流进行性能优化
clearTimeout(this.timer)
}
this.timer=setTimeout( ( ) => {
const touchY = e.touches[0].clientY -79 //e.touches[0]第0项获取的是我们手指的一些信息,clienY获取的是鼠标停止位置距离整个可视区域顶部的距离,减去Header和Search部分的高得到的就是鼠标停止位置距离.list元素顶部的距离
const index = Math.floor((touchY - this.startY) / 20)
if (index >= 0 && index < this.letters.length) {
this.$emit('change', this.letters[index]) //向父组件触发change事件
}
},16)
}
},
handleTouchEnd(){
this.touchStatus = false
}
},
}
</script>
<style lang="stylus" scoped>
@import '~styles/varibles.styl'
.list
display:flex
flex-direction:column
justify-content:center
position:absolute
right:0
bottom:0
top:1.58rem
width:.4rem
.item
line-height:.4rem
text-align:center
color:$bgColor
</style>
今日最大的坑!!!因为我在组件中绑定事件时将函数进行了驼峰命名导致好几个小时程序一直得不到想要的效果~哇~~晚上都快炸了,最终对着老师的视频来回反复仔细看了N遍才发现这个原因,改过来以后程序就对了~你说神奇不神奇,耐不住刨根的性子终于在这篇[vue中v-on后面跟着的函数名不可以用驼峰命名吗?](http://www.caotama.com/98279.html)博客中找到了原因,感谢这位道友为我解了惑吖~
原因:HTML是大小写不敏感的,HTML中的属性@touchStart会被解析为@touchstart,js会通过@touchStart去找,这样当然是找不到的呀。 所以呀,vue中@后的函数名一般都是小写,主要是因为解析的时候大写会被解析成小写,然后 js获取的时候会根据驼峰命名去找就找不到了。