Browse Source

优化首页刷新组件

pull/19/head
zyronon 3 years ago
parent
commit
03bda164b6
  1. BIN
      src/assets/img/icon/newicon/eim.webp
  2. BIN
      src/assets/img/icon/newicon/el1.webp
  3. 97
      src/pages/slide/IndicatorHome.vue
  4. 10
      src/pages/slide/Slide.vue
  5. 18
      src/pages/slide/SlideHorizontal.vue
  6. 33
      src/pages/slide/SlideVertical.vue
  7. 4
      src/store/index.js
  8. 16
      src/utils/mixin.js

BIN
src/assets/img/icon/newicon/eim.webp

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

BIN
src/assets/img/icon/newicon/el1.webp

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

97
src/pages/slide/IndicatorHome.vue

@ -3,24 +3,29 @@
<transition name="fade"> <transition name="fade">
<div class="mask" v-if="open" @click="open = false"></div> <div class="mask" v-if="open" @click="open = false"></div>
</transition> </transition>
<div class="notice"><span>下拉刷新内容</span></div> <div class="notice" :style="noticeStyle"><span>下拉刷新内容</span></div>
<div class="toolbar" ref="toolbar"> <div class="toolbar" ref="toolbar" :style="toolbarStyle">
<div class="left" @click="$nav('/home/live')">直播</div> <img src="../../assets/img/icon/scan.png"
class="search"
@click="$nav('/home/live')"
style="margin-top: .5rem;">
<div class="tab-ctn"> <div class="tab-ctn">
<div class="tabs" ref="tabs"> <div class="tabs" ref="tabs">
<div class="tab" :class="tabOneClass" @click.stop="change(0)"> <div class="tab" :class="tabOneClass" @click.stop="change(0)">
<span>同城</span> <span>同城</span>
<img v-show="index === 0" src="../../assets/img/icon/arrow-up-white.png" alt=""> <img v-show="index === 0" src="../../assets/img/icon/arrow-up-white.png" class="tab1-img">
</div> </div>
<div class="tab" :class="{active:index === 1}" @click.stop="change(1)"> <div class="tab" :class="{active:index === 1}" @click.stop="change(1)">
<span>关注</span> <span>关注</span>
<img src="../../assets/img/icon/live.webp" class="tab2-img">
</div> </div>
<div class="tab" :class="{active:index === 2}" @click.stop="change(2)"><span>推荐</span> <div class="tab" :class="{active:index === 2}" @click.stop="change(2)"><span>推荐</span>
</div> </div>
</div> </div>
<div class="indicator" ref="indicator"></div> <div class="indicator" ref="indicator"></div>
</div> </div>
<img src="../../assets/img/icon/search-gray.png" alt="" <img v-hide="!loading" src="../../assets/img/icon/search-light.png"
class="search"
@click="$nav('/home/search')" @click="$nav('/home/search')"
style="margin-top: .5rem;"> style="margin-top: .5rem;">
</div> </div>
@ -33,12 +38,13 @@
<div class="l-button" :class="{active:type === 2}" @click="toggleType(2)">热点</div> <div class="l-button" :class="{active:type === 2}" @click="toggleType(2)">热点</div>
</div> </div>
<Loading class="loading" style="width: 4rem;" :is-full-screen="false"/> <Loading :style="loadingStyle" class="loading" style="width: 4rem;" :is-full-screen="false"/>
</div> </div>
</template> </template>
<script> <script>
import Loading from "../../components/Loading"; import Loading from "../../components/Loading";
import bus from "../../utils/bus"; import bus from "../../utils/bus";
import {mapState} from "vuex";
export default { export default {
name: "IndicatorHome", name: "IndicatorHome",
@ -63,25 +69,72 @@ export default {
lefts: [], lefts: [],
indicatorSpace: 0, indicatorSpace: 0,
open: false, open: false,
type: 1 loading: false,
type: 1,
moveY: 0
} }
}, },
computed: { computed: {
...mapState(['judgeValue', 'homeRefresh']),
tabOneClass() { tabOneClass() {
return {active: this.index === 0, open: this.open} return {active: this.index === 0, open: this.open}
},
transform() {
return `translate3d(0, ${this.moveY - this.judgeValue > this.homeRefresh ? this.homeRefresh : this.moveY - this.judgeValue}px, 0)`
},
toolbarStyle() {
if (this.loading) {
return {opacity: 1, 'transition-duration': '300ms', transform: `translate3d(0, 0, 0)`,}
}
if (this.moveY) {
return {
opacity: 1 - (this.moveY - this.judgeValue) / (this.homeRefresh / 2),
transform: this.transform
}
}
return {opacity: 1, 'transition-duration': '300ms', transform: `translate3d(0, 0, 0)`,}
},
noticeStyle() {
if (this.loading) {
return {opacity: 0,}
}
if (this.moveY) {
return {
opacity: (this.moveY - this.judgeValue) / (this.homeRefresh / 2) - .5,
transform: this.transform
}
}
return {opacity: 0,}
},
loadingStyle() {
if (this.loading) {
return {opacity: 1, 'transition-duration': '300ms',}
}
if (this.moveY) {
return {
opacity: (this.moveY - this.judgeValue) / (this.homeRefresh / 2) - .5,
transform: this.transform
}
}
} }
}, },
watch: {
// index(newVal) {
// this.end()
// }
},
created() { created() {
}, },
mounted() { mounted() {
this.initTabs() this.initTabs()
bus.on(this.name + '-move', this.move) bus.on(this.name + '-moveX', this.move)
bus.on(this.name + '-moveY', e => {
// console.log('moveY', e)
this.moveY = e
})
bus.on(this.name + '-end', this.end) bus.on(this.name + '-end', this.end)
bus.on(this.name + '-loading', () => {
console.log('loading')
this.loading = true
setTimeout(() => {
this.loading = false
}, 3000)
})
}, },
methods: { methods: {
toggleType(type) { toggleType(type) {
@ -118,9 +171,10 @@ export default {
this.$setCss(this.indicatorRef, 'transition-duration', `0ms`) this.$setCss(this.indicatorRef, 'transition-duration', `0ms`)
this.$setCss(this.indicatorRef, 'left', this.$setCss(this.indicatorRef, 'left',
this.lefts[this.index] - this.lefts[this.index] -
e.x.distance / (this.$store.state.bodyWidth / this.indicatorSpace) + 'px') e / (this.$store.state.bodyWidth / this.indicatorSpace) + 'px')
}, },
end(index) { end(index) {
this.moveY = 0
this.$setCss(this.indicatorRef, 'transition-duration', `300ms`) this.$setCss(this.indicatorRef, 'transition-duration', `300ms`)
this.$setCss(this.indicatorRef, 'left', this.lefts[index] + 'px') this.$setCss(this.indicatorRef, 'left', this.lefts[index] + 'px')
setTimeout(() => { setTimeout(() => {
@ -190,7 +244,7 @@ export default {
color: rgb(156, 158, 165); color: rgb(156, 158, 165);
position: relative; position: relative;
img { .tab1-img {
position: absolute; position: absolute;
@width: 1rem; @width: 1rem;
width: @width; width: @width;
@ -200,8 +254,15 @@ export default {
margin-top: .7rem; margin-top: .7rem;
} }
.tab2-img {
position: absolute;
height: 1.5rem;
left: 2.4rem;
top: -.5rem;
}
&.open { &.open {
img { .tab1-img {
transform: rotate(180deg); transform: rotate(180deg);
} }
} }
@ -223,6 +284,10 @@ export default {
border-radius: .5rem; border-radius: .5rem;
} }
} }
.search {
width: 2rem;
}
} }
.toggle-type { .toggle-type {

10
src/pages/slide/Slide.vue

@ -34,9 +34,9 @@
<span>住宿</span> <span>住宿</span>
</div> </div>
</div> </div>
<SlideVertical> <SlideVertical name="main">
<div class="item" style="background: tan"> <div class="item">
<p style="padding: 1rem;" v-for="i in 50"> <p style="padding: 1rem;" v-for="i in 5">
r2222222222222222222222222222222222222222222222222222222 r2222222222222222222222222222222222222222222222222222222
</p> </p>
</div> </div>
@ -60,14 +60,14 @@
</div> </div>
</div> </div>
</div> </div>
<SlideVertical> <SlideVertical name="main">
<div class="item">r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1</div> <div class="item">r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1</div>
<div class="item">r2222222222222222222222222222222222222222222222222222222</div> <div class="item">r2222222222222222222222222222222222222222222222222222222</div>
<div class="item">r333333333333333333333333333333333333333333333333333333</div> <div class="item">r333333333333333333333333333333333333333333333333333333</div>
</SlideVertical> </SlideVertical>
</div> </div>
<div class="item"> <div class="item">
<SlideVertical> <SlideVertical name="main">
<div class="item">r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1</div> <div class="item">r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1</div>
<div class="item">r2222222222222222222222222222222222222222222222222222222</div> <div class="item">r2222222222222222222222222222222222222222222222222222222</div>
<div class="item">r333333333333333333333333333333333333333333333333333333</div> <div class="item">r333333333333333333333333333333333333333333333333333333</div>

18
src/pages/slide/SlideHorizontal.vue

@ -1,5 +1,6 @@
<script lang="jsx"> <script lang="jsx">
import bus from "../../utils/bus"; import bus from "../../utils/bus";
import {mapState} from "vuex";
export default { export default {
props: { props: {
@ -25,9 +26,11 @@ export default {
startY: 0, startY: 0,
needCheck: true, needCheck: true,
next: false, next: false,
judgeValue: 20
} }
}, },
computed: {
...mapState(['judgeValue'])
},
mounted() { mounted() {
this.wrapper = this.$refs.wrapper this.wrapper = this.$refs.wrapper
this.total = this.wrapper.children.length this.total = this.wrapper.children.length
@ -59,9 +62,7 @@ export default {
this.checkDirection(e) this.checkDirection(e)
if (this.next) { if (this.next) {
bus.emit(this.name + '-move', { bus.emit(this.name + '-moveX', this.moveX)
x: {distance: this.moveX, isRight},
})
this.$stopPropagation(e) this.$stopPropagation(e)
this.$setCss(this.wrapper, 'transform', this.$setCss(this.wrapper, 'transform',
`translate3d(${this.getDistance() `translate3d(${this.getDistance()
@ -74,12 +75,7 @@ export default {
if (!this.needCheck) return if (!this.needCheck) return
if (Math.abs(this.moveX) > this.judgeValue || Math.abs(this.moveY) > this.judgeValue) { if (Math.abs(this.moveX) > this.judgeValue || Math.abs(this.moveY) > this.judgeValue) {
let angle = (Math.abs(this.moveX) * 10) / (Math.abs(this.moveY) * 10) let angle = (Math.abs(this.moveX) * 10) / (Math.abs(this.moveY) * 10)
if (angle > 1) { this.next = angle > 1;
this.next = true
// console.log('')
} else {
// console.log('')
}
// console.log(angle) // console.log(angle)
return this.needCheck = false return this.needCheck = false
} }
@ -104,12 +100,12 @@ export default {
this.$emit('update:index', this.lIndex) this.$emit('update:index', this.lIndex)
this.reset() this.reset()
bus.emit(this.name + '-end', this.lIndex)
}, },
reset() { reset() {
this.moveX = 0 this.moveX = 0
this.next = false this.next = false
this.needCheck = true this.needCheck = true
bus.emit(this.name + '-end', this.lIndex)
}, },
getDistance() { getDistance() {
return -this.lIndex * this.wrapperWidth return -this.lIndex * this.wrapperWidth

33
src/pages/slide/SlideVertical.vue

@ -1,5 +1,14 @@
<script lang="jsx"> <script lang="jsx">
import bus from "../../utils/bus";
import {mapState} from "vuex";
export default { export default {
props: {
name: {
type: String,
default: () => ''
},
},
data() { data() {
return { return {
wrapper: null, wrapper: null,
@ -13,9 +22,11 @@ export default {
startY: 0, startY: 0,
needCheck: true, needCheck: true,
next: false, next: false,
judgeValue: 20
} }
}, },
computed: {
...mapState(['judgeValue','homeRefresh'])
},
mounted() { mounted() {
this.wrapper = this.$refs.wrapper this.wrapper = this.$refs.wrapper
this.total = this.wrapper.children.length this.total = this.wrapper.children.length
@ -29,14 +40,18 @@ export default {
this.startY = e.touches[0].pageY this.startY = e.touches[0].pageY
}, },
touchMove(e) { touchMove(e) {
console.log('move',e.touches[0].pageY)
this.moveX = e.touches[0].pageX - this.startX this.moveX = e.touches[0].pageX - this.startX
this.moveY = e.touches[0].pageY - this.startY this.moveY = e.touches[0].pageY - this.startY
let isDown = this.moveY < 0 let isDown = this.moveY < 0
this.checkDirection(e)
if (this.index === 0 && !isDown && this.next) {
bus.emit(this.name + '-moveY', this.moveY)
}
if ((this.index === 0 && !isDown) || (this.index === this.total - 1 && isDown)) return if ((this.index === 0 && !isDown) || (this.index === this.total - 1 && isDown)) return
this.checkDirection(e)
if (this.next) { if (this.next) {
this.$stopPropagation(e) this.$stopPropagation(e)
@ -55,12 +70,7 @@ export default {
} }
if (Math.abs(this.moveX) > this.judgeValue || Math.abs(this.moveY) > this.judgeValue) { if (Math.abs(this.moveX) > this.judgeValue || Math.abs(this.moveY) > this.judgeValue) {
let angle = (Math.abs(this.moveX) * 10) / (Math.abs(this.moveY) * 10) let angle = (Math.abs(this.moveX) * 10) / (Math.abs(this.moveY) * 10)
if (angle > 1) { this.next = angle <= 1;
// console.log('')
} else {
this.next = true
// console.log('')
}
// console.log(angle) // console.log(angle)
return this.needCheck = false return this.needCheck = false
} }
@ -68,6 +78,9 @@ export default {
}, },
touchEnd(e) { touchEnd(e) {
let isDown = this.moveY < 0 let isDown = this.moveY < 0
if (this.index === 0 && !isDown && this.moveY > (this.homeRefresh + this.judgeValue)) {
bus.emit(this.name + '-loading')
}
let next = true let next = true
if ((this.index === 0 && !isDown) || (this.index === this.total - 1 && isDown)) next = false if ((this.index === 0 && !isDown) || (this.index === this.total - 1 && isDown)) next = false
@ -88,12 +101,12 @@ export default {
this.moveX = 0 this.moveX = 0
this.next = false this.next = false
this.needCheck = true this.needCheck = true
bus.emit(this.name + '-end', this.index)
}, },
getDistance() { getDistance() {
return -this.index * this.wrapperHeight return -this.index * this.wrapperHeight
}, },
}, },
render(createElement, context) { render(createElement, context) {
return ( return (
<div className="slide"> <div className="slide">

4
src/store/index.js

@ -42,7 +42,9 @@ const store = Vuex.createStore({
"is_private": 1 "is_private": 1
}, },
friends: resource.users, friends: resource.users,
excludeRoutes: [] excludeRoutes: [],
judgeValue: 20,
homeRefresh: 60,
}, },
mutations: { mutations: {
setUserinfo(store, val) { setUserinfo(store, val) {

16
src/utils/mixin.js

@ -93,6 +93,22 @@ export default {
el.addEventListener("touchend", cancel); el.addEventListener("touchend", cancel);
el.addEventListener("touchcancel", cancel); el.addEventListener("touchcancel", cancel);
} }
},
hide: {
beforeMount: function (el, binding, vNode) {
if (binding.value) {
el.style.opacity = 1
} else {
el.style.opacity = 0
}
},
updated: function (el, binding, vNode) {
if (binding.value) {
el.style.opacity = 1
} else {
el.style.opacity = 0
}
}
} }
}, },
} }
Loading…
Cancel
Save