Cet article présente principalement le composant loadmore de l'analyse du code source de vue mint-ui. L'éditeur pense qu'il est plutôt bon. Maintenant, je vais le partager avec vous et vous donner une référence. Suivons l'éditeur pour y jeter un œil, j'espère que cela pourra aider tout le monde.
Accès
Document d'accès officiel mint-ui loadmore document
Accès à l'aide de l'exemple
html
<p id="app"> <mt-loadmore :top-method="loadTop" :bottom-method="loadBottom" :bottom-all-loaded="allLoaded" :max-distance="150" @top-status-change="handleTopChange" ref="loadmore"> <p slot="top" class="mint-loadmore-top"> <span v-show="topStatus === 'pull'" :class="{ 'rotate': topStatus === 'drop' }">↓</span> <span v-show="topStatus === 'loading'">Loading...</span> <span v-show="topStatus === 'drop'">释放更新</span> </p> <ul class="scroll-wrapper"> <li v-for="item in list" @click="itemClick(item)">{{ item }}</li> </ul> </mt-loadmore> </p>
css
<link rel="stylesheet" href="https://unpkg.com/mint-ui/lib/style.css" rel="external nofollow" > *{ margin: 0; padding: 0; } html, body{ height: 100%; } #app{ height: 100%; overflow: scroll; } .scroll-wrapper{ margin: 0; padding: 0; list-style: none; } .scroll-wrapper li{ line-height: 120px; font-size: 60px; text-align: center; }
js
<!-- 先引入 Vue --> <script src="https://unpkg.com/vue/dist/vue.js"></script> <!-- 引入组件库 --> <script src="https://unpkg.com/mint-ui/lib/index.js"></script> <script> new Vue({ el: '#app', data: { list: [], allLoaded: false, topStatus: '' }, created: function () { var i =0, len=20; for (; i< len; i++){ this.list.push('demo' + i); } }, methods: { loadTop: function () { // 刷新数据的操作 var self = this; setTimeout(function () { self.list.splice(0, self.list.length); var i =0, len=20; for (; i< len; i++){ self.list.push('demo' + i); } self.$refs.loadmore.onTopLoaded(); }, 2000); }, loadBottom: function () { // 加载更多数据的操作 //load data //this.allLoaded = true;// 若数据已全部获取完毕 var self = this; setTimeout(function () { var i =0; len = 10; for (; i< len; i++){ self.list.push('dddd' + i); } self.$refs.loadmore.onBottomLoaded(); }, 2000); }, handleTopChange: function (status) { this.topStatus = status; }, itemClick: function (data) { console.log('item click, msg : ' + data); } } }); </script>
Analyse du principe de mise en œuvre
Principe de mise en page
Le composant Loadmore est composé en interne de trois emplacements, nommés= top,name= bottom,default;
top est utilisé pour afficher le contenu affiché dans différents états d'actualisation du menu déroulant. La marge-top est initialement définie sur la hauteur de -top pour se cacher<. 🎜>
Principe de mise en œuvre
Analyse du code source
modèle html du composant<p class="mint-loadmore"> <p class="mint-loadmore-content" :class="{ 'is-dropped': topDropped || bottomDropped}" :style="{ 'transform': 'translate3d(0, ' + translate + 'px, 0)' }"> <slot name="top"> <p class="mint-loadmore-top" v-if="topMethod"> <spinner v-if="topStatus === 'loading'" class="mint-loadmore-spinner" :size="20" type="fading-circle"></spinner> <span class="mint-loadmore-text">{{ topText }}</span> </p> </slot> <slot></slot> <slot name="bottom"> <p class="mint-loadmore-bottom" v-if="bottomMethod"> <spinner v-if="bottomStatus === 'loading'" class="mint-loadmore-spinner" :size="20" type="fading-circle"></spinner> <span class="mint-loadmore-text">{{ bottomText }}</span> </p> </slot> </p> </p>
data() { return { translate: 0, // 此变量决定当前组件上下移动, scrollEventTarget: null, // 滚动的dom节点 containerFilled: false, // 当前滚动的内容是否填充完整,不完成会调用 loadmore的回调函数 topText: '', // 下拉刷新,显示的文本 topDropped: false, // 记录当前drop状态,用给组件dom添加is-dropped class(添加回到原点的动画) bottomText: '', // 上拉加载更多 显示的文本 bottomDropped: false, // 同topDropped bottomReached: false, // 当前滚动是否滚动到了底部 direction: '', // touch-move过程中, 当前滑动的方向 startY: 0, // touch-start 起始的y的坐标值 startScrollTop: 0, // touch-start 起始的滚动dom的 scrollTop currentY: 0, // touch-move 过程中的 y的坐标 topStatus: '', // 下拉刷新的状态: pull(下拉) drop(释放) loading(正在加载数据) bottomStatus: '' // 上拉加载更多的状态: 状态同上 }; }
watch: { topStatus(val) { this.$emit('top-status-change', val); switch (val) { case 'pull': this.topText = this.topPullText; break; case 'drop': this.topText = this.topDropText; break; case 'loading': this.topText = this.topLoadingText; break; } }, bottomStatus(val) { this.$emit('bottom-status-change', val); switch (val) { case 'pull': this.bottomText = this.bottomPullText; break; case 'drop': this.bottomText = this.bottomDropText; break; case 'loading': this.bottomText = this.bottomLoadingText; break; } } }
Analyse des fonctions principales
mounted() { this.init();// 当前 vue component挂载完成之后, 执行init()函数 }
init() { this.topStatus = 'pull'; this.bottomStatus = 'pull'; this.topText = this.topPullText; this.scrollEventTarget = this.getScrollEventTarget(this.$el); // 获取滚动的dom节点 if (typeof this.bottomMethod === 'function') { this.fillContainer(); // 判断当前滚动内容是否填满,没有执行外部传入的loadmore回调函数加载数据 this.bindTouchEvents(); // 为当前组件dom注册touch事件 } if (typeof this.topMethod === 'function') { this.bindTouchEvents(); } }, fillContainer() { if (this.autoFill) { this.$nextTick(() => { if (this.scrollEventTarget === window) { this.containerFilled = this.$el.getBoundingClientRect().bottom >= document.documentElement.getBoundingClientRect().bottom; } else { this.containerFilled = this.$el.getBoundingClientRect().bottom >= this.scrollEventTarget.getBoundingClientRect().bottom; } if (!this.containerFilled) { // 如果没有填满内容, 执行loadmore的操作 this.bottomStatus = 'loading'; this.bottomMethod();// 调用外部的loadmore函数,加载更多数据 } }); } }
handleTouchStart(event) { this.startY = event.touches[0].clientY; // 手指按下的位置, 用于下面move事件计算手指移动的距离 this.startScrollTop = this.getScrollTop(this.scrollEventTarget); // 起始scroll dom的 scrollTop(滚动的距离) //下面重置状态变量 this.bottomReached = false; if (this.topStatus !== 'loading') { this.topStatus = 'pull'; this.topDropped = false; } if (this.bottomStatus !== 'loading') { this.bottomStatus = 'pull'; this.bottomDropped = false; } }
handleTouchMove(event) { //确保当前touch节点的y的位置,在当前loadmore组件的内部 if (this.startY < this.$el.getBoundingClientRect().top && this.startY > this.$el.getBoundingClientRect().bottom) { return; } this.currentY = event.touches[0].clientY; let distance = (this.currentY - this.startY) / this.distanceIndex; this.direction = distance > 0 ? 'down' : 'up'; // 下拉刷新,条件(1.外部传入了刷新的回调函数 2.滑动方向是向下的 3.当前滚动节点的scrollTop为0 4.当前topStatus不是loading) if (typeof this.topMethod === 'function' && this.direction === 'down' && this.getScrollTop(this.scrollEventTarget) === 0 && this.topStatus !== 'loading') { event.preventDefault(); event.stopPropagation(); //计算translate(将要平移的距离), 如果当前移动的距离大于设置的最大距离,那么此次这次移动就不起作用了 if (this.maxDistance > 0) { this.translate = distance <= this.maxDistance ? distance - this.startScrollTop : this.translate; } else { this.translate = distance - this.startScrollTop; } if (this.translate < 0) { this.translate = 0; } this.topStatus = this.translate >= this.topDistance ? 'drop' : 'pull';// drop: 到达指定的阈值,可以执行刷新操作了 } // 上拉操作, 判断当前scroll dom是否滚动到了底部 if (this.direction === 'up') { this.bottomReached = this.bottomReached || this.checkBottomReached(); } if (typeof this.bottomMethod === 'function' && this.direction === 'up' && this.bottomReached && this.bottomStatus !== 'loading' && !this.bottomAllLoaded) { event.preventDefault(); event.stopPropagation(); // 判断的逻辑思路同上 if (this.maxDistance > 0) { this.translate = Math.abs(distance) <= this.maxDistance ? this.getScrollTop(this.scrollEventTarget) - this.startScrollTop + distance : this.translate; } else { this.translate = this.getScrollTop(this.scrollEventTarget) - this.startScrollTop + distance; } if (this.translate > 0) { this.translate = 0; } this.bottomStatus = -this.translate >= this.bottomDistance ? 'drop' : 'pull'; } this.$emit('translate-change', this.translate); }
checkBottomReached() { if (this.scrollEventTarget === window) { return document.body.scrollTop + document.documentElement.clientHeight >= document.body.scrollHeight; } else { return this.$el.getBoundingClientRect().bottom <= this.scrollEventTarget.getBoundingClientRect().bottom + 1; } }
handleTouchEnd() { if (this.direction === 'down' && this.getScrollTop(this.scrollEventTarget) === 0 && this.translate > 0) { this.topDropped = true; // 为当前组件添加 is-dropped class(也就是添加动画处理) if (this.topStatus === 'drop') { // 到达了loading的状态 this.translate = '50'; // top slot的高度 this.topStatus = 'loading'; this.topMethod(); // 执行回调函数 } else { // 没有到达,回调原点 this.translate = '0'; this.topStatus = 'pull'; } } // 处理逻辑同上 if (this.direction === 'up' && this.bottomReached && this.translate < 0) { this.bottomDropped = true; this.bottomReached = false; if (this.bottomStatus === 'drop') { this.translate = '-50'; this.bottomStatus = 'loading'; this.bottomMethod(); } else { this.translate = '0'; this.bottomStatus = 'pull'; } } this.$emit('translate-change', this.translate); this.direction = ''; } }
Résumé
méthode de mise en œuvre de liaison à 3 niveaux basée sur la sélection de la ville vue sur mint-ui
vue mint-ui imitation Taobao et adresse de livraison JD.com liaison à quatre niveaux
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!