去除fastclick之后有问题

去除fastclick之后有问题

现在当进入到城市列表搜索页时可以滚动,切换主页再切换回来也可以滚动。

但是当点击城市切换城市以后再点进城市列表搜索页后列表就无法滚动了。

click:true都加了,fastclick的文件也都删了

正在回答

登陆购买课程后可参与讨论,去登陆

8回答

同学你好,下方的方式,是针对于better-scroll2.x版本不能滚动的解决方案。同学的better-scroll的版本是1.x,使用下方的方法会对滚动造成影响。

建议:去掉下方代码再测试下。

http://img1.sycdn.imooc.com//climg/5fae423409baae7c02670082.jpg

祝学习愉快~

  • Liiiu 提问者 #1
    完美解决,谢谢老师
    2020-11-14 14:38:44
提问者 Liiiu 2020-11-13 11:54:54

Alphabet.vue

​<template>
<ul class="list">
<li
v-for="item of letters"
:key="item"
:ref="item"
@click="handleClick"
@touchstart="handleTouchStart"
@touchmove="handleTouchMove"
@touchend="handleTouchEnd"
>{{ item }}
</li>
</ul>
</template>

<script>
export default {
name: 'CityAlphabet',
props: {
cities: Object
},
data () {
return {
// 状态码
touchStatus: false,
startY: 0,
// 防抖
timer: null
}
},
computed: {
letters () {
const letters = []
for (let i in this.cities) {
letters.push(i)
}
return letters
}
},
updated () {
// 找到'A'距离顶部的高度,offsetTop是到上级层的高度
// 因为这个高度是固定的,所以不必放在handleTouchMove方法当中
// 在页面完成渲染后执行即可
this.startY = this.$refs['A'][0].offsetTop
},
methods: {
handleClick (e) {
// 向父级元素传递数据
this.$emit('change', e.target.innerHTML)
},
handleTouchStart () {
this.touchStatus = true
},
handleTouchMove (e) {
if (this.touchStatus) {
// 防抖
if (this.timer) {
clearTimeout(this.timer)
}
// 利用8ms延迟实现防抖,大幅度减少方法调用频率
this.timer = setTimeout(() => {
// 记住touches是数组要想获取高度值要加上[0]
// 79是顶部Header组件及Search组件加起来的高度
// clientY是事件触发时的手指高度
const touchY = e.touches[0].clientY - 79
// 触摸高度-'A'距离顶部的高度,结果再除每一个列表项的高度取整,就是用户触摸的列表项
const index = Math.floor((touchY - this.startY) / 20)
// 控制只在此列表内触摸才会触发
if (index >= 0 && index < this.letters.length) {
this.$emit('change', this.letters[index])
}
}, 8)
}
},
handleTouchEnd () {
this.touchStatus = false
}
}
}
</script>

<style lang="stylus" scoped>
@import "~css/varibles.styl"
.list
// 弹性盒子布局,高度居中样式写法
display flex
flex-direction column
justify-content center
position absolute
top 1.58rem
right 0
bottom 0
width .4rem

li
line-height .4rem
text-align center
color $bgColor
</style>


提问者 Liiiu 2020-11-13 11:45:55

Header.vue

​<template>
<div class="header">
城市列表
<router-link to="/">
<div class="iconfont city-back">&#xe624;</div>
</router-link>
</div>
</template>

<script>
export default {
name: 'CityHeader'
}
</script>

<style lang="stylus" scoped>
@import "~css/varibles.styl"
.header
position relative
height $headerHeight
line-height $headerHeight
overflow hidden
text-align center
font-size .32rem
color #fff
background $bgColor
.city-back
position absolute
top 0
left 0
width .64rem
font-size .4rem
text-align center
color $linkTextColor
</style>


提问者 Liiiu 2020-11-13 11:45:27

Search.vue

​<template>
<div>
<div class="search">
<label>
<input
v-model="keyword"
class="search-input"
type="text"
placeholder="输入城市名或拼音"
/>
</label>
</div>
<div class="search-content" ref="search" v-show="keyword">
<ul>
<li
v-for="item of list"
:key="item.id"
class="search-item border-bottom"
@click="handleCityClick(item.name)"
>
{{ item.name }}
</li>
<li class="search-item border-bottom" v-show="hasNoData">没有找到匹配数据</li>
</ul>
</div>
</div>
</template>

<script>
import BScroll from 'better-scroll'
import { mapMutations } from 'vuex'

