Commit d87838f9 by 高淑倩

merge_mainjs

parents 314d0c9f ed73cbfb
...@@ -10,9 +10,11 @@ export default { ...@@ -10,9 +10,11 @@ export default {
} }
</script> </script>
<style>
</style>
<style lang="scss"> <style lang="scss">
@import "~@/assets/font-awesome/scss/font-awesome.scss"; @import "~@/assets/font-awesome/scss/font-awesome.scss";
/** 重置element-ui theme **/
$--color-primary: #337ab7 !default;
$--font-path: '~element-ui/lib/theme-chalk/fonts';
@import "~element-ui/packages/theme-chalk/src/index";
</style> </style>
...@@ -29,6 +29,19 @@ ...@@ -29,6 +29,19 @@
.fl { .fl {
float: left; float: left;
} }
.clearfix {
clear: both;
overflow: auto;
}
.clearfix:before {
content: "";
clear: both;
}
.clearfix:after {
content: "";
clear: both;
}
.step { .step {
background-color: rgba(52, 73, 94, 1); background-color: rgba(52, 73, 94, 1);
color: #fff; color: #fff;
...@@ -40,3 +53,12 @@ ...@@ -40,3 +53,12 @@
a,button { a,button {
cursor: pointer; cursor: pointer;
} }
.left-l {
left: 70px;
}
.left-ll {
left: 240px;
}
<template lang="pug"> <template lang="pug">
el-container.header-container el-container.header-container(:class="{'left-l':!sidebarUnfoldInfo,'left-ll':sidebarUnfoldInfo}")
nav.header-nav.clear nav.header-nav.clear
ul.clear ul.clearfix
li.nav-item.fl('@click'="handleShowMemus('show',$event)") li.nav-item.fl('@click'="handleShowMenus('show',$event)")
a.link a.link
i.fa.fa-th-list i.fa.fa-th-list
li.nav-item.fl li.nav-item.fl(@click="handleEditMenus()")
a.link a.link
i.fa.fa-th-large i.fa.fa-th-large
li.nav-item.fl li.nav-item.fl
a.link el-popover(
placement="bottom-end",
:offset="100",
:width="300",
popper-class="historys-popper",
trigger="click")
.historys-body
.history-list--item.clearfix(v-for='historyItem in historys ')
.name.fl {{historyItem.name}}
.time.fr {{historyItem.time}}
a.link(slot="reference")
i.fa.fa-clock-o i.fa.fa-clock-o
.history-links-preview.fl .history-links-preview.fl
.history-item.fl('v-for'="(history,index) in historysLimit",':key'="index") {{history.name}} .history-item.fl('v-for'="(history,index) in historysLimit",':key'="index") {{history.name}}
li.nav-item.fr li.nav-item.fr
a.link el-popover(
placement="bottom-end",
:offset="100",
:width="150",
popper-class="helpers-popper",
trigger="click")
.opration-body
.opration-list--item.clearfix(v-for='opration in oprations ')
.name.fl(@click="gotoPage(opration.link)") {{opration.name}}
a.link(slot="reference")
img.user-img(':src'="user.headerImage") img.user-img(':src'="user.headerImage")
span.user-name {{user.name}} span.user-name {{user.name}}
i.fa.fa-angle-down i.fa.fa-angle-down
...@@ -22,14 +41,26 @@ ...@@ -22,14 +41,26 @@
a.link a.link
i.fa.fa-envelope-o i.fa.fa-envelope-o
li.nav-item.fr li.nav-item.fr
a.link el-popover(
placement="bottom-end",
:offset="100",
:width="150",
popper-class="helpers-popper",
trigger="click")
.helpers-body
.helper-list--item.clearfix(v-for='help in helpers ')
i.fa.fl.helper-item--icon(:class="help.icon",:style="help.style",style={width:'22px',height:'22px'})
.name.fl {{help.name}}
a.link(slot="reference")
i.fa.fa-comments i.fa.fa-comments
el-row.meuns-nav el-row.meuns-nav(v-show="showMenusPanel")
el-menu&attributes({ el-menu(@click="toggleMenus($event)")&attributes({
'default-active':"2", 'default-active':"2",
'class':"el-menu-vertical", 'class':"el-menu-vertical",
'@open':"handleOpen", '@open':"handleOpen",
'@close':"handleClose", '@close':"handleClose",
'text-color':'#2a3f54',
'active-text-color':'#fff'
}) })
el-submenu.menus-body.clear(index="1") el-submenu.menus-body.clear(index="1")
el-menu-item-group.menus-groups.fl('v-for'="(item,index) in menus",':key'="index") el-menu-item-group.menus-groups.fl('v-for'="(item,index) in menus",':key'="index")
...@@ -38,32 +69,28 @@ ...@@ -38,32 +69,28 @@
i(class="fa",':class'="item.ico", style={'margin-right':'5px'}) i(class="fa",':class'="item.ico", style={'margin-right':'5px'})
span.main-menus-title {{item.name}} span.main-menus-title {{item.name}}
el-menu-item&attributes({ el-menu-item&attributes({
':index':"idx | pipeString(index)", ':index':"formatPathString(index,idx)",
'v-for':'(it,idx) in item.children', 'v-for':'(it,idx) in item.children',
':key':"idx" ':key':"idx"
}) {{it.name}} })
el-menu-item-group.menus-tags('v-for'="(i,inx) in it.children",':key'="inx") el-menu-item-group.menus-tags
<!--template(slot="title") {{i.name}}--> template(slot="title")
span {{it.name}}
el-menu-item&attributes({ el-menu-item&attributes({
':index':"inx | pipeString(index,idx)", 'v-for':'(i,inx) in it.children',
':key':"inx" ':index':"formatPathString(index,idx,inx)",
':key':"inx",
'@click':'setActiveStyle(i,$event)',
':class':"{ active:formatPathString(index,idx,inx) === currentSelectIndex}"
}) {{i.name}} }) {{i.name}}
</template> </template>
<style lang="stylus"> <style lang="stylus">
.header-container .header-container
position fixed position fixed
left 0
right 0 right 0
top 0 top 0
z-index 99 z-index 99
box-shadow 0 1px 1px rgba(0,0,0,.2) box-shadow 0 1px 1px rgba(0,0,0,.2)
.header-nav
position relative
background #ededed
width 100%
margin-left 70px
.el-submenu__title
display none
.nav-item .nav-item
display inline-block display inline-block
position relative position relative
...@@ -82,19 +109,76 @@ ...@@ -82,19 +109,76 @@
.history-links-preview .history-links-preview
margin-top 16px margin-top 16px
margin-left 15px margin-left 15px
.menus-body
.el-menu
margin-bottom 200px
.header-nav
position relative
background #ededed
width 100%
.el-menu--inline
display block !important
.menus-tags
.el-menu-item
background #f5f5f5
line-height 30px
padding 0 10px
color #2a3f54
min-width 120px
cursor pointer
&:hover,
&:focus
background #f5f5f5
.menus-groups
& > .el-menu-item-group__title
&:before
display none
.el-submenu__title
display none
.el-menu-item-group__title
position relative
padding-left 10px !important
margin-left 10px
color: #2a3f54;
font-size: 14px;
font-weight: bold;
padding-left: 10px;
position: relative;
&::before
content ''
position absolute
width 4px
height 4px;
border-radius 50%
left 0
top 50%
margin-top -2px
background #2a3f54
.main-menus-title
font-size 15px
.el-menu-item
padding 0 10px !important
&.active
background: #1ABB9C !important
color: #fff !important
</style> </style>
<style lang="stylus" scoped> <style lang="stylus" scoped>
.meuns-nav .meuns-nav
position absolute position absolute
left 0 left 0
right 0 right 0
bottom 0 height 1000px
box-sizing border-box
top 70px top 70px
z-index 9 z-index 9
overflow-y scroll
.menus-body .menus-body
display flex display flex
.menus-groups .menus-groups
width 200px width 200px
border-right: 1px solid #ddd;
margin: 15px 0;
padding 1px
.main-menus .main-menus
color #2a3f54 color #2a3f54
font-size 15px font-size 15px
...@@ -127,13 +211,57 @@ ...@@ -127,13 +211,57 @@
.el-menu-item .el-menu-item
height auto height auto
line-height 1.5 line-height 1.5
overflow hidden
text-align left
&:hover,
&:focus
background none
.history-list--item,
.helper-list--item,
.opration-list--item
display flex
justify-content flex-start
align-items center
box-sizing border-box
font-size: 12px
color: #5A738E
width: 100%
padding: 3px 20px;
clear: both;
font-weight: 400;
line-height: 1.42857143;
white-space: nowrap;
cursor pointer
.helper-list--item
padding 5px 0
.helper-item--icon
display: flex;
justify-content center
align-items center
padding: 5px;
border-radius: 5px;
margin-right: 5px;
</style> </style>
<script> <script>
import { mapGetters } from 'vuex' import { mapGetters, mapActions } from 'vuex'
export default { export default {
name: 'headerNav', name: 'headerNav',
data () { data () {
return { return {
showMenusPanel: false,
showEditMenusPanel: false,
currentSelectIndex: -1,
oprations: [{name: '修改密码', link: 'http://www.baidu.com'}, {name: '安全退出', link: 'http://www.baidu.com'}],
helpers: [{
name: '点击联系客服',
icon: 'fa-qq',
style: {background: '#ff9293', color: '#fff'}
}, {name: '使用帮助',
style: {background: '#40b0ff', color: '#fff'},
icon: 'fa-info'},
{name: '舞象客服',
style: {background: '#e0e0e0', color: '#000'},
icon: 'fa-user-circle-o'}],
user: { user: {
headerImage: 'http://photo.bigaka.com/photos//2132/201805/56741525659969939_144_144.jpg', headerImage: 'http://photo.bigaka.com/photos//2132/201805/56741525659969939_144_144.jpg',
name: '测试商户组' name: '测试商户组'
...@@ -162,19 +290,46 @@ export default { ...@@ -162,19 +290,46 @@ export default {
return [...historys] return [...historys]
} }
}, },
...mapGetters({menus: 'getMenus'}) ...mapGetters({
menus: 'getMenus',
editMenus: 'getEditMenus',
sidebarUnfoldInfo: 'getSidebarUnfoldInfo'
})
}, },
methods: { methods: {
...mapActions([
'showEditMenus',
'hideEditMenus'
]),
clickItem () { clickItem () {
console.log(this) console.log(this)
}, },
handleOpen () {}, handleOpen () {},
handleClose () {}, handleClose () {},
handleShowMemus (type) { handleShowMenus () {
this.$nextTick(() => { this.showMenusPanel = !this.showMenusPanel
let dom = document.querySelector('.el-submenu__title') },
dom.click() toggleMenus (...args) {
}) console.log(args)
},
handleEditMenus () {
if (!this.editMenus) {
this.showEditMenus()
} else {
this.hideEditMenus()
}
},
setActiveStyle (item, ev) {
this.currentSelectIndex = ev.index
console.log(item)
},
formatPathString (...args) {
return args.join('-')
},
gotoPage (link) {
if (link) {
location.href = link
}
} }
} }
} }
......
<template>
<div>
<!--滑动区域-->
<mescroll-vue ref="mescroll" :up="mescrollUp" @init="mescrollInit">
<!--筛选条件; 模拟列表的重置和演示空布局的使用-->
<div class="nav">
<p :class="getActiveCls(0)" @click="changeTab(0)">全部</p>
<p :class="getActiveCls(1)" @click="changeTab(1)">奶粉</p>
<p :class="getActiveCls(2)" @click="changeTab(2)">图书</p>
</div>
<!--展示上拉加载的数据列表-->
<ul id="dataList" class="data-list">
<li v-for="pd in dataList" :key="pd.id">
<p class="msg-title">{{pd.title}}</p>
<p class="msg-text">{{pd.content_text}}</p>
<p class="msg-time">{{pd.create_time}}</p>
</li>
</ul>
</mescroll-vue>
</div>
</template>
<script>
// 引入mescroll的vue组件
import MescrollVue from '@/lib/mescroll/mescroll.vue'
export default {
name: 'message',
components: {
MescrollVue
},
data () {
return {
mescroll: null, // mescroll实例对象
mescrollUp: {
callback: this.upCallback, // 上拉回调,此处可简写; 相当于 callback: function (page, mescroll) { getListData(page); }
page: {
num: 0, // 当前页码,默认0,回调之前会加1,即callback(page)会从1开始
size: 10 // 每页数据的数量
},
noMoreSize: 5, // 如果列表已无数据,可设置列表的总数量要大于等于5条才显示无更多数据;避免列表数据过少(比如只有一条数据),显示无更多数据会不好看
toTop: {
src: './static/images/mescroll/mescroll-totop.png' // 回到顶部按钮的图片路径,支持网络图
},
empty: {
// 列表第一页无任何数据时,显示的空提示布局; 需配置warpId才生效;
warpId: 'dataList', // 父布局的id;
icon: './static/images/mescroll/mescroll-empty.png', // 图标,支持网络图
tip: '暂无相关数据~', // 提示
btntext: '去逛逛 >', // 按钮,默认""
btnClick () { // 点击按钮的回调,默认null
alert('点击了按钮,具体逻辑自行实现')
}
},
lazyLoad: {
use: true // 是否开启懒加载,默认false
}
},
dataList: [], // 列表数据
pdType: 0 // 菜单
}
},
beforeRouteEnter (to, from, next) { // 如果没有配置回到顶部按钮或isBounce,则beforeRouteEnter不用写
next(vm => {
vm.$refs.mescroll.beforeRouteEnter() // 进入路由时,滚动到原来的列表位置,恢复回到顶部按钮和isBounce的配置
})
},
beforeRouteLeave (to, from, next) { // 如果没有配置回到顶部按钮或isBounce,则beforeRouteLeave不用写
this.$refs.mescroll.beforeRouteLeave() // 退出路由时,记录列表滚动的位置,隐藏回到顶部按钮和isBounce的配置
next()
},
methods: {
// mescroll组件初始化的回调,可获取到mescroll对象
mescrollInit (mescroll) {
this.mescroll = mescroll
},
// 上拉回调 page = {num:1, size:10}; num:当前页 ,默认从1开始; size:每页数据条数,默认10
upCallback (page, mescroll) {
// 模拟联网
this.getListDataFromNet(page.num, page.size)
},
// 选中状态的样式
getActiveCls (type) {
return this.pdType === type ? 'active' : ''
},
// 切换菜单
changeTab (type) {
if (this.pdType !== type) {
this.pdType = type
this.dataList = []// 在这里手动置空列表,可显示加载中的请求进度
this.mescroll.resetUpScroll() // 刷新列表数据
}
},
/* 联网加载列表数据
在您的实际项目中,请参考官方写法: http://www.mescroll.com/api.html#tagUpCallback
请忽略getListDataFromNet的逻辑,这里仅仅是在本地模拟分页数据,本地演示用
实际项目以您服务器接口返回的数据为准,无需本地处理分页.
* */
async getListDataFromNet (pageNum, pageSize) {
// 延时一秒,模拟联网
const res = await this.axios.get('http://rap2api.taobao.org/app/mock/115626/store/notice!getStoreNoticeListByPageAction.do',{
params:{
pageNo:pageNum,
pageSize,
push_state:2
}
})
if (res.data.code === 0) {
const resData = res.data.dataList
const length = this.dataList.length
if (length <= res.data.totalCount) {
this.dataList = this.dataList.concat(resData)
}
}
}
}
}
</script>
<style scope>
/*以fixed的方式固定mescroll的高度*/
.mescroll {
position: fixed;
top: 44px;
bottom: 0;
height: auto;
}
.header {
z-index: 9990;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 44px;
line-height: 44px;
text-align: center;
border-bottom: 1px solid #eee;
background-color: white;
}
.header .btn-left {
position: absolute;
top: 0;
left: 0;
padding: 12px;
line-height: 22px;
}
.swiper {
width: 100%;
vertical-align: bottom;
}
.nav {
text-align: center;
border-bottom: 1px solid #ddd;
}
.nav p {
display: inline-block;
width: 30%;
padding: 10px 0;
}
.nav .active {
border-bottom: 1px solid #FF6990;
color: #FF6990;
}
.data-list li {
position: relative;
padding: 10px 8px 10px 120px;
border-bottom: 1px solid #eee;
}
.data-list .pd-img {
position: absolute;
left: 18px;
top: 18px;
width: 80px;
height: 80px;
}
.data-list .pd-name {
font-size: 16px;
line-height: 20px;
height: 40px;
overflow: hidden;
}
.data-list .pd-price {
margin-top: 8px;
color: red;
}
.data-list .pd-sold {
font-size: 12px;
margin-top: 8px;
color: gray;
}
</style>
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
img(class='icon-arrow',':class'="{right:!unfold}","src"='@/assets/images/sidebar/left-arrow-gray.png') img(class='icon-arrow',':class'="{right:!unfold}","src"='@/assets/images/sidebar/left-arrow-gray.png')
</template> </template>
<script> <script>
import { mapGetters } from 'vuex' import { mapGetters, mapActions } from 'vuex'
import sidebarItem from '../sidebarItem' import sidebarItem from '../sidebarItem'
const logo = require('@/assets/images/sidebar/logo-blue.png') const logo = require('@/assets/images/sidebar/logo-blue.png')
export default { export default {
...@@ -103,6 +103,7 @@ export default { ...@@ -103,6 +103,7 @@ export default {
} else { } else {
this.unfold = args[0] this.unfold = args[0]
} }
this.setSidebarUnfold(this.unfold)
}, },
hiddenUnfoldBtn () { hiddenUnfoldBtn () {
this.unfoldBtn = false this.unfoldBtn = false
...@@ -115,7 +116,8 @@ export default { ...@@ -115,7 +116,8 @@ export default {
}, },
getCurrentMenus (index) { getCurrentMenus (index) {
return this.menus[index] return this.menus[index]
} },
...mapActions(['setSidebarUnfold'])
} }
} }
</script> </script>
......
<template>
<div class="menus-edit--control" v-show="editMenus">
<div class="content" >
<div class="dropdown-menu quick-links-panel" >
<!-- 快捷入口 -->
<div class="clearfix quick-links-container">
<a class="fl"><i class="fa fa-thumb-tack"></i></a>
<div class="quick-items fl">
<a class="quick-item" v-for="(item, index) in quickItems" :key="index"> {{item.name}} </a>
</div>
<span class="tips inline">Tips:快速触达,最多10个</span>
<a class="fr" @click="hideContentBox()" ><i class="fa fa-times"></i></a>
<a class="fr" @click="showEditMenus()" ><i class="fa fa-ellipsis-h"></i></a>
</div>
</div>
</div>
<div class="warpper">
<el-dialog :visible.sync="dialogFormVisible" width="100%" center :show-close="false" :top="'4vh'">
<menusTemplete :select-list="selectMenus" @choose="chooseMenus" />
<div slot="footer" class="dialog-footer">
<el-button @click="hideEditMenus()">取 消</el-button>
<el-button type="primary" @click="sure()">确 定</el-button>
<span class="tip">已选:{{selectList.length}}个快捷菜单,最多可选10个。</span>
</div>
</el-dialog>
</div>
</div>
</template>
<style>
.dropdown-menu.quick-links-panel,.dropdown-menu.quick-links-panel a {
color: #73879c;
margin-right: 20px;
}
.dropdown-menu.quick-links-panel a i {
font-size: 24px;
line-height: 42px;
}
.dropdown-menu.quick-links-panel .quick-links-container {
padding-left: 15px;
}
.dropdown-menu.quick-links-panel {
left: 0;
width: 100%;
line-height: 42px;
border-top: 0;
z-index: 999;
border: 0;
background: #f9f9f9;
}
.dropdown-menu.menu-links-panel.in, .dropdown-menu.quick-links-panel.in {
transform: translateY(0);
-webkit-transform: translateY(0);
opacity: 1;
}
.menus-edit--control .el-dialog__header {
display: none;
}
.menus-edit--control .quick-item {
margin: 0 15px 0 0;
font-size: 14px;
line-height: 42px
}
.warpper .el-dialog--center .el-dialog__body {
height: 600px;
overflow: auto;
}
.warpper .el-dialog__body .menus-templete {
padding-bottom: 0;
}
</style>
<style scoped>
.tip {
margin-left: 10px;
font-size: 12px;
color: #aaa;
}
</style>
<script>
import { mapActions, mapGetters } from 'vuex'
import menusTemplete from './menusTemplete'
export default {
components: {
menusTemplete
},
data () {
return {
dialogFormVisible: false,
selectList: [],
tempSelectList: [],
quickItems: [],
tempQuickItems: [],
limitLength: 10,
isSure: false
}
},
created () {
let quickItemsInfo = localStorage.getItem('_quickItemsInfo')
if (quickItemsInfo) {
quickItemsInfo = JSON.parse(quickItemsInfo)
this.quickItems = quickItemsInfo.quickItems
this.selectList = quickItemsInfo.selectList
}
},
props: ['showControl'],
computed: {
selectMenus () {
return [...this.tempSelectList, ...this.selectList]
},
...mapGetters({editMenus: 'getEditMenus'})
},
methods: {
...mapActions({
hideMenus: 'hideEditMenus'
}),
hideEditMenus () {
this.dialogFormVisible = false
this.tempSelectList = []
this.tempQuickItems = []
},
showEditMenus () {
this.isSure = false
this.dialogFormVisible = true
},
hideContentBox () {
this.hideMenus()
},
sure () {
this.quickItems = [...this.quickItems, ...this.tempQuickItems]
this.selectList = [...this.selectList, ...this.tempSelectList]
const quicksInfo = {quickItems: this.quickItems, selectList: this.selectList}
localStorage.setItem('_quickItemsInfo', JSON.stringify(quicksInfo))
this.hideEditMenus()
this.$message({
message: '快捷菜单设置成功',
type: 'success'
})
},
chooseMenus ({item, vNode}) {
const totalLength = this.tempQuickItems.length + this.quickItems.length
if (this.limitLength < totalLength) {
this.$message({
message: '最多选择十个快捷菜单',
type: 'warning'
})
return false
}
const index = vNode.index
const canAdd = this.tempSelectList.indexOf(index) === -1 && this.selectList.indexOf(index) === -1
if (canAdd) {
this.tempSelectList.push(index)
this.tempQuickItems.push(item)
} else {
let idx = this.tempSelectList.indexOf(index)
if (idx === -1) {
this.selectList.splice(idx, 1)
this.quickItems.slice(idx, 1)
} else {
idx = this.selectList.indexOf(index)
this.tempSelectList.splice(idx, 1)
this.tempQuickItems.slice(idx, 1)
}
}
},
handlerLength (length) {
if (this.limitLength < length) {
this.$message({
message: '最多选择十个快捷菜单',
type: 'warning'
})
return false
}
}
}
}
</script>
<template lang="pug">
.menus-templete
el-row.meuns-nav
el-menu(@click="toggleMenus($event)")&attributes({
'default-active':"2",
'class':"el-menu-vertical",
'@open':"handleOpen",
'@close':"handleClose",
'text-color':'#2a3f54',
'active-text-color':'#fff'
})
el-submenu.menus-body.clear(index="1")
el-menu-item-group.menus-groups('v-for'="(item,index) in menus",':key'="index")
template(slot="title")
.main-menus
i(class="fa",':class'="item.ico", style={'margin-right':'5px'})
span.main-menus-title {{item.name}}
el-menu-item&attributes({
':index':"formatPathString(index,idx)",
'v-for':'(it,idx) in item.children',
':key':"idx"
})
el-menu-item-group.menus-tags
template(slot="title")
span {{it.name}}
el-menu-item&attributes({
'v-for':'(i,inx) in it.children',
':index':"formatPathString(index,idx,inx)",
':key':"inx",
'@click':'selectHandle(i,$event)',
':class':"{ active: selectList.indexOf(formatPathString(index,idx,inx)) > -1 }"
}) {{i.name}}
</template>
<style lang="stylus">
.menus-templete
overflow auto
padding-bottom 80px
height 700px
min-width 1280px
.el-menu--inline
display block
.menus-body
& > ul
display flex !important
flex-wrap nowrap
flex 1
flex-direction row
&:before,
&:after
display none
.el-menu
margin-bottom 0
.menus-tags
.el-menu-item
background #f5f5f5
line-height 30px
padding 0 10px
color #2a3f54
min-width 120px
width auto
cursor pointer
&:hover,
&:focus
background #f5f5f5
.menus-groups
& > ul
display flex
flex-wrap wrap
& > .el-menu-item-group__title
&:before
display none
.el-submenu__title
display none
.el-menu-item-group__title
position relative
padding-left 10px !important
margin-left 10px
color: #2a3f54;
font-size: 14px;
font-weight: bold;
position: relative;
&::before
content ''
position absolute
width 4px
height 4px;
border-radius 50%
left 0
top 50%
margin-top -2px
background #2a3f54
.main-menus-title
font-size 15px
.el-menu-item
display: flex
padding 0 10px !important
&.active
background: #1ABB9C !important
color: #fff !important
.fixed-footer
position fixed
display flex
justify-content center
align-items center
bottom 0
width 100%
background #fff
height 50px
</style>
<style lang="stylus" scoped>
.meuns-nav
position relative
overflow auto
.el-submenu,
.el-menu-item
min-width 120px
.menus-body
display flex
flex-direction row
.menus-groups
border-right: 1px solid #ddd;
margin: 15px 0;
padding 1px
max-width 356px
.main-menus
color #2a3f54
font-size 15px
font-weight bold
text-align left
.el-menu-item
height auto
line-height 1.5
overflow hidden
text-align left
&:hover,
&:focus
background none
</style>
<script>
export default {
name: 'menusTemplete',
data () {
return {
currentSelectIndex: -1,
num: 3
}
},
props: {
selectList: {
type: Array,
default () {
return []
}
}
},
filters: {
limit (array, num) {
if (num) {
return array
}
return array.slice(0, num)
},
pipeString (...args) {
return args.join('-')
}
},
computed: {
menus () {
const names = ['会员中心', '营销中心', '销售中心', '渠道中心', '系统设置', '平台管理'] // '智能营销', '分析师'
return this.$store.state.global.menus.filter(item => names.indexOf(item.name) > -1)
}
},
methods: {
clickItem () {
console.log(this)
},
handleOpen () {},
handleClose () {},
handleShowMenus () {
this.showMenusPanel = !this.showMenusPanel
},
toggleMenus (...args) {
console.log(args)
},
handleEditMenus () {},
selectHandle (item, vNode, ...args) {
this.currentSelectIndex = args.join('-')
this.$emit('choose', {item, vNode})
},
formatPathString (...args) {
return args.join('-')
}
}
}
</script>
# mescroll
## mescroll -- 精致的下拉刷新和上拉加载js框架 (JS framework for pull-refresh and pull-up-loading)
## http://www.mescroll.com
1. 原生js, 支持vue, 不依赖jquery,zepto
2. 一套代码多端运行. 完美运行于android,iOS,手机浏览器,兼容PC主流浏览器
3. 参数自由搭配, 随心定制, 轻松拓展
4. 主流APP案例, 丰富经典
5. MIT协议, 免费商用, 欢迎pull requests ~
6. <a target="_blank" href="//shang.qq.com/wpa/qunwpa?idkey=1067896895dabdf6cf11f4decb0be8bfd3687d3d208730bf2757238ba1948469">mescroll交流群: 633126761</a>
## 目录:
* <a href="https://github.com/mescroll/mescroll/releases" target="_blank">最新版本:1.3.8 (2018-09-29) 重要升级</a> <br/><br/>
* <a href="#功能亮点-">功能亮点 </a> <br/>
* <a href="#快速入门-">快速入门 </a> <br/>
* <a href="#图片懒加载-">图片懒加载 </a> <br/>
* <a href="#vue-cli">vue单文件 (理解原理)</a>
* <a href="#mescroll组件" target="_blank">mescroll组件 (推荐使用)</a>
* <a href="https://github.com/mescroll/mescroll/tree/master/vue-demo" target="_blank">vue-cli demo (建议看看)</a>
* <a href="http://www.mescroll.com/preview.html?name=list-products-vue" target="_blank">vue在线示例 (了解即可)</a>
* <a href="#基础案例-base-demos-"><b>基础案例 base demos</b></a> <br/>
* <a href="#中级案例-intermediate-demos-"><b>中级案例 intermediate demos</b></a> <br/>
* <a href="#高级案例-senior-demos-"><b>高级案例 senior demos</b></a> <br/><br/>
* <a href="#下载基础中级案例源码-">下载基础中级案例 </a> <br/>
* <a href="#获取高级案例源码-">获取高级案例 </a> <br/><br/>
* <a href="#api文档-">API文档 </a> <br/>
* <a href="#常用方法-">常用方法 </a> <br/>
* <a href="#其他方法-">其他方法 </a> <br/><br/>
* <a href="http://www.mescroll.com/qa.html?v=0929">常见问题 </a> <br/>
* <a href="http://www.mescroll.com/reward.html#tagRank">打赏排行榜 </a> <br/>
## 功能亮点 :
1. 自动判断和提示列表无任何数据或无更多数据
2. 支持监听列表滚动事件,无需手动判断处理列表的页码,时间等变量
3. 可指定列表滚动到任何位置,附带平滑效果一键滚动到顶部或底部
4. 可配置列表数据不满屏时,自动加载下一页
5. 一个界面可支持多个下拉刷新,上拉加载
6. 可临时锁定下拉刷新和上拉加载
7. 支持图片懒加载,可配置各种占位图与显示动画,上手超简单
## NPM
#### 特别感谢 @<a href="https://github.com/channg">channg</a> 帮忙整理发布NPM
```
npm install --save mescroll.js //不要使用cnpm安装
```
## 快速入门 :
#### 1. 引用 **mescroll.min.css** , **mescroll.min.js**
#### 2. 拷贝以下布局结构:
```
<div id="mescroll" class="mescroll"> //id可以改,而"mescroll"的class不能删
<div> //这个div不能删, 可以改成ul或者其他容器标签.
//内容...
</div>
</div>
```
#### 3. 固定mescroll的div高度. 推荐通过定位的方式,简单快捷: <a href="http://www.mescroll.com/qa.html#q2">(点此查看其他方法)</a>
```
.mescroll{
position: fixed;
top: 44px;
bottom: 0;
height: auto; /*如设置bottom:50px,则需height:auto才能生效*/
}
```
#### 4. 创建MeScroll对象:
```
var mescroll = new MeScroll("mescroll", { //第一个参数"mescroll"对应上面布局结构div的id (1.3.5版本支持传入dom对象)
down: {
callback: downCallback //下拉刷新的回调,别写成downCallback(),多了括号就自动执行方法了
},
up: {
callback: upCallback, //上拉加载回调,简写callback:function(page){upCallback(page);}
//以下是一些常用的配置,当然不写也可以的.
page: {
num: 0, //当前页 默认0,回调之前会加1; 即callback(page)会从1开始
size: 10, //每页数据条数,默认10
},
htmlNodata: '<p class="upwarp-nodata">亲,没有更多数据了~</p>',
noMoreSize: 5, //如果列表已无数据,可设置列表的总数量要大于5才显示无更多数据;避免列表数据过少(比如只有一条数据),显示无更多数据会不好看.这就是为什么无更多数据 有时候不显示的原因了.
toTop: {
//回到顶部按钮
src: "../img/mescroll-totop.png", //图片路径,默认null,支持网络图
offset: 1000, //列表滚动1000px才显示回到顶部按钮
},
empty: {
//列表第一页无任何数据时,显示的空提示布局; 需配置warpId才显示
warpId: "xxid", //父布局的id (1.3.5版本支持传入dom元素)
icon: "../img/mescroll-empty.png", //图标,默认null,支持网络图
tip: "暂无相关数据~" //提示
},
lazyLoad: {
use: true, // 是否开启懒加载,默认false
attr: 'imgurl', // 网络图片地址的属性名 (图片加载成功会自动移除改属性): <img imgurl='网络图 src='占位图''/>
offset: 200 // 超出可视区域多少px的图片仍可触发懒加载 默认200. 目的是提前加载可视区域外的部分图片
}
}
});
```
###### 温馨提示:
###### 1. 如果您的下拉刷新是重置列表数据,那么down完全可以不用配置,具体用法参考<a class="blue" href="http://www.mescroll.com/demo.html?v=0929">第一个基础案例</a>
###### 解析: down内部默认调用的是mescroll.resetUpScroll(),而resetUpScroll会将page.num=1,再触发up.callback,从而实现刷新列表数据
###### 2. 如果您的项目是在iOS的微信,QQ,Safari等浏览器访问的,建议配置up的isBounce为false,禁止ios的回弹效果; <a class="blue" href="http://www.mescroll.com/qa.html?v=0929#q10">解析(必读)</a>
#### 5. 处理回调:
```
//下拉刷新的回调
function downCallback(){
$.ajax({
url: 'xxxxxx',
success: function(data){
//联网成功的回调,隐藏下拉刷新的状态;
mescroll.endSuccess();//无参,注意此处无参
//设置数据
//setXxxx(data);//自行实现 TODO
},
error: function(data){
//联网失败的回调,隐藏下拉刷新的状态
mescroll.endErr();
}
});
}
//上拉加载的回调 page = {num:1, size:10}; num:当前页 从1开始, size:每页数据条数
function upCallback(page){
$.ajax({
url: 'xxxxxx?num='+ page.num +"&size="+ page.size,
success: function(curPageData){
//联网成功的回调,隐藏下拉刷新和上拉加载的状态;
//mescroll会根据传的参数,自动判断列表如果无任何数据,则提示空;列表无下一页数据,则提示无更多数据;
//方法一(推荐): 后台接口有返回列表的总页数 totalPage
//必传参数(当前页的数据个数, 总页数)
//mescroll.endByPage(curPageData.length, totalPage);
//方法二(推荐): 后台接口有返回列表的总数据量 totalSize
//必传参数(当前页的数据个数, 总数据量)
//mescroll.endBySize(curPageData.length, totalSize);
//方法三(推荐): 您有其他方式知道是否有下一页 hasNext
//必传参数(当前页的数据个数, 是否有下一页true/false)
//mescroll.endSuccess(curPageData.length, hasNext);
//方法四 (不推荐),会存在一个小问题:比如列表共有20条数据,每页加载10条,共2页.
//如果只根据当前页的数据个数判断,则需翻到第三页才会知道无更多数据
//如果传了hasNext,则翻到第二页即可显示无更多数据.
//mescroll.endSuccess(curPageData.length);
//提示:curPageData.length必传的原因:
// 1.使配置的noMoreSize生效
// 2.判断是否有下一页的首要依据: 当传的值小于page.size时,则一定会认为无更多数据. 比传入的totalPage, totalSize, hasNext具有更高的判断优先级
// 3.当传的值等于page.size时,才会取totalPage, totalSize, hasNext判断是否有下一页. 传totalPage, totalSize, hasNext主要目的是避免方法四描述的小问题
//设置列表数据
//setListData(curPageData);//自行实现 TODO
},
error: function(){
//联网失败的回调,隐藏下拉刷新和上拉加载的状态
mescroll.endErr();
}
});
}
```
--- 以上为mescroll最基本的用法,强烈建议您下载并查看 <a href="#基础案例-base-demos-">mescroll基础案例</a> , 发现mescroll更强大的功能 ~<br/>
--- 基础案例一共6个, 每个案例3分钟, 一共花您18分钟; 这18分钟您将了解mescroll在不同情况下应如何快速配置 ~<br/>
--- 特别建议您, 手动改改 <a href="http://www.mescroll.com/preview.html?name=mescroll-options">mescroll-options</a> 的每项配置, 观察修改后的效果, 轻松理解各项参数, 还会有意想不到的发现哦 ~<br/>
--- 磨刀不误砍柴工,心急吃不了热豆腐. 请静下心来体验与理解mescroll, 一定会让您事半功倍 ~<br/>
--- 如使用中有疑问, 请先查看 <a href="http://www.mescroll.com/qa.html?v=0929">常见问题专区</a> ~<br/><br/>
## 图片懒加载
mescroll的图片懒加载功能是1.3.6新增的,使用超简单 :
##### 1. 确保mescroll至少更新到1.3.6版本
##### 2. 初始化mescroll的时候,在up中配置lazyLoad的use为true :
```
var mescroll = new MeScroll("mescroll", {
up: {
lazyLoad: {
use: true, // 是否开启懒加载,默认false
attr: 'imgurl', // 网络图片地址的属性名 (图片加载成功会自动移除改属性): <img imgurl='网络图 src='占位图''/>
showClass: 'mescroll-lazy-in', // 图片加载成功的显示动画: 渐变显示,参见mescroll.css
delay: 500, // 列表滚动的过程中每500ms检查一次图片是否在可视区域,如果在可视区域则加载图片
offset: 200 // 超出可视区域200px的图片仍可触发懒加载,目的是提前加载部分图片
}
}
})
```
##### 3. 设置img或div的 imgurl 属性, 值为图片的网络地址
```
img标签: <img imgurl="网络图" src="占位图"/> // 占位图直接在src设置; 图片加载成功,就会替换src的占位图
div或其他标签: <div imgurl="网络图" style="background-image: url(占位图)"></div>; // 占位图在css中设置; 图片以背景图的形式展示
```
##### 4. 至此mescroll的懒加载功能已经可以正常使用了,mescroll在列表滚动时会自动加载可视区域内的图片.另外,有时候您可能会动态添加或修改图片,希望手动触发一下懒加载, 那么只需调用 mescroll.lazyLoad() 或 mescroll.endByPage() 或 mescroll.endBySize() 或 mescroll.endSuccess() 即可.
##### 5. mescroll的所有案例都开启了懒加载,您可参考体验. <a href="http://www.mescroll.com/preview.html?name=list-mescroll-lazy" target="_blank">当然这里还有专门介绍懒加载的案例~</a>
## vue-cli
在vue单文件中的使用步骤 (至少更新到1.3.5版本):
##### 1. 执行npm命令安装mescroll : &nbsp; &nbsp; **npm install --save mescroll.js** //不要使用cnpm安装
##### 2. 引入mescroll.min.js : &nbsp; &nbsp; **import MeScroll from 'mescroll.js'**
##### 3. 引入mescroll.min.css : &nbsp; &nbsp; **import 'mescroll.js/mescroll.min.css'**
##### 4. vue单文件示例 :
```
<template>
<div>
<!--mescroll滚动区域的基本结构,为避免id重复导致的多次初始化,这里使用ref-->
<div ref="mescroll" class="mescroll">
<div>
<!--内容...-->
</div>
</div>
</div>
</template>
<script>
//引入mescroll.min.js和mescroll.min.css
import MeScroll from 'mescroll.js'
import 'mescroll.js/mescroll.min.css'
export default {
name: 'xxx',
data() {
return {
mescroll: null, //mescroll实例对象
dataList:[] //列表数据
}
},
mounted: function () {
//创建MeScroll对象
this.mescroll = new MeScroll(this.$refs.mescroll, { // 在vue的mounted生命周期初始化mescroll,确保此处配置的ref有值
// down:{}, //下拉刷新的配置. (如果下拉刷新和上拉加载处理的逻辑是一样的,则down可不用写了)
up: {
callback: this.upCallback,
// 以下是一些常用的配置,当然不写也可以的.
page: {
num: 0, //当前页 默认0,回调之前会加1; 即callback(page)会从1开始
size: 10, //每页数据条数,默认10
},
htmlNodata: '<p class="upwarp-nodata">亲,没有更多数据了~</p>',
noMoreSize: 5, //如果列表已无数据,可设置列表总数大于5才显示无更多数据;避免列表数据过少(比如只有一条数据),显示无更多数据会不好看
toTop: {
//回到顶部按钮
src: "./static/mescroll/mescroll-totop.png", //图片路径,默认null,支持网络图
offset: 1000, //列表滚动1000px才显示回到顶部按钮
},
empty: {
//列表第一页无任何数据时,显示的空提示布局; 需配置warpId才显示
warpId: "xxid", //父布局的id (1.3.5版本支持传入dom元素)
icon: "./static/mescroll/mescroll-empty.png", //图标,默认null,支持网络图
tip: "暂无相关数据~", //提示
}
}
});
},
methods: {
//上拉回调 page = {num:1, size:10}; num:当前页 ,默认从1开始; size:每页数据条数,默认10
upCallback(page) {
//联网请求
axios.get("xxxxxx", {
params: {
num: page.num, //页码
size: page.size //每页长度
}
}).then((response)=> {
//请求的列表数据
let arr = response.data;
//如果是第一页需手动制空列表
if (page.num == 1) this.dataList = [];
//把请求到的数据添加到列表
this.dataList = this.dataList.concat(arr);
//数据渲染成功后,隐藏下拉刷新的状态
this.$nextTick(() => {
this.mescroll.endSuccess(arr.length);
})
}).catch((e)=> {
//联网失败的回调,隐藏下拉刷新和上拉加载的状态;
this.mescroll.endErr();
})
}
},
// 进入路由时,恢复列表状态
beforeRouteEnter (to, from, next) { // 如果没有配置回到顶部按钮或isBounce,则beforeRouteEnter不用写
next(vm => {
if (vm.mescroll) {
// 恢复到之前设置的isBounce状态
if (vm.mescroll.lastBounce != null) vm.mescroll.setBounce(vm.mescroll.lastBounce)
// 滚动到之前列表的位置 (注意:路由使用keep-alive才生效)
if (vm.mescroll.lastScrollTop) {
vm.mescroll.setScrollTop(vm.mescroll.lastScrollTop)
setTimeout(() => { // 需延时,因为setScrollTop内部会触发onScroll,可能会渐显回到顶部按钮
vm.mescroll.setTopBtnFadeDuration(0)// 设置回到顶部按钮显示时无渐显动画
}, 16)
}
}
})
},
// 离开路由时,记录列表状态
beforeRouteLeave (to, from, next) { // 如果没有配置回到顶部按钮或isBounce,则beforeRouteLeave不用写
if (this.mescroll) {
this.mescroll.lastBounce = this.mescroll.optUp.isBounce// 记录当前是否禁止ios回弹
this.mescroll.setBounce(true) // 允许bounce
this.mescroll.lastScrollTop = this.mescroll.getScrollTop()// 记录当前滚动条的位置
this.mescroll.hideTopBtn(0)// 隐藏回到顶部按钮,无渐隐动画
}
next()
}
}
</script>
<style scope>
/*通过fixed固定mescroll的高度*/
.mescroll {
position: fixed;
top: 44px;
bottom: 0;
height: auto;
}
</style>
```
##### 以上写法有些繁琐,在vue中强烈建议使用mescroll组件,简单快捷:
## mescroll组件
mescroll组件使用步骤 (至少更新到1.3.5版本):
##### 1. 执行npm命令安装mescroll : &nbsp; &nbsp; **npm install --save mescroll.js** //不要使用cnpm安装
##### 2. 引入mescroll组件 : &nbsp; &nbsp; **import MescrollVue from 'mescroll.js/mescroll.vue'**
##### 3. vue单文件示例 :
```
<template>
<div>
<!--mescroll滚动区域的基本结构-->
<mescroll-vue ref="mescroll" :down="mescrollDown" :up="mescrollUp" @init="mescrollInit">
<!--内容...-->
</mescroll-vue>
</div>
</template>
<script>
// 引入mescroll的vue组件
import MescrollVue from 'mescroll.js/mescroll.vue'
export default {
name: 'xxx',
components: {
MescrollVue // 注册mescroll组件
},
data () {
return {
mescroll: null, // mescroll实例对象
mescrollDown:{}, //下拉刷新的配置. (如果下拉刷新和上拉加载处理的逻辑是一样的,则mescrollDown可不用写了)
mescrollUp: { // 上拉加载的配置.
callback: this.upCallback, // 上拉回调,此处可简写; 相当于 callback: function (page, mescroll) { getListData(page); }
//以下是一些常用的配置,当然不写也可以的.
page: {
num: 0, //当前页 默认0,回调之前会加1; 即callback(page)会从1开始
size: 10 //每页数据条数,默认10
},
htmlNodata: '<p class="upwarp-nodata">亲,没有更多数据了~</p>',
noMoreSize: 5, //如果列表已无数据,可设置列表总数大于5才显示无更多数据;避免列表数据过少(比如只有一条数据),显示无更多数据会不好看
toTop: {
//回到顶部按钮
src: "./static/mescroll/mescroll-totop.png", //图片路径,默认null,支持网络图
offset: 1000 //列表滚动1000px才显示回到顶部按钮
},
empty: {
//列表第一页无任何数据时,显示的空提示布局; 需配置warpId才显示
warpId: "xxid", //父布局的id (1.3.5版本支持传入dom元素)
icon: "./static/mescroll/mescroll-empty.png", //图标,默认null,支持网络图
tip: "暂无相关数据~" //提示
}
},
dataList: [] // 列表数据
}
},
beforeRouteEnter (to, from, next) { // 如果没有配置回到顶部按钮或isBounce,则beforeRouteEnter不用写
next(vm => {
vm.$refs.mescroll.beforeRouteEnter() // 进入路由时,滚动到原来的列表位置,恢复回到顶部按钮和isBounce的配置
})
},
beforeRouteLeave (to, from, next) { // 如果没有配置回到顶部按钮或isBounce,则beforeRouteLeave不用写
this.$refs.mescroll.beforeRouteLeave() // 退出路由时,记录列表滚动的位置,隐藏回到顶部按钮和isBounce的配置
next()
},
methods: {
// mescroll组件初始化的回调,可获取到mescroll对象
mescrollInit (mescroll) {
this.mescroll = mescroll
},
// 上拉回调 page = {num:1, size:10}; num:当前页 ,默认从1开始; size:每页数据条数,默认10
upCallback (page, mescroll) {
// 联网请求
axios.get('xxxxxx', {
params: {
num: page.num, // 页码
size: page.size // 每页长度
}
}).then((response) => {
// 请求的列表数据
let arr = response.data
// 如果是第一页需手动制空列表
if (page.num === 1) this.dataList = []
// 把请求到的数据添加到列表
this.dataList = this.dataList.concat(arr)
// 数据渲染成功后,隐藏下拉刷新的状态
this.$nextTick(() => {
mescroll.endSuccess(arr.length)
})
}).catch((e) => {
// 联网失败的回调,隐藏下拉刷新和上拉加载的状态;
mescroll.endErr()
})
}
}
}
</script>
<style scope>
/*以fixed的方式固定mescroll的高度*/
.mescroll {
position: fixed;
top: 44px;
bottom: 0;
height: auto;
}
</style>
```
## API文档 :
#### <a href="http://www.mescroll.com/api.html?v=0929#options" target="_blank">前往官网查看 >> </a>
```
//创建mescroll对象
var mescroll = new MeScroll(id或dom对象, { down: {下拉刷新的配置参数}, up: {上拉加载的配置参数} });
```
<table border="1" cellspacing="0">
<tr align="center"><td colspan="3"><b>down 下拉刷新的配置参数</b></td></tr>
<tr align="center">
<td>参数名</td>
<td>默认值</td>
<td>说明</td>
</tr>
<tr align="center">
<td>use</td>
<td>true</td>
<td>是否启用下拉刷新</td>
</tr>
<tr align="center">
<td>auto</td>
<td>true</td>
<td>是否在初始化完毕之后自动执行下拉刷新的回调</td>
</tr>
<tr align="center">
<td>autoShowLoading</td>
<td>false</td>
<td>当设置auto=true时(在初始化完毕之后自动执行下拉刷新的回调)<br/>是否显示下拉刷新的进度<br/>需配置down的callback才生效</td>
</tr>
<tr align="center">
<td>isLock</td>
<td>false</td>
<td>是否锁定下拉刷新</td>
</tr>
<tr align="center">
<td>isBoth</td>
<td>false</td>
<td>下拉刷新时,如果滑动到列表底部是否可以同时触发上拉加载</td>
</tr>
<tr align="center">
<td>offset</td>
<td>80</td>
<td>在列表顶部,下拉大于80px,松手即可触发下拉刷新的回调</td>
</tr>
<tr align="center">
<td>outOffsetRate</td>
<td>0.2</td>
<td>在列表顶部,下拉的距离大于offset时,改变下拉区域高度比例;值越接近0,高度变化越小,表现为越往下越难拉</td>
</tr>
<tr align="center">
<td>bottomOffset</td>
<td>20</td>
<td>当手指touchmove位置在距离body底部20px范围内的时候结束上拉刷新,避免Webview嵌套导致touchend事件不执行<br/>这是1.2.1版本新增的配置,请检查最新版~</td>
</tr>
<tr align="center">
<td>minAngle</td>
<td>45</td>
<td>触发下拉最少要偏移的角度(滑动的轨迹与水平线的锐角值),取值区间 [0,90];默认45度,即向下滑动的角度大于45度(方位角为45°~145°及225°~315°)则触发下拉;而小于45度,将不触发下拉,避免与左右滑动的轮播等组件冲突;<br/>注意:没有必要配置超出[0,90]区间的值,否则角度限制无效; 因为假设配置60, 生效的方位角就已经是60°到120° 和 240°到300°的范围了;<br/>这是1.1.6版本新增的配置,请检查最新版~</td>
</tr>
<tr align="center">
<td>hardwareClass</td>
<td>"mescroll-hardware"</td>
<td>硬件加速样式,解决iOS下拉因隐藏进度条而闪屏的问题,参见mescroll.css</td>
</tr>
<tr align="center">
<td>warpClass</td>
<td>"mescroll-downwarp"</td>
<td>下拉刷新的布局容器样式,参见mescroll.css</td>
</tr>
<tr align="center">
<td>mustToTop<br/>1.3.7版本新增</td>
<td>false</td>
<td>是否滚动条必须在顶部,才可以下拉刷新.默认false. 当您发现下拉刷新会闪白屏时,设置true即可修复.</td>
</tr>
<tr align="center">
<td>warpId</td>
<td>null</td>
<td>可配置下拉刷新的布局添加到指定id的div <br/> 默认不配置,默认添加到mescrollId</td>
</tr>
<tr align="center">
<td>resetClass</td>
<td>"mescroll-downwarp-reset"</td>
<td>下拉刷新高度重置的动画,参见mescroll.css</td>
</tr>
<tr align="center">
<td>textInOffset<br/>1.3.7版本新增</td>
<td>'下拉刷新'</td>
<td>下拉的距离在offset范围内的提示文本</td>
</tr>
<tr align="center">
<td>textOutOffset<br/>1.3.7版本新增</td>
<td>'释放更新'</td>
<td>下拉的距离大于offset范围的提示文本</td>
</tr>
<tr align="center">
<td>textLoading<br/>1.3.7版本新增</td>
<td>'加载中 ...'</td>
<td>加载中的提示文本</td>
</tr>
<tr align="center">
<td>htmlContent</td>
<td>'&lt;p class="downwarp-progress"&gt;&lt;/p&gt;&lt;p class="downwarp-tip"&gt;&lt;/p&gt;'</td>
<td>下拉刷新的布局内容</td>
</tr>
<tr align="center">
<td>inited</td>
<td>function(mescroll, downwarp) { ... }</td>
<td>下拉刷新初始化完毕的回调(mescroll实例对象,下拉刷新容器dom对象)</td>
</tr>
<tr align="center">
<td>inOffset</td>
<td>function(mescroll) { ... }</td>
<td>下拉的距离进入offset范围内那一刻的回调(mescroll实例对象)</td>
</tr>
<tr align="center">
<td>outOffset</td>
<td>function(mescroll) { ... }</td>
<td>下拉的距离大于offset那一刻的回调(mescroll实例对象)</td>
</tr>
<tr align="center">
<td>onMoving</td>
<td>function(mescroll, rate, downHight) { ... }</td>
<td>下拉过程中的回调,滑动过程一直在执行; rate下拉区域当前高度与指定距离的比值(inOffset: rate<1; outOffset: rate>=1); downHight当前下拉区域的高度</td>
</tr>
<tr align="center">
<td>beforeLoading</td>
<td>function(mescroll, downwarp) { return false; }</td>
<td>准备触发下拉刷新的回调; 如果要完全自定义下拉刷新,那么return true,此时将不触发showLoading和callback回调; 参考案例【淘宝 v6.8.0】</td>
</tr>
<tr align="center">
<td>showLoading</td>
<td>function(mescroll) { ... }</td>
<td>显示下拉刷新进度的回调</td>
</tr>
<tr align="center">
<td>afterLoading</td>
<td>function(mescroll) { return 0 }</td>
<td>结束加载中,准备隐藏下拉的回调 <br/>返回结束下拉的延时执行时间,默认0ms<br/>常用于结束下拉之前再显示另外一小段动画,才去隐藏下拉刷新的场景, 参考案例【dotJump】</td>
</tr>
<tr align="center">
<td>callback</td>
<td>function(mescroll) { mescroll.resetUpScroll(); }</td>
<td>下拉刷新的回调; 默认重置上拉加载列表为第一页</td>
</tr>
</table>
<br/>
<table border="1" cellspacing="0">
<tr align="center"><td colspan="3"><b>up 上拉加载的配置参数</b></td></tr>
<tr align="center">
<td>参数名</td>
<td>默认值</td>
<td>说明</td>
</tr>
<tr align="center">
<td>use</td>
<td>true</td>
<td>是否启用上拉加载</td>
</tr>
<tr align="center">
<td>auto</td>
<td>false</td>
<td>是否在初始化完毕之后自动执行上拉加载的回调</td>
</tr>
<tr align="center">
<td>isLock</td>
<td>false</td>
<td>是否锁定上拉加载</td>
</tr>
<tr align="center">
<td>isBoth</td>
<td>false</td>
<td>上拉加载时,如果滑动到列表顶部是否可以同时触发下拉刷新</td>
</tr>
<tr align="center">
<td>isBounce</td>
<td>true</td>
<td>是否允许ios的bounce回弹;默认true,允许回弹 (v 1.3.0新增)</td>
</tr>
<tr align="center">
<td>offset</td>
<td>100</td>
<td>列表滚动到距离底部小于100px,即可触发上拉加载的回调</td>
</tr>
<tr align="center">
<td>noMoreSize</td>
<td>5</td>
<td>如果列表已无数据,可设置列表的总数量要大于5条才显示无更多数据;避免列表数据过少(比如只有一条数据),显示无更多数据会不好看</td>
</tr>
<tr align="center">
<td>toTop</td>
<td align="left">{ <br/>
warpId: null, <br/>
src: null, <br/>
html: null, <br/>
offset: 1000, <br/>
warpClass: "mescroll-totop", <br/>
showClass: "mescroll-fade-in", <br/>
hideClass: "mescroll-fade-out", <br/>
duration: 300, <br/>
supportTap: false <br/>
btnClick : null <br/>
}</td>
<td align="left">回到顶部按钮的配置: <br/>
warpId: 父布局的id; 默认添加在body中 (1.3.5版本支持传入dom元素) <br/>
src: 图片路径,必须配置src才会显示回到顶部按钮,不配置不显示 <br/>
html: 标签内容,默认null; 如果同时设置了src,则优先取src (2017/12/10新增) <br/>
offset: 列表滚动1000px显示回到顶部按钮 <br/>
warpClass: 按钮样式,参见mescroll.css <br/>
showClass: 显示样式,参见mescroll.css <br/>
hideClass: 隐藏样式,参见mescroll.css <br/>
duration: 回到顶部的动画时长,默认300ms <br/>
supportTap: 如果您的运行环境支持tap,则可配置true,可减少点击延时,快速响应事件;默认false,通过onclick添加点击事件; (v 1.3.0 新增) (注:微信和PC无法响应tap事件) <br/>
btnClick: 点击按钮的回调; 提示:如果在回调里return true,将不执行回到顶部的操作
</td>
</tr>
<tr align="center">
<td>loadFull</td>
<td align="left">{ <br/>
use: false, <br/>
delay: 500 <br/>
}</td>
<td align="left">
use: 列表数据过少,不足以滑动触发上拉加载,是否自动加载下一页,直到满屏或者无更多数据为止; 默认false,因为可通过调高page.size避免这个情况 <br/>
delay: 延时执行的毫秒数; 延时是为了保证列表数据或占位的图片都已初始化完成,且下拉刷新上拉加载中区域动画已执行完毕;
</td>
</tr>
<tr align="center">
<td>empty</td>
<td align="left">{ <br/>
warpId: null, <br/>
icon: null, <br/>
tip: "暂无相关数据~", <br/>
btntext: "", <br/>
btnClick: null, <br/>
supportTap: false <br/>
}</td>
<td align="left">列表第一页无任何数据时,显示的空提示布局; 需配置warpId或clearEmptyId才生效 <br/>
warpId: 父布局的id; 如果此项有值,将不使用clearEmptyId的值; (1.3.5版本支持传入dom元素) <br/>
icon: 空布局的图标路径 <br/>
tip: 提示文本 <br/>
btntext: 按钮文本 <br/>
btnClick: 点击按钮的回调 <br/>
supportTap: 如果您的运行环境支持tap,则可配置true,可减少点击延时,快速响应事件;默认false,通过onclick添加点击事件; (v 1.3.0 新增) (注:微信和PC无法响应tap事件) <br/>
</td>
</tr>
<tr align="center">
<td>clearId</td>
<td>null</td>
<td>加载第一页时需清空数据的列表id; 如果此项有值,将不使用clearEmptyId的值; 在vue中使用,则无需配置此项</td>
</tr>
<tr align="center">
<td>clearEmptyId</td>
<td>null</td>
<td>相当于同时设置了clearId和empty.warpId; 简化写法; 在vue中使用,不能配置此项 (1.3.5版本支持传入dom元素)</td>
</tr>
<tr align="center">
<td>hardwareClass</td>
<td>"mescroll-hardware"</td>
<td>硬件加速样式,使动画更流畅,参见mescroll.css</td>
</tr>
<tr align="center">
<td>warpClass</td>
<td>"mescroll-upwarp"</td>
<td>上拉加载的布局容器样式,参见mescroll.css</td>
</tr>
<tr align="center">
<td>warpId</td>
<td>null</td>
<td>可配置上拉加载的布局添加到指定id的div;默认不配置,默认添加到mescrollId</td>
</tr>
<tr align="center">
<td>htmlLoading</td>
<td>'&lt;p class="upwarp-progress mescroll-rotate"&gt;&lt;/p&gt;&lt;p class="upwarp-tip"&gt;加载中..&lt;/p&gt;'</td>
<td>上拉加载中的布局,参见mescroll.css</td>
</tr>
<tr align="center">
<td>htmlNodata</td>
<td>'&lt;p class="upwarp-nodata"&gt;-- END --&lt;/p&gt;'</td>
<td>无数据的布局,参见mescroll.css</td>
</tr>
<tr align="center">
<td>inited</td>
<td>function(mescroll, upwarp){}</td>
<td>初始化完毕的回调; 回调(mescroll实例, upwarp上拉加载的布局Dom对象)</td>
</tr>
<tr align="center">
<td>showLoading</td>
<td>function(mescroll, upwarp){ ... }</td>
<td>显示上拉加载中的回调; 回调(mescroll实例, upwarp上拉加载的布局Dom对象)</td>
</tr>
<tr align="center">
<td>showNoMore</td>
<td>function(mescroll, upwarp){ ... }</td>
<td>显示无更多数据的回调; 回调(mescroll实例, upwarp上拉加载的布局Dom对象)</td>
</tr>
<tr align="center">
<td>onScroll</td>
<td>null</td>
<td>列表滑动监听, 默认null<br/>例 onScroll : function(mescroll, y, isUp){ ... };<br/>y为列表当前滚动条的位置;<br/>isUp=true向上滑,isUp=false向下滑)<br/>isUp是1.2.1版本新增的配置,请检查最新版~</td>
</tr>
<tr align="center">
<td>callback</td>
<td>function(page,mescroll){}</td>
<td>上拉加载的回调; 回调(page对象,mescroll实例), 其中page={num:页码, size:每页数据的数量, time:第一页数据的时间}</td>
</tr>
<tr align="center">
<td>page</td>
<td align="left">{ <br/>num:0, <br/> size:10, <br/> time:null <br/>}</td>
<td align="left">num: 当前页码,默认0,回调之前会加1,即callback(page)会从1开始; <br/>size: 每页数据的数量; <br/>time: 加载第一页数据服务器返回的时间;防止用户翻页时,后台新增了数据从而导致下一页数据重复;</td>
</tr>
<tr>
<td align="center">scrollbar</td>
<td>{<br/>&nbsp; use : ... , <br/>&nbsp; barClass : "mescroll-bar" <br/>}</td>
<td>use : 是否开启自定义滚动条; PC端默认true开启自定义滚动条; 移动端默认false不使用 <br/>barClass : 自定义滚动条的样式; 参见mescroll.css</td>
</tr>
<tr>
<td align="center">lazyLoad<br/>(1.3.6新增)</td>
<td>
{<br/>
use: false,<br/>
attr: 'imgurl',<br/>
showClass: 'mescroll-lazy-in',<br/>
delay: 500,<br/>
offset: 200<br/>
}
</td>
<td>
use: 是否开启懒加载,默认false<br/>
attr: 标签中网络图片地址的属性名,默认"imgurl"<br/>
showClass: 显示样式:渐变显示,参见mescroll.css<br/>
delay: 列表滚动的过程中检查一次图片是否在可视区域的时间间隔,默认500 (单位ms)<br/>
offset: 超出可视区域多少px的图片仍可触发懒加载 默认200
</td>
</tr>
</table>
## 常用方法 :
#### <a href="http://www.mescroll.com/api.html#methods" target="_blank">前往官网查看 >> </a>
<table border="1" cellspacing="0">
<tr align="center">
<td>方法名</td>
<td>说明</td>
</tr>
<tr align="center">
<td align="left">mescroll.endByPage(dataSize, totalPage, systime);<br/>(v 1.2.1 新增)</td>
<td align="left">隐藏下拉刷新和上拉加载的状态, 在联网获取数据成功后调用<br />
dataSize : 当前页获取的数据总数(注意是当前页)<br />
totalPage : 列表的总页数<br/>
systime : 加载第一页数据的服务器时间 (可空);
</td>
</tr>
<tr align="center">
<td align="left">mescroll.endBySize(dataSize, totalSize, systime);<br/>(v 1.2.1 新增)</td>
<td align="left">隐藏下拉刷新和上拉加载的状态, 在联网获取数据成功后调用<br />
dataSize : 当前页获取的数据总数(注意是当前页)<br />
totalSize : 列表的总数据量<br/>
systime : 加载第一页数据的服务器时间 (可空);
</td>
</tr>
<tr align="center">
<td align="left">mescroll.endSuccess(dataSize, hasNext, systime);<br/>(v 1.2.1 调整)</td>
<td align="left">隐藏下拉刷新和上拉加载的状态, 在联网获取数据成功后调用<br />
dataSize : 当前页获取的数据量(注意是当前页)<br />
hasNext : 是否有下一页数据true/false<br/>
systime : 加载第一页数据的服务器时间 (可空);
</td>
</tr>
<tr align="center">
<td>mescroll.endErr();</td>
<td>隐藏下拉刷新和上拉加载的状态, 在联网获取数据失败后调用;<br/>mescroll内部会自动恢复原来的页码,时间等变量;</td>
</tr>
<tr align="center">
<td>mescroll.resetUpScroll( isShowLoading );</td>
<td>重置列表为第一页 (常用于列表筛选条件变化或切换菜单时重新刷新列表数据)<br />内部实现: 把page.num=1,再主动触发up.callback<br />isShowLoading 是否显示进度布局; <br />1.默认null,不传参,则显示上拉加载的进度布局 <br />2.传参true, 则显示下拉刷新的进度布局<br />3.传参false,则不显示上拉和下拉的进度 (常用于静默更新列表数据)</td>
</tr>
<tr align="center">
<td>mescroll.triggerDownScroll();</td>
<td>主动触发下拉刷新</td>
</tr>
<tr align="center">
<td>mescroll.triggerUpScroll();</td>
<td>主动触发上拉加载</td>
</tr>
<tr align="center">
<td>mescroll.setPageNum(num);<br/>(v 1.2.5 新增)</td>
<td>设置当前page.num的值</td>
</tr>
<tr align="center">
<td>mescroll.setPageSize(size);<br/>(v 1.2.5 新增)</td>
<td>设置当前page.size的值</td>
</tr>
<tr align="center">
<td>mescroll.scrollTo( y, t );</td>
<td>滚动列表到指定位置 ( y=0回到列表顶部; 如需滚动到列表底部,可设置y很大的值,比如y=99999 ); t时长,单位ms,默认300</td>
</tr>
<tr align="center">
<td>mescroll.optDown;</td>
<td>获取下拉刷新的配置</td>
</tr>
<tr align="center">
<td>mescroll.optUp;</td>
<td>获取上拉加载的配置</td>
</tr>
<tr align="center">
<td>mescroll.lockDownScroll( isLock );</td>
<td>锁定下拉刷新 ( isLock=ture,null 锁定 ; isLock=false 解锁 )</td>
</tr>
<tr align="center">
<td>mescroll.lockUpScroll( isLock );</td>
<td>锁定上拉加载 ( isLock=ture,null 锁定 ; isLock=false 解锁 )</td>
</tr>
<tr align="center">
<td>mescroll.os<br/>(v 1.2.5 新增)</td>
<td>
<b>mescroll.os.ios</b> 为true, 则是ios设备;<br/>
<b>mescroll.os.android</b> 为true, 则是android设备;<br/>
<b>mescroll.os.pc</b> 为true, 则是PC端;
</td>
</tr>
<tr align="center">
<td>mescroll.setBounce(boolean)<br/>(v 1.3.0 新增)</td>
<td>
<b>mescroll.setBounce(true)</b> 允许bounce;<br/>
<b>mescroll.setBounce(false)</b> 禁止bounce
</td>
</tr>
<tr align="center">
<td>mescroll.lazyLoad(delay)<br/>(v 1.3.6 新增)</td>
<td>
主动触发懒加载: 自动加载可视区域的图片.<br />
delay:延时加载图片的时间,默认500ms.目的是确保dom元素已渲染完成.
</td>
</tr>
</table>
## 其他方法 :
#### <a href="http://www.mescroll.com/api.html#others" target="_blank">前往官网查看 >> </a>
<table border="1" cellspacing="0">
<tr align="center"><td colspan="2">以下方法不常用,您可灵活运用于更复杂的场景</tr>
<tr align="center">
<td width="288px">mescroll.showDownScroll();</td>
<td width="600px">显示下拉刷新的进度布局<br/>
mescroll.triggerDownScroll() 和 mescroll.resetUpScroll() 内部有调用</td>
</tr>
<tr align="center">
<td>mescroll.endDownScroll();</td>
<td>隐藏下拉刷新的进度布局<br/>
mescroll.endSuccess() 和 mescroll.endErr() 内部有调用</td>
</tr>
<tr align="center">
<td>mescroll.showUpScroll();</td>
<td>显示上拉加载的进度布局<br/>
mescroll.triggerDownScroll() 和 mescroll.resetUpScroll() 内部有调用</td>
</tr>
<tr align="center">
<td>mescroll.showNoMore();</td>
<td>显示上拉无更多数据的布局<br/>
mescroll.endUpScroll() 内部有调用</td>
</tr>
<tr align="center">
<td>mescroll.hideUpScroll(displayAble);</td>
<td>隐藏上拉加载的布局<br/>
mescroll.endUpScroll() 内部有调用<br/>
1.3.5新增参数 displayAble: 是否通过display:none隐藏, 默认false通过visibility:hidden的方式隐藏
</td>
</tr>
<tr align="center">
<td>mescroll.clearDataList();</td>
<td>清空上拉加载的数据列表<br/>
mescroll.resetUpScroll() 和 mescroll.endSuccess() 内部有调用</td>
</tr>
<tr align="center">
<td>mescroll.loadFull();</td>
<td>检查如果加载的数据过少,无法触发上拉加载时,则自动加载下一页,直到满屏或无数据<br/>
此方法最好在列表的图片数据加载完成之后调用,以便计算列表内容高度的准确性<br/>
mescroll.endSuccess() 内部有调用</td>
</tr>
<tr align="center">
<td>mescroll.showEmpty();</td>
<td>显示无任何数据的空布局<br/>
mescroll.endSuccess() 内部有调用</td>
</tr>
<tr align="center">
<td>mescroll.removeEmpty();</td>
<td>移除无任何数据的空布局<br/>
mescroll.endSuccess() 内部有调用</td>
</tr>
<tr align="center">
<td>mescroll.showTopBtn(time);</td>
<td>显示回到顶部的按钮<br/>time: 显示的动画时长,默认0.5秒 (1.3.5版本新增参数)</td>
</tr>
<tr align="center">
<td>mescroll.hideTopBtn(time);</td>
<td>隐藏回到顶部的按钮 <br/>time: 隐藏的动画时长,默认0.5秒 (1.3.5版本新增参数)</td>
</tr>
<tr align="center">
<td>mescroll.setTopBtnFadeDuration(time);<br/>(1.3.5版本新增)</td>
<td>设置回到顶部按钮的显示和隐藏的动画时长 <br/>time: 显示隐藏动画时长,默认0.5秒</td>
</tr>
<tr align="center">
<td>mescroll.getScrollTop();</td>
<td>获取滚动条的位置y; 也可以在up配置onScroll监听滚动条的位置</td>
</tr>
<tr align="center">
<td>mescroll.getBodyHeight();</td>
<td>获取body的高度 </td>
</tr>
<tr align="center">
<td>mescroll.getClientHeight();</td>
<td>获取滚动容器的高度 </td>
</tr>
<tr align="center">
<td>mescroll.getScrollHeight();</td>
<td>获取滚动内容的高度 </td>
</tr>
<tr align="center">
<td>mescroll.getToBottom();<br/>(v 1.3.0新增)</td>
<td>获取当前滚动条到底部的距离 </td>
</tr>
<tr align="center">
<td>mescroll.getStep(star, end, callback, t, rate);<br/>(v 1.2.8 新增) </td>
<td align="left">
star : 开始值; <br/>
end : 结束值; <br/>
callback(step,timer) : 回调 function(step,timer), <br/>
t : 计步时长; 传0则直接回调end值; 不传则默认300ms ; <br/>
rate : 周期; 不传则默认30ms计步一次 ; <br/>
此方法相当于默认在300ms内,每30ms返回star到end之间的阶梯值step; 可用于模拟帧动画 <br/>
比如mescroll的回到顶部缓冲动画,轮播导航案例的顶部菜单滚动都是通过getStep实现<br/>
(注: 您可根据实际情况在 callback 通过 window.clearInterval(timer) 提前结束计步器)
</td>
</tr>
<tr align="center">
<td>mescroll.version;<br/>(v 1.3.0新增)</td>
<td>mescroll的版本号</td>
</tr>
<tr align="center">
<td>mescroll.destroy();</td>
<td>销毁mescroll</td>
</tr>
</table>
## 基础案例 base demos :
#### <a href="http://www.mescroll.com/demo.html" target="_blank">前往官网查看 >> </a>
#### 1. 【商品列表】演示下拉刷新重置列表数据
#### ---------- <a href="http://www.mescroll.com/preview.html?name=list-products" target="_blank">在线体验 </a> ---------- [查看源码](https://github.com/mescroll/mescroll/blob/master/demo/base/list-products.html) ----------
![](http://oux5x2xxe.bkt.clouddn.com/1508205320970list-products.gif)
<br/><br/>
#### 2. 【新闻列表】演示下拉刷新添加新数据到列表顶部
#### ---------- <a href="http://www.mescroll.com/preview.html?name=list-news" target="_blank">在线体验 </a> ---------- [查看源码](https://github.com/mescroll/mescroll/blob/master/demo/base/list-news.html) ----------
![](http://oux5x2xxe.bkt.clouddn.com/1508205314004list-news.gif)
<br/><br/>
#### 3. 【单mescroll】演示每次切换菜单都重置列表,不缓存数据
#### ---------- <a href="http://www.mescroll.com/preview.html?name=list-mescroll-one" target="_blank">在线体验 </a> ---------- [查看源码](https://github.com/mescroll/mescroll/blob/master/demo/base/list-mescroll-one.html) ----------
![](http://oux5x2xxe.bkt.clouddn.com/1508205310491list-mescroll-one.gif)
<br/><br/>
#### 4. 【多mescroll】演示每个菜单列表仅初始化一次,切换菜单缓存数据
#### ---------- <a href="http://www.mescroll.com/preview.html?name=list-mescroll-more" target="_blank">在线体验 </a> ---------- [查看源码](https://github.com/mescroll/mescroll/blob/master/demo/base/list-mescroll-more.html) ----------
![](http://oux5x2xxe.bkt.clouddn.com/1508205306072list-mescroll-more.gif)
<br/><br/>
#### 5. 【满屏加载与锁定滑动】演示自动满屏加载,可临时锁定上拉刷新和下拉加载
#### ---------- <a href="http://www.mescroll.com/preview.html?name=list-full-lock" target="_blank">在线体验 </a> ---------- [查看源码](https://github.com/mescroll/mescroll/blob/master/demo/base/list-full-lock.html) ----------
![](http://oux5x2xxe.bkt.clouddn.com/1508205101076list-full-lock.gif)
<br/><br/>
#### 6. 【mescroll所有配置项】源码展示mescroll所有配置项, 快速理解与调试mescroll
#### ---------- <a href="http://www.mescroll.com/preview.html?name=mescroll-options" target="_blank">在线体验 </a> ---------- [查看源码](https://github.com/mescroll/mescroll/blob/master/demo/base/mescroll-options.html) ----------
![](http://oux5x2xxe.bkt.clouddn.com/1508205347926mescroll-options.gif)
<br/><br/>
## 中级案例 intermediate demos :
#### <a href="http://www.mescroll.com/demo.html#middle" target="_blank">前往官网查看 >> </a>
#### 1. 【知乎 v3.53.0】APP的下拉刷新上拉加载
#### ---------- <a href="http://www.mescroll.com/preview.html?name=zhihu" target="_blank">在线体验 </a> ---------- [查看源码](https://github.com/mescroll/mescroll/blob/master/demo/zhihu/zhihu.html) ----------
![](http://oux5x2xxe.bkt.clouddn.com/1508204842656zhihu.gif)
<br/><br/>
#### 2. 【新浪微博 v7.6.1】APP的下拉刷新上拉加载
#### ---------- <a href="http://www.mescroll.com/preview.html?name=xinlang" target="_blank">在线体验 </a> ---------- [查看源码](https://github.com/mescroll/mescroll/blob/master/demo/xinlang/xinlang.html) ----------
![](http://oux5x2xxe.bkt.clouddn.com/1508205006290xinlang.gif)
<br/><br/>
#### 3. 【贝贝 v6.0.0】APP的下拉刷新上拉加载
#### ---------- <a href="http://www.mescroll.com/preview.html?name=beibei" target="_blank">在线体验 </a> ---------- [查看源码](https://github.com/mescroll/mescroll/blob/master/demo/beibei/beibei.html) ----------
![](http://oux5x2xxe.bkt.clouddn.com/1508205298057beibei.gif)
<br/><br/>
#### 4. 【雅布力 v2.4.0】APP的下拉刷新上拉加载
#### ---------- <a href="http://www.mescroll.com/preview.html?name=yabuli" target="_blank">在线体验 </a> ---------- [查看源码](https://github.com/mescroll/mescroll/blob/master/demo/yabuli/yabuli.html) ----------
![](http://oux5x2xxe.bkt.clouddn.com/1508204995995yabuli.gif)
<br/><br/>
#### 5. 【吸顶悬浮效果】
#### ---------- <a href="http://www.mescroll.com/preview.html?name=sticky" target="_blank">在线体验 </a> ---------- [查看源码](https://github.com/mescroll/mescroll/blob/master/demo/sticky/mescroll-sticky.html) ----------
![](http://oux5x2xxe.bkt.clouddn.com/1512487870668IMG_4195.GIF)
<br/><br/>
#### 6. 【关键词搜索】
#### ---------- <a href="http://www.mescroll.com/preview.html?name=search" target="_blank">在线体验 </a> ---------- [查看源码](https://github.com/mescroll/mescroll/blob/master/demo/search/mescroll-search.html) ----------
![](http://oux5x2xxe.bkt.clouddn.com/1512835307876IMG_4217.GIF)
<br/><br/>
#### 7. 【轮播切换效果】
#### ---------- <a href="http://www.mescroll.com/preview.html?name=swiper-tap" target="_blank">在线体验 </a> ---------- [查看源码](https://github.com/mescroll/mescroll/blob/master/demo/swiper/mescroll-swiper-tap.html) ----------
![](http://oux5x2xxe.bkt.clouddn.com/1512487862014IMG_4194.GIF)
<br/><br/>
#### 8. 【轮播导航菜单】
#### ---------- <a href="http://www.mescroll.com/preview.html?name=swiper-nav" target="_blank">在线体验 </a> ---------- [查看源码](https://github.com/mescroll/mescroll/blob/master/demo/swiper/mescroll-swiper-nav.html) ----------
![](http://oux5x2xxe.bkt.clouddn.com/1512487862014IMG_4194.GIF)
<br/><br/>
## 高级案例 senior demos :
#### <a href="http://www.mescroll.com/demo.html#hight" target="_blank">前往官网查看 >> </a>
#### 1. 【淘宝 v6.8.0】APP的下拉刷新上拉加载
![](http://oux5x2xxe.bkt.clouddn.com/1508205033359taobao.gif)
<br/><br/>
#### 2. 【京东 v6.1.0】APP的下拉刷新上拉加载
![](http://oux5x2xxe.bkt.clouddn.com/1508205090739jingdong.gif)
<br/><br/>
#### 3. 【美团 v8.2.3】APP的下拉刷新上拉加载
![](http://oux5x2xxe.bkt.clouddn.com/1508205067956meituan.gif)
<br/><br/>
#### 4. 【美囤妈妈 v2.0.5】APP的下拉刷新上拉加载
![](http://oux5x2xxe.bkt.clouddn.com/1508205054953meitunmama.gif)
<br/><br/>
## 下载基础中级案例源码 :
<table border="1" cellspacing="0" width="100%">
<tr align="center" height="80px">
<td>mescroll.css</td>
<td>mescroll.js</td>
<td>mescroll所有基础案例源码</td>
<td>mescroll所有中级案例源码</td>
</tr>
<tr align="center" height="80px">
<td colspan="4"> <a href="https://codeload.github.com/mescroll/mescroll/zip/master" target="_blank">【立即下载】</a> </td>
</tr>
</table>
## 获取高级案例源码 :
<table border="1" cellspacing="0" width="100%">
<tr align="center">
<td rowspan="4" width="400px">
mescroll高级案例源码 -- 淘宝 v6.8.0<br/>
mescroll高级案例源码 -- 京东 v6.1.0<br/>
mescroll高级案例源码 -- 美团 v8.2.3<br/>
mescroll高级案例源码 -- 美囤妈妈 v2.0.5
</td>
</tr>
<tr align="center">
<td width="480px">
【 获取方法一 】<br/>
我是大神 , 我为mescroll添砖加瓦<br/>
在 GitHub 上 Star 和 Fork 了 mescroll<br/>
并提出优化或改进建议,获得了采纳 ~
</td>
</tr>
<tr align="center">
<td width="480px">
【 获取方法二 】<br/>
我爱分享 , 编写mescroll相关案例<br/>
联系 QQ 2260429223 投稿<br/>
评审优化后,在mescroll官网展示<br/>
源码指向您的GitHub
</td>
</tr>
<tr align="center">
<td width="480px">
【 获取方法三 】<br/>
我不做伸手党, 打赏任意金额<br/>
联系 QQ 2260429223 获取高级案例源码<br/>
<a href="http://www.mescroll.com/reward.html#tagRank">打赏排行 榜上有名</a>
</td>
</tr>
</table>
![](http://oux5x2xxe.bkt.clouddn.com/1508204975143pay-wx.jpg)
![](http://oux5x2xxe.bkt.clouddn.com/1508204974529pay-zfb.jpg)
/*! mescroll -- 精致的下拉刷新和上拉加载js框架 ( a great JS framework for pull-refresh and pull-up-loading )
* version 1.3.8
* 2018-09-29
* author: wenju < mescroll@qq.com > 文举
* *
* 官网: http://www.mescroll.com
* 动态: https://github.com/mescroll/mescroll/releases
* 问答: http://www.mescroll.com/qa.html
* issues: https://github.com/mescroll/mescroll/issues
* QQ交流群: 633126761
*
* 温馨提示: mescroll唯一的全局样式: html,body{height:100%},用于固定body的高度满屏; 如果影响到您原本的项目样式,可自行删除
*
*
* ----- mescroll的html结构解析 ----
*
<body>
<div id="mescroll" class="mescroll">
<div>
//下拉刷新区域 ( mescroll初始化之后自动创建 )
<div class="mescroll-downwarp">
<div class="downwarp-content">
<p class="downwarp-progress"></p> <p class="downwarp-tip">下拉刷新 </p>
</div>
</div>
//界面的具体内容
//<div>界面内容</div>
//数据列表..
//<ul id="dataList" class="data-list">
// <li>数据列表</li>
//空布局 ( 列表无任何数据时, 且配置了warpId时, 会自动创建显示 )
<div class="mescroll-empty">
<img class="empty-icon" src="../img/mescroll-empty.png"/>
<p class="empty-tip">暂无相关数据~</p>
<p class="empty-btn">去逛逛 ></p>
</div>
//</ul>
//上拉加载区域 ( mescroll初始化之后自动创建 )
<div class="mescroll-upwarp">
//加载中..
<p class="upwarp-progress mescroll-rotate"></p><p class="upwarp-tip">加载中..</p>
//无数据
<p class="upwarp-nodata">-- END --</p>
</div>
</div>
</div>
//回到顶部按钮 ( 列表滚动到配置的距离时, 且配置了warpId时, 会自动创建显示, 注意是添加在body中的 )
<img class="mescroll-totop" src="../img/mescroll-totop.png"/>
</body>
*/
html,body{height:100%}body{-webkit-overflow-scrolling:touch}.mescroll{width:100%;height:100%;overflow-y:auto}.mescroll-hardware{-webkit-transform:translateZ(0);-webkit-transform-style:preserve-3d;-webkit-backface-visibility:hidden;-webkit-perspective:1000}.mescroll-downwarp{position:relative;width:100%;height:0;overflow:hidden;text-align:center}.mescroll-downwarp-reset{-webkit-transition:height 300ms;transition:height 300ms}.mescroll-downwarp .downwarp-content{position:absolute;left:0;bottom:0;width:100%;min-height:30px;padding:10px 0}.mescroll-upwarp{min-height:30px;padding:15px 0;text-align:center;visibility:hidden}.mescroll-downwarp .downwarp-tip,.mescroll-upwarp .upwarp-tip,.mescroll-upwarp .upwarp-nodata{display:inline-block;font-size:12px;color:gray;vertical-align:middle}.mescroll-downwarp .downwarp-tip,.mescroll-upwarp .upwarp-tip{margin-left:8px}.mescroll-downwarp .downwarp-progress,.mescroll-upwarp .upwarp-progress{display:inline-block;width:16px;height:16px;border-radius:50%;border:1px solid gray;border-bottom-color:transparent;vertical-align:middle}.mescroll-rotate{-webkit-animation:mescrollRotate .6s linear infinite;animation:mescrollRotate .6s linear infinite}@-webkit-keyframes mescrollRotate{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(360deg)}}@keyframes mescrollRotate{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}.mescroll-empty{width:100%;padding-top:20px;text-align:center}.mescroll-empty .empty-icon{width:45%}.mescroll-empty .empty-tip{margin-top:6px;font-size:14px;color:gray}.mescroll-empty .empty-btn{max-width:50%;margin:20px auto;padding:10px;border:1px solid #65aadd;border-radius:6px;background-color:white;color:#65aadd}.mescroll-empty .empty-btn:active{opacity:.75}.mescroll-totop{z-index:9990;position:fixed;right:10px;bottom:30px;width:36px;height:36px;border-radius:50%;opacity:0}.mescroll-lazy-in,.mescroll-fade-in{-webkit-animation:mescrollFadeIn .5s linear forwards;animation:mescrollFadeIn .5s linear forwards}@-webkit-keyframes mescrollFadeIn{0%{opacity:0}100%{opacity:1}}@keyframes mescrollFadeIn{0%{opacity:0}100%{opacity:1}}.mescroll-fade-out{pointer-events:none;-webkit-animation:mescrollFadeOut .5s linear forwards;animation:mescrollFadeOut .5s linear forwards}@-webkit-keyframes mescrollFadeOut{0%{opacity:1}100%{opacity:0}}@keyframes mescrollFadeOut{0%{opacity:1}100%{opacity:0}}.mescroll-bar::-webkit-scrollbar-track{background-color:transparent}.mescroll-bar::-webkit-scrollbar{width:6px}.mescroll-bar::-webkit-scrollbar-thumb{border-radius:6px;background-color:#ccc}.mescroll-bar::-webkit-scrollbar-thumb:hover{background-color:#aaa}
\ No newline at end of file
/*! mescroll -- 精致的下拉刷新和上拉加载js框架 ( a great JS framework for pull-refresh and pull-up-loading )
* version 1.3.8
* 2018-09-29
* author: wenju < mescroll@qq.com > 文举
* *
* 官网: http://www.mescroll.com
* 动态: https://github.com/mescroll/mescroll/releases
* 问答: http://www.mescroll.com/qa.html
* issues: https://github.com/mescroll/mescroll/issues
* QQ交流群: 633126761
*/
(function(a,b){if(typeof define==="function"){define(b)}else{if(typeof module!=="undefined"&&module.exports){module.exports=b()}else{this[a]=b()}}})("MeScroll",function(){var a=function(b,e){var h=this;h.version="1.3.8";h.isScrollBody=(!b||b==="body");h.scrollDom=h.isScrollBody?document.body:h.getDomById(b);if(!h.scrollDom){return}h.options=e||{};var d=navigator.userAgent;var c=!!d.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);var i=typeof window.orientation==="undefined";var g=d.indexOf("Android")>-1||d.indexOf("Adr")>-1;h.os={ios:c,pc:i,android:g};h.isDownScrolling=false;h.isUpScrolling=false;var f=h.options.down&&h.options.down.callback;h.initDownScroll();h.initUpScroll();setTimeout(function(){if(h.optDown.use&&h.optDown.auto&&f){if(h.optDown.autoShowLoading){h.triggerDownScroll()}else{h.optDown.callback&&h.optDown.callback(h)}}h.optUp.use&&h.optUp.auto&&!h.isUpAutoLoad&&h.triggerUpScroll()},30)};a.prototype.extendDownScroll=function(b){a.extend(b,{use:true,auto:true,autoShowLoading:false,isLock:false,isBoth:false,offset:80,outOffsetRate:0.2,bottomOffset:20,minAngle:45,hardwareClass:"mescroll-hardware",mustToTop:false,warpId:null,warpClass:"mescroll-downwarp",resetClass:"mescroll-downwarp-reset",textInOffset:"下拉刷新",textOutOffset:"释放更新",textLoading:"加载中 ...",htmlContent:'<p class="downwarp-progress"></p><p class="downwarp-tip"></p>',inited:function(d,c){d.downTipDom=c.getElementsByClassName("downwarp-tip")[0];d.downProgressDom=c.getElementsByClassName("downwarp-progress")[0]},inOffset:function(c){if(c.downTipDom){c.downTipDom.innerHTML=c.optDown.textInOffset}if(c.downProgressDom){c.downProgressDom.classList.remove("mescroll-rotate")}},outOffset:function(c){if(c.downTipDom){c.downTipDom.innerHTML=c.optDown.textOutOffset}},onMoving:function(d,f,c){if(d.downProgressDom){var e=360*f;d.downProgressDom.style.webkitTransform="rotate("+e+"deg)";d.downProgressDom.style.transform="rotate("+e+"deg)"}},beforeLoading:function(d,c){return false},showLoading:function(c){if(c.downTipDom){c.downTipDom.innerHTML=c.optDown.textLoading}if(c.downProgressDom){c.downProgressDom.classList.add("mescroll-rotate")}},afterLoading:function(c){return 0},callback:function(c){c.resetUpScroll()}})};a.prototype.extendUpScroll=function(b){var c=this.os.pc;a.extend(b,{use:true,auto:true,isLock:false,isBoth:false,isBounce:true,callback:null,page:{num:0,size:10,time:null},noMoreSize:5,offset:100,toTop:{warpId:null,src:null,html:null,offset:1000,warpClass:"mescroll-totop",showClass:"mescroll-fade-in",hideClass:"mescroll-fade-out",fadeDuration:0.5,duration:300,supportTap:false,btnClick:null},loadFull:{use:false,delay:500},empty:{warpId:null,icon:null,tip:"暂无相关数据~",btntext:"",btnClick:null,supportTap:false},clearId:null,clearEmptyId:null,hardwareClass:"mescroll-hardware",warpId:null,warpClass:"mescroll-upwarp",htmlLoading:'<p class="upwarp-progress mescroll-rotate"></p><p class="upwarp-tip">加载中..</p>',htmlNodata:'<p class="upwarp-nodata">-- END --</p>',inited:function(d,e){},showLoading:function(d,e){e.innerHTML=d.optUp.htmlLoading},showNoMore:function(d,e){e.innerHTML=d.optUp.htmlNodata},onScroll:null,scrollbar:{use:c,barClass:"mescroll-bar"},lazyLoad:{use:false,attr:"imgurl",showClass:"mescroll-lazy-in",delay:500,offset:200}})};a.extend=function(d,b){if(!d){return b}for(var c in b){if(d[c]==null){d[c]=b[c]}else{if(typeof d[c]==="object"){a.extend(d[c],b[c])}}}return d};a.prototype.initDownScroll=function(){var c=this;c.optDown=c.options.down||{};c.extendDownScroll(c.optDown);c.touchstartEvent=function(f){if(c.isScrollTo){c.preventDefault(f)}c.startPoint=c.getPoint(f);c.lastPoint=c.startPoint;c.maxTouchmoveY=c.getBodyHeight()-c.optDown.bottomOffset;c.inTouchend=false;var d=c.getScrollTop();c.isKeepTop=d===0;if(c.os.pc&&d<=0){c.scrollDom.addEventListener("mousemove",c.touchmoveEvent,{passive:false});document.ondragstart=function(){return false}}};c.scrollDom.addEventListener("mousedown",c.touchstartEvent);c.scrollDom.addEventListener("touchstart",c.touchstartEvent);c.touchmoveEvent=function(l){if(!c.startPoint){return}var d=c.getScrollTop();if(d>0){c.isKeepTop=false}var h=c.getPoint(l);var f=h.y-c.startPoint.y;if(f>0){if(d<=0){c.preventDefault(l);if(c.optDown.use&&!c.inTouchend&&!c.isDownScrolling&&!c.optDown.isLock&&(!c.isUpScrolling||(c.isUpScrolling&&c.optUp.isBoth))){if(c.optDown.mustToTop&&!c.isKeepTop){return}var o=Math.abs(c.lastPoint.x-h.x);var n=Math.abs(c.lastPoint.y-h.y);var m=Math.sqrt(o*o+n*n);if(m!==0){var g=Math.asin(n/m)/Math.PI*180;if(g<c.optDown.minAngle){return}}if(c.maxTouchmoveY>0&&h.y>=c.maxTouchmoveY){c.inTouchend=true;c.touchendEvent();return}var p=h.y-c.lastPoint.y;if(!c.downHight){c.downHight=0}if(c.downHight<c.optDown.offset){if(c.movetype!==1){c.movetype=1;c.optDown.inOffset(c);c.downwarp.classList.remove(c.optDown.resetClass);c.isMoveDown=true;if(c.os.ios&&!c.isKeepTop){c.scrollDom.classList.add(c.optDown.hardwareClass);c.scrollDom.style.webkitOverflowScrolling="auto";c.isSetScrollAuto=true}}c.downHight+=p}else{if(c.movetype!==2){c.movetype=2;c.optDown.outOffset(c);c.downwarp.classList.remove(c.optDown.resetClass);c.isMoveDown=true;if(c.os.ios&&!c.isKeepTop){c.scrollDom.classList.add(c.optDown.hardwareClass);c.scrollDom.style.webkitOverflowScrolling="auto";c.isSetScrollAuto=true}}if(p>0){c.downHight+=p*c.optDown.outOffsetRate}else{c.downHight+=p}}c.downwarp.style.height=c.downHight+"px";var k=c.downHight/c.optDown.offset;c.optDown.onMoving(c,k,c.downHight)}}}else{if(f<0){var q=c.getScrollHeight();var j=c.getClientHeight();var i=q-j-d;if(!c.optUp.isBounce&&i<=0){c.preventDefault(l)}if(c.optUp.use&&!c.optUp.isLock&&c.optUp.hasNext&&!c.isUpScrolling&&(!c.isDownScrolling||(c.isDownScrolling&&c.optDown.isBoth))&&(j+c.optUp.offset>=q||i<=0)){c.triggerUpScroll()}}}c.lastPoint=h};c.scrollDom.addEventListener("touchmove",c.touchmoveEvent,{passive:false});c.touchendEvent=function(){if(c.optDown.use&&c.isMoveDown){if(c.downHight>=c.optDown.offset){c.triggerDownScroll()}else{c.downwarp.classList.add(c.optDown.resetClass);c.downHight=0;c.downwarp.style.height=0}if(c.isSetScrollAuto){c.scrollDom.style.webkitOverflowScrolling="touch";c.scrollDom.classList.remove(c.optDown.hardwareClass);c.isSetScrollAuto=false}c.movetype=0;c.isMoveDown=false}if(c.os.pc){c.scrollDom.removeEventListener("mousemove",c.touchmoveEvent);document.ondragstart=function(){return true}}};c.scrollDom.addEventListener("mouseup",c.touchendEvent);c.scrollDom.addEventListener("mouseleave",c.touchendEvent);c.scrollDom.addEventListener("touchend",c.touchendEvent);c.scrollDom.addEventListener("touchcancel",c.touchendEvent);if(c.optDown.use){c.downwarp=document.createElement("div");c.downwarp.className=c.optDown.warpClass;c.downwarp.innerHTML='<div class="downwarp-content">'+c.optDown.htmlContent+"</div>";var b=c.optDown.warpId?c.getDomById(c.optDown.warpId):c.scrollDom;if(c.optDown.warpId&&b){b.appendChild(c.downwarp)}else{if(!b){b=c.scrollDom}b.insertBefore(c.downwarp,c.scrollDom.firstChild)}setTimeout(function(){c.optDown.inited(c,c.downwarp)},0)}};a.prototype.preventDefault=function(b){if(b&&b.cancelable&&!b.defaultPrevented){b.preventDefault()}};a.prototype.getPoint=function(b){return{x:b.touches?b.touches[0].pageX:b.clientX,y:b.touches?b.touches[0].pageY:b.clientY}};a.prototype.triggerDownScroll=function(){if(!this.optDown.beforeLoading(this,this.downwarp)){this.showDownScroll();this.optDown.callback&&this.optDown.callback(this)}};a.prototype.showDownScroll=function(){this.isDownScrolling=true;this.optDown.showLoading(this);this.downHight=this.optDown.offset;this.downwarp.classList.add(this.optDown.resetClass);this.downwarp.style.height=this.optDown.offset+"px"};a.prototype.endDownScroll=function(){var d=this;var c=function(){d.downHight=0;d.downwarp.style.height=0;d.isDownScrolling=false;if(d.downProgressDom){d.downProgressDom.classList.remove("mescroll-rotate")}};var b=d.optDown.afterLoading(d);if(typeof b==="number"&&b>0){setTimeout(c,b)}else{c()}};a.prototype.lockDownScroll=function(b){if(b==null){b=true}this.optDown.isLock=b};a.prototype.initUpScroll=function(){var c=this;c.optUp=c.options.up||{use:false};c.extendUpScroll(c.optUp);if(c.optUp.scrollbar.use){c.scrollDom.classList.add(c.optUp.scrollbar.barClass)}if(!c.optUp.isBounce){c.setBounce(false)}if(c.optUp.use===false){return}c.optUp.hasNext=true;c.upwarp=document.createElement("div");c.upwarp.className=c.optUp.warpClass;var b;if(c.optUp.warpId){b=c.getDomById(c.optUp.warpId)}if(!b){b=c.scrollDom}b.appendChild(c.upwarp);c.preScrollY=0;c.lazyStartTime=new Date().getTime();c.lazyTag="mescroll-lazying";c.scrollEvent=function(){var g=c.getScrollTop();var f=g-c.preScrollY>0;c.preScrollY=g;if(!c.isUpScrolling&&(!c.isDownScrolling||(c.isDownScrolling&&c.optDown.isBoth))){if(!c.optUp.isLock&&c.optUp.hasNext){var d=c.getScrollHeight()-c.getClientHeight()-g;if(d<=c.optUp.offset&&f){c.triggerUpScroll()}}}var h=c.optUp.toTop;if(h.src||h.html){if(g>=h.offset){c.showTopBtn()}else{c.hideTopBtn()}}if(c.optUp.lazyLoad.use){var e=new Date().getTime();c.lazyTimer&&clearTimeout(c.lazyTimer);if(e-c.lazyStartTime>=c.optUp.lazyLoad.delay){c.lazyStartTime=e;c.lazyLoad(0)}else{c.lazyTimer=c.lazyLoad()}}c.optUp.onScroll&&c.optUp.onScroll(c,g,f)};if(c.isScrollBody){window.addEventListener("scroll",c.scrollEvent)}else{c.scrollDom.addEventListener("scroll",c.scrollEvent)}setTimeout(function(){c.optUp.inited(c,c.upwarp)},0)};a.prototype.setBounce=function(b){if(this.isScrollBody||!this.os.ios){return}if(b===false){this.optUp.isBounce=false;window.addEventListener("touchmove",this.bounceTouchmove,{passive:false})}else{this.optUp.isBounce=true;window.removeEventListener("touchmove",this.bounceTouchmove)}};a.prototype.bounceTouchmove=function(h){var j=this;var d=h.target;var f=true;while(d!==document.body&&d!==document){var m=d.classList;if(m){if(m.contains("mescroll")||m.contains("mescroll-touch")){f=false;break}else{if(m.contains("mescroll-touch-x")||m.contains("mescroll-touch-y")){var c=h.touches?h.touches[0].pageX:h.clientX;var b=h.touches?h.touches[0].pageY:h.clientY;if(!j.preWinX){j.preWinX=c}if(!j.preWinY){j.preWinY=b}var l=Math.abs(j.preWinX-c);var k=Math.abs(j.preWinY-b);var i=Math.sqrt(l*l+k*k);j.preWinX=c;j.preWinY=b;if(i!==0){var g=Math.asin(k/i)/Math.PI*180;if((g<=45&&m.contains("mescroll-touch-x"))||(g>45&&m.contains("mescroll-touch-y"))){f=false;break}}}}}d=d.parentNode}if(f&&h.cancelable&&!h.defaultPrevented){h.preventDefault()}};a.prototype.triggerUpScroll=function(){if(this.optUp.callback&&!this.isUpScrolling){this.showUpScroll();this.optUp.page.num++;this.isUpAutoLoad=true;this.optUp.callback(this.optUp.page,this)}};a.prototype.showUpScroll=function(){this.isUpScrolling=true;this.upwarp.classList.add(this.optUp.hardwareClass);this.upwarp.style.visibility="visible";this.upwarp.style.display="block";this.optUp.showLoading(this,this.upwarp)};a.prototype.showNoMore=function(){this.upwarp.style.visibility="visible";this.upwarp.style.display="block";this.optUp.hasNext=false;this.optUp.showNoMore(this,this.upwarp)};a.prototype.hideUpScroll=function(b){if(b){this.upwarp.style.display="none"}else{this.upwarp.style.visibility="hidden"}this.upwarp.classList.remove(this.optUp.hardwareClass);var c=this.upwarp.getElementsByClassName("upwarp-progress")[0];if(c){c.classList.remove("mescroll-rotate")}};a.prototype.endUpScroll=function(c,b){if(c!=null){if(c){this.showNoMore()}else{this.hideUpScroll(b)}}this.isUpScrolling=false};a.prototype.resetUpScroll=function(c){if(this.optUp&&this.optUp.use){var b=this.optUp.page;this.prePageNum=b.num;this.prePageTime=b.time;b.num=1;b.time=null;if(!this.isDownScrolling&&c!==false){if(c==null){this.removeEmpty();this.clearDataList();this.showUpScroll()}else{this.showDownScroll()}}this.isUpAutoLoad=true;this.optUp.callback&&this.optUp.callback(b,this)}};a.prototype.setPageNum=function(b){this.optUp.page.num=b-1};a.prototype.setPageSize=function(b){this.optUp.page.size=b};a.prototype.clearDataList=function(){var c=this.optUp.clearId||this.optUp.clearEmptyId;if(c){var b=this.getDomById(c);if(b){b.innerHTML=""}}};a.prototype.endByPage=function(c,e,d){var b;if(this.optUp.use&&e!=null){b=this.optUp.page.num<e}this.endSuccess(c,b,d)};a.prototype.endBySize=function(d,c,e){var b;if(this.optUp.use&&c!=null){var f=(this.optUp.page.num-1)*this.optUp.page.size+d;b=f<c}this.endSuccess(d,b,e)};a.prototype.endSuccess=function(c,b,i){var f=this;if(f.isDownScrolling){f.endDownScroll()}if(f.optUp.use){var j;if(c!=null){var e=f.optUp.page.num;var g=f.optUp.page.size;if(e===1){f.clearDataList();if(i){f.optUp.page.time=i}}if(c<g||b===false){f.optUp.hasNext=false;if(c===0&&e===1){j=false;f.showEmpty()}else{var d=(e-1)*g+c;if(d<f.optUp.noMoreSize){j=false}else{j=true}f.removeEmpty()}}else{j=false;f.optUp.hasNext=true;f.removeEmpty()}}var h=!f.optUp.hasNext;f.endUpScroll(j,h);f.loadFull();f.optUp.lazyLoad.use&&f.lazyLoad()}};a.prototype.endErr=function(){if(this.isDownScrolling){var b=this.optUp.page;if(b&&this.prePageNum){b.num=this.prePageNum;b.time=this.prePageTime}this.endDownScroll()}if(this.isUpScrolling){this.optUp.page.num--;this.endUpScroll(false)}};a.prototype.loadFull=function(){var b=this;if(b.optUp.loadFull.use&&!b.optUp.isLock&&b.optUp.hasNext&&b.optUp.callback&&b.getScrollHeight()<=b.getClientHeight()){setTimeout(function(){if(b.getScrollHeight()<=b.getClientHeight()){b.triggerUpScroll()}},b.optUp.loadFull.delay)}};a.prototype.lockUpScroll=function(b){if(b==null){b=true}this.optUp.isLock=b};a.prototype.showEmpty=function(){var c=this;var d=c.optUp.empty;var b=d.warpId||c.optUp.clearEmptyId;if(b==null){return}var g=c.getDomById(b);if(g){c.removeEmpty();var f="";if(d.icon){f+='<img class="empty-icon" src="'+d.icon+'"/>'}if(d.tip){f+='<p class="empty-tip">'+d.tip+"</p>"}if(d.btntext){f+='<p class="empty-btn">'+d.btntext+"</p>"}c.emptyDom=document.createElement("div");c.emptyDom.className="mescroll-empty";c.emptyDom.innerHTML=f;g.appendChild(c.emptyDom);if(d.btnClick){var e=c.emptyDom.getElementsByClassName("empty-btn")[0];if(d.supportTap){e.addEventListener("tap",function(h){h.stopPropagation();c.preventDefault(h);d.btnClick()})}else{e.onclick=function(){d.btnClick()}}}}};a.prototype.removeEmpty=function(){this.removeChild(this.emptyDom)};a.prototype.showTopBtn=function(c){if(!this.topBtnShow){this.topBtnShow=true;var d=this;var e=d.optUp.toTop;if(d.toTopBtn==null){if(e.html){d.toTopBtn=document.createElement("div");d.toTopBtn.innerHTML=e.html}else{d.toTopBtn=document.createElement("img");d.toTopBtn.src=e.src}d.toTopBtn.className=e.warpClass;if(e.supportTap){d.toTopBtn.addEventListener("tap",function(g){g.stopPropagation();d.preventDefault(g);var f=e.btnClick&&e.btnClick();if(f!==true){d.scrollTo(0,d.optUp.toTop.duration)}})}else{d.toTopBtn.onclick=function(){var f=e.btnClick&&e.btnClick();if(f!==true){d.scrollTo(0,d.optUp.toTop.duration)}}}var b;if(e.warpId){b=d.getDomById(e.warpId)}if(!b){b=document.body}b.appendChild(d.toTopBtn)}d.toTopBtn.classList.remove(e.hideClass);d.toTopBtn.classList.add(e.showClass);d.setTopBtnFadeDuration(c)}};a.prototype.hideTopBtn=function(b){if(this.topBtnShow&&this.toTopBtn){this.topBtnShow=false;this.toTopBtn.classList.remove(this.optUp.toTop.showClass);this.toTopBtn.classList.add(this.optUp.toTop.hideClass);this.setTopBtnFadeDuration(b)}};a.prototype.setTopBtnFadeDuration=function(b){if(this.toTopBtn){var c=(b!=null?b:this.optUp.toTop.fadeDuration)+"s";this.toTopBtn.style.animationDuration=c;this.toTopBtn.style.webkitAnimationDuration=c}};a.prototype.scrollTo=function(g,c){var d=this;var f=d.getScrollTop();var b=g;if(b>0){var e=d.getScrollHeight()-d.getClientHeight();if(b>e){b=e}}else{b=0}d.isScrollTo=true;d.scrollDom.style.webkitOverflowScrolling="auto";d.getStep(f,b,function(h){d.setScrollTop(h);if(h===b){d.scrollDom.style.webkitOverflowScrolling="touch";d.isScrollTo=false}},c)};a.prototype.getStep=function(f,d,k,l,h){var j=d-f;if(l===0||j===0){k&&k(d);return}l=l||300;h=h||30;var g=l/h;var c=j/g;var e=0;var b=window.setInterval(function(){if(e<g-1){f+=c;k&&k(f,b);e++}else{k&&k(d,b);window.clearInterval(b)}},h)};a.prototype.lazyLoad=function(b){var d=this;var c=b!=null?b:d.optUp.lazyLoad.delay;var e=setTimeout(function(){var k=d.scrollDom.querySelectorAll("["+d.optUp.lazyLoad.attr+"]");var f=k.length;for(var j=0;j<f;j++){var l=k[j];if(l.getAttribute(d.lazyTag)!=="true"&&d.isInSee(l,d.optUp.lazyLoad.offset)){var h=l.getAttribute(d.optUp.lazyLoad.attr);var g=new Image();g.onload=function(){var i=this.src;var n=this.dom;var m=d.optUp.lazyLoad.showClass;m&&n.classList.add(m);if(n.tagName==="IMG"){n.src=i}else{n.style.backgroundImage="url("+i+")"}n.removeAttribute(d.optUp.lazyLoad.attr);n.removeAttribute(d.lazyTag)};g.onerror=function(){this.dom.removeAttribute(d.lazyTag)};g.onabort=function(){this.dom.removeAttribute(d.lazyTag)};g.src=h;l.setAttribute(d.lazyTag,"true");g.dom=l}}},c);return e};a.prototype.isInSee=function(f,e){e=e||0;var b=this.getOffsetTop(f);var d=this.getScrollTop()-e;var g=b+f.offsetHeight;var c=d+e+this.getClientHeight()+e;return(b<c&&b>=d)||(g<=c&&g>d)};a.prototype.getOffsetTop=function(d){var c=d.offsetTop;var b=d.offsetParent;while(b!=null&&b!==this.scrollDom){c+=b.offsetTop+b.clientTop;b=b.offsetParent}return c};a.prototype.getScrollHeight=function(){return this.scrollDom.scrollHeight};a.prototype.getClientHeight=function(){if(this.isScrollBody&&document.compatMode==="CSS1Compat"){return document.documentElement.clientHeight}else{return this.scrollDom.clientHeight}};a.prototype.getBodyHeight=function(){return document.body.clientHeight||document.documentElement.clientHeight};a.prototype.getScrollTop=function(){if(this.isScrollBody){return document.documentElement.scrollTop||document.body.scrollTop}else{return this.scrollDom.scrollTop}};a.prototype.getToBottom=function(){return this.getScrollHeight()-this.getClientHeight()-this.getScrollTop()};a.prototype.setScrollTop=function(b){if(typeof b==="number"){if(this.isScrollBody){document.documentElement.scrollTop=b;document.body.scrollTop=b}else{this.scrollDom.scrollTop=b}}};a.prototype.getDomById=function(c){var b;if(c){if(typeof c==="string"){b=document.getElementById(c)}else{if(c.nodeType){b=c}}}if(!b){console.error('the element with id as "'+c+'" can not be found: document.getElementById("'+c+'")==null')}return b};a.prototype.removeChild=function(c){if(c){var b=c.parentNode;b&&b.removeChild(c);c=null}};a.prototype.destroy=function(){var b=this;b.scrollDom.removeEventListener("touchstart",b.touchstartEvent);b.scrollDom.removeEventListener("touchmove",b.touchmoveEvent);b.scrollDom.removeEventListener("touchend",b.touchendEvent);b.scrollDom.removeEventListener("touchcancel",b.touchendEvent);b.scrollDom.removeEventListener("mousedown",b.touchstartEvent);b.scrollDom.removeEventListener("mousemove",b.touchmoveEvent);b.scrollDom.removeEventListener("mouseup",b.touchendEvent);b.scrollDom.removeEventListener("mouseleave",b.touchendEvent);b.removeChild(b.downwarp);if(b.isScrollBody){window.removeEventListener("scroll",b.scrollEvent)}else{b.scrollDom.removeEventListener("scroll",b.scrollEvent)}b.removeChild(b.upwarp);b.removeChild(b.toTopBtn);b.setBounce(true)};return a});
\ No newline at end of file
<template>
<div ref="mescroll" class="mescroll">
<div>
<slot></slot>
</div>
</div>
</template>
<script>
// 引入mescroll.min.js和mescroll.min.css
import MeScroll from 'mescroll.js'
import 'mescroll.js/mescroll.min.css'
export default {
name: 'MeScrollVue',
data: function () {
return {
mescroll: null,
lastScrollTop: 0, // 路由切换时滚动条的位置
lastBounce: null // 路由切换时是否禁止ios回弹
}
},
props: {
up: Object,
down: Object
},
mounted: function () {
this.mescroll = new MeScroll(this.$refs.mescroll, {
up: this.up,
down: this.down
})
this.$emit('init', this.mescroll) // init回调mescroll对象
},
methods: {
beforeRouteEnter () {
if (this.mescroll) {
// 滚动到之前列表的位置
if (this.lastScrollTop) {
this.mescroll.setScrollTop(this.lastScrollTop)
setTimeout(() => { // 需延时,因为setScrollTop内部会触发onScroll,可能会渐显回到顶部按钮
this.mescroll.setTopBtnFadeDuration(0) // 设置回到顶部按钮显示时无渐显动画
}, 16)
}
// 恢复到之前设置的isBounce状态
if (this.lastBounce != null) this.mescroll.setBounce(this.lastBounce)
}
},
beforeRouteLeave () {
if (this.mescroll) {
this.lastScrollTop = this.mescroll.getScrollTop() // 记录当前滚动条的位置
this.mescroll.hideTopBtn(0) // 隐藏回到顶部按钮,无渐隐动画
this.lastBounce = this.mescroll.optUp.isBounce // 记录当前是否禁止ios回弹
this.mescroll.setBounce(true) // 允许bounce
}
}
}
}
</script>
<style>
</style>
{
"name": "mescroll.js",
"version": "1.3.8",
"description": "精致的下拉刷新和上拉加载 js框架.支持vue,完美运行于移动端和主流PC浏览器 ( a great JS framework for pull-refresh and pull-up-loading )",
"main": "mescroll.min.js",
"scripts": {},
"repository": {
"type": "git",
"url": "git+https://github.com/mescroll/mescroll.git"
},
"author": "wenju",
"license": "MIT",
"bugs": {
"url": "https://github.com/mescroll/mescroll/issues"
},
"homepage": "https://github.com/mescroll/mescroll#readme",
"_from": "mescroll.js@1.3.8",
"_resolved": "http://registry.npm.taobao.org/mescroll.js/download/mescroll.js-1.3.8.tgz"
}
\ No newline at end of file
...@@ -6,13 +6,15 @@ import router from './router' ...@@ -6,13 +6,15 @@ import router from './router'
import ElementUI from 'element-ui' import ElementUI from 'element-ui'
import './assets/styles/reset.css' import './assets/styles/reset.css'
import './assets/styles/common.css' import './assets/styles/common.css'
import 'element-ui/lib/theme-chalk/index.css' // import 'element-ui/lib/theme-chalk/index.css'
import qs from 'qs' import qs from 'qs'
import store from './store' import store from './store'
import Axios from 'axios' import Axios from 'axios'
import * as filters from './filters' import * as filters from './filters'
// 引入echarts // 引入echarts
import echarts from 'echarts' import echarts from 'echarts'
import * as plugins from './plugin'
// Axios.defaults.baseURL = 'http://testcenter.bigaka.net/crm' // Axios.defaults.baseURL = 'http://testcenter.bigaka.net/crm'
const AUTH_TOKEN = 'X8IvNcvIe7xFvbNhk0I5HyVZY1E' const AUTH_TOKEN = 'X8IvNcvIe7xFvbNhk0I5HyVZY1E'
...@@ -33,7 +35,7 @@ Axios.interceptors.request.use( ...@@ -33,7 +35,7 @@ Axios.interceptors.request.use(
) )
Vue.use(ElementUI) Vue.use(ElementUI)
// Vue.use(http) Vue.use(plugins)
Object.keys(filters).forEach(key => { Object.keys(filters).forEach(key => {
Vue.filter(key, filters[key]) Vue.filter(key, filters[key])
......
<template> <template>
<div class="wrapper"> <div class="wrapper">
<home-header></home-header>
<home-sidebar></home-sidebar> <home-sidebar></home-sidebar>
<section class="main">
<home-header></home-header>
<div class="content-box"> <div class="content-box">
<menus-edit />
<div class="content"> <div class="content">
<transition name="move" mode="out-in"> <transition name="move" mode="out-in">
<!-- <keep-alive exclude="prize"> --> <!-- <keep-alive exclude="prize"> -->
...@@ -11,16 +13,24 @@ ...@@ -11,16 +13,24 @@
</transition> </transition>
</div> </div>
</div> </div>
</section>
</div> </div>
</template> </template>
<script> <script>
import { mapActions } from 'vuex' import { mapActions } from 'vuex'
import HomeSidebar from 'components/Sidebar' import HomeSidebar from 'components/Sidebar'
import HomeHeader from 'components/Header' import HomeHeader from 'components/Header'
import menusEdit from 'components/menus/edit'
export default { export default {
data () {
return {
}
},
components: { components: {
HomeSidebar, HomeSidebar,
HomeHeader HomeHeader,
menusEdit
}, },
created () { created () {
this.getMenus() this.getMenus()
...@@ -34,14 +44,21 @@ export default { ...@@ -34,14 +44,21 @@ export default {
</script> </script>
<style lang="stylus" scoped> <style lang="stylus" scoped>
.wrapper .wrapper
display flex
width 100% width 100%
height 100% height 100%
overflow hidden overflow hidden
.main
flex 1
display flex
position relative
.content-box .content-box
position absolute /*position absolute*/
display inline-block display inline-block
top 58px flex 1
bottom 0 margin-top 58px
/*top 58px*/
/*bottom 0*/
width 80% width 80%
-webkit-transition left 0.3s ease-in-out -webkit-transition left 0.3s ease-in-out
transition left 0.3s ease-in-out transition left 0.3s ease-in-out
......
import momentPlugin from './moment' import moment from './moment'
import utils from './underscore' import underscore from './underscore'
import http from '../http' export const momentPlugin = moment
export { export const underscorePlugin = underscore
momentPlugin,
utils,
http
}
...@@ -3,8 +3,19 @@ import { globalApi } from '@/api' ...@@ -3,8 +3,19 @@ import { globalApi } from '@/api'
// 获取菜单数据 // 获取菜单数据
const GET_MEUMS = 'GET_MEUMS' const GET_MEUMS = 'GET_MEUMS'
// 显示设置快捷菜单
const SHOW_EDIT_MENUS = 'SHOW_EDIT_MENUS'
// 隐藏设置快捷菜单
const HIDE_EDIT_MENUS = 'HIDE_EDIT_MENUS'
// 边侧菜单
const SIDEBAR_UNFOLD = 'SIDEBAR_UNFOLD'
const state = { const state = {
menus: [] menus: [],
editMenus: false,
sidebarUnfold: false // false:边侧菜单收缩, true:边侧菜单展开
} }
const actions = { const actions = {
...@@ -14,18 +25,42 @@ const actions = { ...@@ -14,18 +25,42 @@ const actions = {
let res = await globalApi.getMenus(parmas) let res = await globalApi.getMenus(parmas)
let menus = res.data.data let menus = res.data.data
commit(GET_MEUMS, menus) commit(GET_MEUMS, menus)
},
showEditMenus ({commit}) {
commit(SHOW_EDIT_MENUS, true)
},
hideEditMenus ({commit}) {
commit(HIDE_EDIT_MENUS, false)
},
setSidebarUnfold ({commit}, type) {
commit(SIDEBAR_UNFOLD, type)
} }
} }
const getters = { const getters = {
getMenus (state) { getMenus (state) {
return state.menus return state.menus
},
getEditMenus (state) {
return state.editMenus
},
getSidebarUnfoldInfo (state) {
return state.sidebarUnfold
} }
} }
const mutations = { const mutations = {
[GET_MEUMS] (state, menus) { [GET_MEUMS] (state, menus) {
state.menus = menus state.menus = menus
},
[SHOW_EDIT_MENUS] (state, status) {
state.editMenus = status
},
[HIDE_EDIT_MENUS] (state, status) {
state.editMenus = status
},
[SIDEBAR_UNFOLD] (state, type) {
state.sidebarUnfold = type
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment