I have always wanted to study how vUE components are written. Fortunately, I finally started my research today, so I just wrote this article today. Shall we first analyze the whole page

The header is also fixed at the top

We need to be prompted to load more of these words as we scroll

(loadmore.vue)
<template>
<div class="more" v-show="loadmoreShow">
	{{text}}		
</div>	
</template>

<script>
// eslint-disable-next-line
/* eslint-disable */
export default {
	name: 'loadmore',
	props: {
		text: {
			type: String,
			default: '',
		},
		loadmoreShow: {
			type: Boolean,
			default: false,
		}
	}
}
</script>
<style scoped lang="scss">
@import "@/static/vars.scss";
.more{
	color: $loadmorecolor;
	height: 30px;
	line-height:30px;
	font-size: $fontsize;
	margin-bottom: 50px;
}	
</style>
Copy the code

When no data is loaded, we need to say no more data (nulldata.vue)

<template> <div class="null" V-show ="nulld"> No more data </div> </template> <script> // eslint-disable-next-line /* eslint-disable */ export default { name: 'nulldata', props: { nulld: { type: Boolean, default: false } } } </script> <style scoped lang="scss"> @import "@/static/vars.scss"; .null{ color: $nulldatacolor; height: 30px; line-height:30px; font-size: $fontsize; margin-bottom: 50px; } </style>Copy the code

Now we’re going to write the scroll component (scroll.vue)

<template lang="html"> <div class="scroll" @touchstart=touchStart($event) @touchmove=touchMove($event) @touchend=touchEnd($event)> <section class="inner"> <! <slot> </slot> // < V-loadMore ref='loadmore' :loadmoreShow="loadmoreShow" :text="text"></ V-loadmore > <v-nulldata :nulld="dataList.nulld"></v-nulldata> </section> </div> </template> <script> // eslint-disable-next-line /* eslint-disable */ import nulldata from '@/components/nulldata.vue' import loadmore from '@/components/loadmore.vue' export default { props: { bottom: { type: Number, default: 50 }, enbaleLoadMore: { type: Boolean, default: true, }, dataList: { default: false, required: false }, onLoadMore: { type: Function, default: undefined, } }, components: { "v-nulldata": nulldata, "v-loadmore": loadmore }, data() { return { text: '', isLoading: false, loadmoreEl:null, loadmoreShow: false, touches: { startX: 0, startY: 0, scrollTop: 0, touching: false, } } }, mounted() { this.loadmoreEl = this.$refs.loadmore.$el; }, methods: { touchStart(e){ // console.log('touchStart',e) var touch = e.targetTouches[0]; this.touches.startX = touch.pageX this.touches.startY = touch.pageY this.touches.scrollTop = this.$el.scrollTop || this.touches.scrollTop this.touches.touching = true // this.dataList.nulld = false this.enableLoadMore = true; }, touchMove(e){ if(! this.enableLoadMore || ! This. Touches. Touching | | this. DataList. Nulld) {/ / if you don't start to load more, good, or no sliding, [0].view.content.size.content.scrollTop if(view.content.content.size.content.scrollTop) { E.preventdefault ()} this.text = 'loadmore' this.loadMoreShow = true; }, touchEnd(e) { if (this.isLoading) { return; } console. Log (" touches too short ") this.touches. Touching = false ----begin let endX = e.touches [0]. endY = e.changedTouches[0].pageY, dy = this.touches.startY - endY, dx = endX - this.touches.startX; // if(math.abs (dx) < 2 && math.abs (dy) < 2) {// console.log(" math.abs (dx) < 2 ") this.loadmoreShow = false; // Hide the addbar return; } if(! this.enableLoadMore || this.isLoading) { this.loadmoreEl.style.display = 'none'; Return} console.log(1) let outerHeight = this.$el.clientheight, innerHeight = this.$el.querySelector('.inner').clientHeight, scrollTop = this.$el.scrollTop, bottom = innerHeight - outerHeight - scrollTop; // console.log("outerHeight",outerHeight) // console.log("innerHeight",innerHeight) // console.log("scrollTop",scrollTop) // console.log("bottom",bottom) // console.log('this.$el',this.$el) // Console. log("this.bottom",this.bottom) if(bottom <= this.bottom) {// Too little content this.doloadmore (); } else { this.loadmoreShow = false; // Hide loadbar}}, doLoadMore() {this.isloading = true this.text = 'loading' this.onloadMore (this.loaddOne); }, loadDone() { this.isLoading = false this.loadmoreShow = false; </script> <style scoped lang=" SCSS ">. Scroll {position: relative; z-index: 100; top: 34px; overflow: auto; -webkit-overflow-scrolling: touch; .inner{ transition-duration: 300ms; } } </style>Copy the code

The basic SCSS style is as follows: vars.scss

$backgroundcolor: rgb(0, 150, 136);
$fontsize: 24px;
$color: #fff;
$nulldatacolor: #999999;
$loadmorecolor: #666;
Copy the code

The overall directory structure is as follows

<template> <div class="index"> <v-header></v-header> <div class="box"> <v-scroll :onLoadMore="onLoadMore" :dataList="dataList"> <ul> <li v-for="(item) in listdata" :key="item.name">{{item.name}}</li> <li v-for="(item) in downdata" :key="item.name">{{item.name}}</li> </ul> </v-scroll> </div> <v-footer></v-footer> </div> </template> <script>  // eslint-disable-next-line /* eslint-disable */ import scroll from "@/components/scroll.vue" import vheader from '@/components/vheader.vue' import vfooter from '@/components/vfooter.vue' export default { name: 'index', components: {"v-scroll": scroll, 'v-header': vheader, 'v-footer': vfooter,}, data() {return {counter: 1, // current page num: PageStart: 0, pageEnd: 0, pageEnd: 0, listData: [], // drop down to update data store array downData: }}}, mounted: function() {this.getList(); // if () {this.getList(); // if () {this.getList(); }, methods: { getList() { var response = [] for(let i = 0; i < 100; i++) { response.push({ name: i }) } this.listdata = response.slice(0, this.num); }, onLoadMore(done) { this.counter++; let end = this.pageEnd = this.num * this.counter; let i = this.pageStart = this.pageEnd - this.num; setTimeout(() => { for(i; i < end; I ++) {if(I >= 50) {this.datalist. Nulld = true; break; } else { this.downdata.push({ name: i + "===" }) // more.style.display = 'none'; }} done(); }, 2000); } } } </script> <style scoped lang="scss"> @import "@/static/vars.scss"; .index{ .box{ ul li{ height: 40px; line-height:40px; border: 1px solid red; } } } </style>Copy the code

Segmentfault.com/q/101000000…
Segmentfault.com/a/119000000…
Forum.ionicframework.com/t/error-ign…
Lee Jinwen/VUE components