export default {
name: 'CitySearch',
props: {
cities: Object
},
data () {
return {
keyword: '',
list: [],
timer: null
}
},
computed: {
hasNoData () {
return !this.list.length
}
},
methods: {
handleCityClick (city) {
// 通过commit方法触发vuex修改数据
// 因为此处业务逻辑较简单,所以直接使用commit
// 否则应该使用dispatch方法触发actions容器
// 再通过actions容器触发commit方法
// this.$store.commit('changeCity', city)
// 可使用mapMutations方法简化
this.changeCity(city)
// vue中路由跳转的方法
this.$router.push('/')
},
...mapMutations(['changeCity'])
},
watch: {
keyword () {
if (this.timer) {
clearTimeout(this.timer)
}
if (!this.keyword) {
this.list = []
return
}
// 防抖,优化性能
this.timer = setTimeout(() => {
const result = []
// 遍历对象,找出'A','B'...
for (let i in this.cities) {
// 遍历出数据
this.cities[i].forEach((value) => {
// 中英文数据搜索
if (value.spell.indexOf(this.keyword) > -1 || value.name.indexOf(this.keyword) > -1) {
result.push(value)
}
})
}
this.list = result
}, 100)
}
},
mounted () {
this.scroll = new BScroll(this.$refs.search, {
click: true
})
}
}
</script>

<style lang="stylus" scoped>
@import "~css/varibles.styl"
.search
background $bgColor
padding 0 .1rem
height .72rem

.search-input
// 这里若想使用padding
// 要配合使用属性box-sizing: border-box
box-sizing border-box
padding 0 .1rem
width 100%
height .62rem
line-height .62rem
text-align center
border-radius .06rem
color $darkTextColor

.search-content
position absolute
overflow hidden
top 1.58rem
left 0
right 0
bottom 0
background #eee
z-index 1

.search-item
line-height .62rem
padding-left .2rem
background #fff
color #666
</style>


提问者 Liiiu 2020-11-13 11:44:52

List.vue

​<template>
<!-- 使用ref属性来让Vue获取DOM元素-->
<div class="list" ref="wrapper">
<!-- 此div为了解决符合better-scroll插件要求的DOM结构-->
<div>
<div class="area">
<div class="title border-topbottom">当前城市</div>
<div class="btn-list">
<div class="btn-wrapper">
<!-- 使用vuex获取当前城市数据-->
<div class="btn">{{ this.currentCity }}</div>
</div>
</div>
</div>
<div class="area">
<div class="title border-topbottom">热门城市</div>
<div class="btn-list">
<div class="btn-wrapper"
v-for="item of hotCities"
:key="item.id"
@click="handleCityClick(item.name)"
>
<div class="btn">{{ item.name }}</div>
</div>
</div>
</div>
<!-- 循环遍历对象时,第二项是key,数组则是index-->
<!-- 只要不是在一个循环层级,key值重复也无伤大雅,但尽量避免-->
<div class="area"
v-for="(cityItem, 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="item of cityItem"
:key="item.id"
@click="handleCityClick(item.name)"
>
{{ item.name }}
</div>
</div>
</div>
</div>
</div>
</template>

<script>
import BScroll from 'better-scroll'
import { mapState, mapMutations } from 'vuex'

export default {
name: 'CityList',
props: {
hotCities: Array,
cities: Object,
letter: String
},
computed: {
// mapState也可传入对象
...mapState({
currentCity: 'city'
})
},
// DOM加载完毕后执行
mounted () {
// 通过$refs找到ref属性为wrapper的对应DOM元素
this.scroll = new BScroll(this.$refs.wrapper, {
click: true
})
},
methods: {
handleCityClick (city) {
// 通过commit方法触发vuex修改数据
// 因为此处业务逻辑较简单,所以直接使用commit
// 否则应该使用dispatch方法触发actions容器
// 再通过actions容器触发commit方法
// this.$store.commit('changeCity', city)
// 可使用mapMutations方法简化
this.changeCity(city)
// vue中路由跳转的方法
this.$router.push('/')
},
...mapMutations(['changeCity'])
},
// 解决个别情况无法滚动问题
updated () {
this.scroll.refresh()
},
// 通过watch监听器监听letter的变化
watch: {
letter () {
if (this.letter) {
// 因为scrollToElement方法内部要传入DOM元素
// 通过$refs找到跟列表中一致的元素
// 注意此处要加上.trim方法去掉空格
const element = this.$refs[this.letter.trim()][0]
this.scroll.scrollToElement(element)
}
}
}
}
</script>

<style lang="stylus" scoped>
@import "~css/varibles.styl"
.border-topbottom
&:before
border-color #ccc

&:after
border-color #ccc

.border-bottom
&:before
border-color #ccc

.list
position absolute
overflow hidden
top 1.58rem
left 0
right 0
bottom 0

.title
line-height .54rem
background #eee
padding-left .2rem
color #666
font-size .26rem

.btn-list
padding .1rem .6rem .1rem .1rem
overflow hidden

.btn-wrapper
float left
width 33.3%

.btn
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>


提问者 Liiiu 2020-11-13 11:44:11

City.vue

