子组件(字母A/B/C)
Alphabet.vue
<template> <ul class="list"> <!-- <li class="item" v-for="(item,key) of cities" :key="key" @click="handleLetterClick" @touchstart="handleTouchStart" @touchmove="handleTouchMove" @touchend="handleTouchEnd" >{{key}}</li> --> <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> // 引入better-scroll插件 import Bscroll from ‘better-scroll‘ export default{ name:‘CityAlphabet‘, props:{ cities:Object }, // 计算属性 computed:{ // 先定义一个数组。letters=[‘A‘,‘B‘,‘C‘] letters(){ const letters = [] for(let i in this.cities){ letters.push(i) } return letters // [‘A‘,‘B‘,‘C‘] } }, data(){ return { touchStart:false } }, methods:{ handleLetterClick(e){ console.log(e.target.innerText); // 打印点击的字母 // 子组件传值给父组件。向外触发事件。父组件监听。 this.$emit(‘change‘,e.target.innerText) }, // 监听左边城市的滚动。 handleTouchStart (){ // 手指触摸 this.touchStart=true }, handleTouchMove (e){ /* 1.a到顶部的高度. 2.当前滑动到哪的位置与顶部的高度。注意:要减去header的高度. 3.算出两个值之间的差值。除以每个字母的高度。算出当前是第几个字母。 4.获取到字母,触发自定义事件。传值给父级,父级再传值给兄弟组件。 */ const startY = this.$refs[‘A‘][0].offsetTop; // 1.a到顶部的高度 // console.log(startY); const touchY = e.touches[0].clientY - 79; // 2.当前滑动到哪的位置与顶部的高度。注意:要减去header的高度. // console.log(touchY); const index = Math.floor((touchY - startY)/20); // 3.算出两个值之间的差值。除以每个字母的高度。算出当前是第几个字母。 // console.log(index); if(index >= 0 && index < this.letters.length){ this.$emit(‘change‘, this.letters[index]); } }, handleTouchEnd (){ // 结束滑动 this.touchStatus = false; } } } </script> <style lang="stylus" scoped> @import ‘~styles/varibles.styl‘ .list display:flex flex-direction:column justify-content:center position:absolute top:1.58rem right:0 bottom:0 width:.4rem .item line-height:.4rem text-align:center color:$bgColor </style>
父组件
City.vue
<template> <div> <city-header></city-header> <city-search></city-search> <city-list :hotCities="hotCities" :cities="cities" :letter="letter" > </city-list> <city-alphabet :cities="cities" @change="handleLetterChange" > </city-alphabet> </div> </template> <script> // ajax工具 import axios from ‘axios‘ // 引入子组件 import CityHeader from ‘./components/Header‘ import CitySearch from ‘./components/Search‘ import CityList from ‘./components/List‘ import CityAlphabet from ‘./components/Alphabet‘ export default{ name:‘City‘, // 组件 components:{ CityHeader, CitySearch, CityList, CityAlphabet }, data(){ return { // 热门城市 hotCities:[], // 城市 cities:{}, letter:‘‘ } }, // 函数 methods:{ getCityInfo(){ axios.get(‘/api/city.json‘) .then(this.handleGetCityInfoSucc) }, handleGetCityInfoSucc(res){ console.log(res); res = res.data; if (res.ret && res.data){ const data = res.data this.hotCities = data.hotCities this.cities = data.cities } }, // 父组件监听子组件自定义事件。 handleLetterChange(letter){ console.log(‘父组件接收到了letter:‘,letter); // 父组件接收到子组件接收到的数据。 // 父组件再通过属性传递给另一个子组件。 this.letter = letter } }, //dom加载完成 mounted (){ this.getCityInfo() } } </script> <style lang="stylus" scopend> </style>
兄弟组件(展示城市)
List.vue
<template> <div class="list" ref="wrapper"> <div> <div class="area"> <div class="title border-topbottom">当前城市</div> <div class="button-list"> <div class="button-wrapper"> <div class="button">北京</div> </div> </div> </div> <div class="area"> <div class="title border-topbottom">热门城市</div> <div class="button-list"> <div class="button-wrapper" v-for="item of hotCities" :key="item.id"> <div class="button">{{item.name}}</div> </div> </div> </div> <div class="area" v-for="(item,key) of cities" :key="key" :ref="key" > <div class="title border-topbottom">{{key}}</div> <div class="item-list"> <div class="item border-bottom" v-for="innerItem of item" :key="innerItem.id" >{{innerItem.name}}</div> </div> </div> </div> </div> </template> <script> // 引入better-scroll插件 import Bscroll from ‘better-scroll‘ export default{ name:‘CityList‘, props:{ hotCities:Array, cities:Object, letter: String }, // dom挂载完毕之后执行. mounted(){ // ref="wrapper" ref可以帮我们获取dom. this.scroll = new Bscroll(this.$refs.wrapper) }, // 侦听器 watch:{ // 监听letter的变化。 letter(){ // console.log(‘兄弟组件收到了letter:‘,this.letter) if(this.letter){ // 点击到哪个字母,div区域就显示哪一块内容。$refs[key] const element = this.$refs[this.letter][0]; // 注意:这是一个数组。不是一个元素。不能直接传给滚动对象。后面加一个0就好了。 console.log(element); this.scroll.scrollToElement(element); // 传的参数必须是dom元素。 } } } } </script> <style lang="stylus" scoped> .border-topbottom &:before border-color:#ccc &:after border-color:#ccc .border-bottom &:before border-color:#ccc .list overflow:hidden position:absolute top:1.58rem left:0 right:0 bottom:0 .title line-height:.54rem background:#eee padding-left:.2rem color:#666 font-size:.26rem .button-list overflow:hidden padding:.1rem .6rem .1rem .1rem .button-wrapper float:left width:33.33% .button margin:.1rem padding:.1rem 0 text-align:center border:.02rem solid #ccc border-radius:.06rem .item-list .item line-height:.76rem padding-left:.2rem </style>
原文地址:https://www.cnblogs.com/c-x-m/p/10047014.html
时间: 2024-10-30 08:39:45