​<template>
<div>
<!-- 城市列表头部组件-->
<city-header></city-header>
<!-- 城市列表搜索组件-->
<city-search :cities="cities"></city-search>
<!-- 城市列表项组件-->
<city-list
:cities="cities"
:hotCities="hotCities"
:letter="letter"
></city-list>
<!-- 城市列表字母组件-->
<!-- 父组件上通过监听方法获取子组件传值-->
<city-alphabet :cities="cities" @change="handleChange"></city-alphabet>
</div>
</template>

<script>
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 {
cities: {},
hotCities: [],
letter: ''
}
},
methods: {
getCityInfo () {
axios.get('/api/city.json')
.then(this.getCityInfoSuc)
},
getCityInfoSuc (res) {
res = res.data
if (res.code && res.data) {
const data = res.data
this.cities = data.cities
this.hotCities = data.hotCities
}
},
handleChange (letter) {
this.letter = letter
}
},
mounted () {
this.getCityInfo()
}
}
</script>

<style scoped>

</style>


提问者 Liiiu 2020-11-13 11:43:34

package.json

{
"name": "vue",
"version": "1.0.0",
"description": "A Vue.js project",
"author": "liuzhaozhi <1765805596@qq.com>",
"private": true,
"scripts": {
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"start": "npm run dev",
"lint": "eslint --ext .js,.vue src",
"build": "node build/build.js"
},
"dependencies": {
"axios": "^0.21.0",
"better-scroll": "^1.15.2",
"stylus": "^0.54.8",
"stylus-loader": "^3.0.2",
"swiper": "^6.3.5",
"vue": "^2.5.2",
"vue-awesome-swiper": "^2.6.7",
"vue-router": "^3.0.1",
"vuex": "^3.5.1"
},
"devDependencies": {
"autoprefixer": "^7.1.2",
"babel-core": "^6.22.1",
"babel-eslint": "^8.2.1",
"babel-helper-vue-jsx-merge-props": "^2.0.3",
"babel-loader": "^7.1.1",
"babel-plugin-syntax-jsx": "^6.18.0",
"babel-plugin-transform-runtime": "^6.22.0",
"babel-plugin-transform-vue-jsx": "^3.5.0",
"babel-preset-env": "^1.3.2",
"babel-preset-stage-2": "^6.22.0",
"chalk": "^2.0.1",
"copy-webpack-plugin": "^4.0.1",
"css-loader": "^0.28.0",
"eslint": "^4.15.0",
"eslint-config-standard": "^10.2.1",
"eslint-friendly-formatter": "^3.0.0",
"eslint-loader": "^1.7.1",
"eslint-plugin-import": "^2.7.0",
"eslint-plugin-node": "^5.2.0",
"eslint-plugin-promise": "^3.4.0",
"eslint-plugin-standard": "^3.0.1",
"eslint-plugin-vue": "^4.0.0",
"extract-text-webpack-plugin": "^3.0.0",
"file-loader": "^1.1.4",
"friendly-errors-webpack-plugin": "^1.6.1",
"html-webpack-plugin": "^2.30.1",
"node-notifier": "^5.1.2",
"optimize-css-assets-webpack-plugin": "^3.2.0",
"ora": "^1.2.0",
"portfinder": "^1.0.13",
"postcss-import": "^11.0.0",
"postcss-loader": "^2.0.8",
"postcss-url": "^7.2.1",
"rimraf": "^2.6.0",
"semver": "^5.3.0",
"shelljs": "^0.7.6",
"uglifyjs-webpack-plugin": "^1.1.1",
"url-loader": "^0.5.8",
"vue-loader": "^13.3.0",
"vue-style-loader": "^3.0.1",
"vue-template-compiler": "^2.5.2",
"webpack": "^3.6.0",
"webpack-bundle-analyzer": "^2.9.0",
"webpack-dev-server": "^2.9.1",
"webpack-merge": "^4.1.0"
},
"engines": {
"node": ">= 6.0.0",
"npm": ">= 3.0.0"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}


好帮手慕言 2020-11-13 10:41:29

​同学你好,可能是better-scroll版本的问题。建议:可以打开package.json文件,看下better-scroll的版本和下方是不是一样的。

http://img1.sycdn.imooc.com//climg/5fadf04509bc231f03920047.jpg

如果不一样,建议运行下方命令:

npm install better-scroll@1.15.2 --save

如果上述方法不能解决问题,建议:把package.json文件、City文件夹中的所有文件的代码都粘贴上来,老师帮助排查,祝学习愉快~

  • 提问者 Liiiu #1
    版本一致,其他文件的代码已经传上去了,还有一个Alphabet.vue不让传了,您看下已经上传的文件有什么问题不
    2020-11-13 11:54:07
  • 提问者 Liiiu #2
    Alphabet.vue也上传了
    2020-11-13 11:55:17
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师