提交 4e1db854 编写于 作者: H HuangYi 提交者: GitHub

Merge pull request #52 from didi/index-list-dev

Index-list: add item slot + get actual title height and sub title height + add data property shortcut
[
{
"name": "★Hot City",
"name": "★ Hot City",
"shortcut": "★",
"items": [
{
"name": "BEIJING",
......@@ -33,7 +34,7 @@
"value": 1
},
{
"name": "BAYINGUOLENGZHOU,",
"name": "BAYINGUOLENGZHOU",
"value": 5
},
{
......
......@@ -4,7 +4,13 @@
<div slot="content">
<div class="view-wrapper">
<div class="index-list-wrapper">
<cube-index-list :data="cityData" :title="title" @select="selectItem" @title-click="clickTitle"></cube-index-list>
<cube-index-list :data="cityData" :title="title" @title-click="clickTitle">
<cube-index-list-group v-for="group in cityData" :group="group">
<cube-index-list-item v-for="item in group.items" :item="item" @select="selectItem">
我是自定义{{item.name}}
</cube-index-list-item>
</cube-index-list-group>
</cube-index-list>
</div>
</div>
</div>
......
<template>
<div class="cube-index-list-group">
<h2 class="cube-index-list-anchor">{{group.name}}</h2>
<ul>
<slot>
<cube-index-list-item v-for="(item, index) in group.items" :key="index" :item="item" @select="selectItem"></cube-index-list-item>
</slot>
</ul>
</div>
</template>
<script type="text/ecmascript-6">
const COMPONENT_NAME = 'cube-index-list-group'
const EVENT_SELECT = 'select'
export default {
name: COMPONENT_NAME,
props: {
group: {
type: Object,
default() {
return {}
}
}
},
methods: {
selectItem(item) {
this.$emit(EVENT_SELECT, item)
}
}
}
</script>
<style lang="stylus" rel="stylesheet/stylus">
.cube-index-list-anchor
padding: 16px 16px 10px 16px
line-height: 1
font-size: $fontsize-medium
color: $index-list-anchor-color
background: $index-list-anchor-bgc
</style>
<template>
<div
class="cube-index-list-item border-bottom-1px"
@touchstart="addActiveCls"
@touchend="removeActiveCls"
@click="selectItem()">
<slot>
{{item.name}}
</slot>
</div>
</template>
<script type="text/ecmascript-6">
import {
addClass,
removeClass
} from '../../common/helpers/dom'
const COMPONENT_NAME = 'cube-index-list-item'
const ACTIVE_CLS = 'cube-index-list-item_active'
const EVENT_SELECT = 'select'
export default {
name: COMPONENT_NAME,
props: {
item: {
type: Object,
default() {
return {}
}
}
},
methods: {
addActiveCls(e) {
addClass(e.currentTarget, ACTIVE_CLS)
},
removeActiveCls(e) {
removeClass(e.currentTarget, ACTIVE_CLS)
},
selectItem() {
this.$emit(EVENT_SELECT, this.item)
}
}
}
</script>
<style lang="stylus" rel="stylesheet/stylus">
.cube-index-list-item
position: relative
height: 50px
line-height: 50px
padding: 0 16px
font-size: $fontsize-medium
color: $index-list-item-color
&:last-child
border-none()
.cube-index-list-item_active
background: $index-list-item-active-bgc
</style>
......@@ -11,19 +11,10 @@
{{title}}
</h1>
<ul ref="groups">
<li v-for="group in data" ref="listGroup">
<h2 class="cube-index-list-anchor">{{group.name}}</h2>
<ul>
<li
class="cube-index-list-item border-bottom-1px"
v-for="item in group.items"
@touchstart="addActiveCls"
@touchend="removeActiveCls"
@click="selectItem(item)">
{{item.name}}
</li>
</ul>
</li>
<slot>
<cube-index-list-group v-for="(group, index) in data" :key="index" :group="group" @select="selectItem">
</cube-index-list-group>
</slot>
</ul>
</div>
</cube-scroll>
......@@ -41,8 +32,7 @@
<script type="text/ecmascript-6">
import {
getData,
addClass,
removeClass
getRect
} from '../../common/helpers/dom'
import CubeScroll from '../scroll/scroll.vue'
......@@ -50,10 +40,7 @@
const COMPONENT_NAME = 'cube-index-list'
const EVENT_SELECT = 'select'
const EVENT_TITLE_CLICK = 'title-click'
const ACTIVE_CLS = 'cube-index-list-item_active'
const TITLE_HEIGHT = 50
const SUBTITLE_HEIGHT = 40
const ANCHOR_HEIGHT = window.innerHeight <= 480 ? 17 : 18
export default {
......@@ -65,7 +52,9 @@
},
data: {
type: Array,
default: []
default() {
return []
}
}
},
data() {
......@@ -75,33 +64,41 @@
diff: -1,
options: {
probeType: 3
}
},
titleHeight: null
}
},
created() {
this.listenScroll = true
this.groupList = []
this.listHeight = []
this.touch = {}
this.subTitleHeight = 0
},
mounted() {
setTimeout(() => {
this.$nextTick(() => {
this.titleHeight = this.title && this.$refs.title ? getRect(this.$refs.title).height : 0
const subTitleEl = this.$el.querySelector('.cube-index-list-anchor')
this.subTitleHeight = subTitleEl ? getRect(subTitleEl).height : 0
this._calculateHeight()
}, 20)
})
},
computed: {
fixedTitle() {
if (this.scrollY > -TITLE_HEIGHT) {
if (this.titleHeight === null || this.scrollY > -this.titleHeight) {
return ''
}
return this.data[this.currentIndex] ? this.data[this.currentIndex].name : ''
},
shortcutList() {
return this.data.map((group) => {
return group.name.substr(0, 1)
return group ? group.shortcut || group.name.substr(0, 1) : ''
})
}
},
methods: {
/* TODO: remove refresh next minor version */
refresh() {
this.$refs.indexList.refresh()
},
......@@ -130,22 +127,18 @@
this._scrollTo(anchorIndex)
},
addActiveCls(e) {
addClass(e.currentTarget, ACTIVE_CLS)
},
removeActiveCls(e) {
removeClass(e.currentTarget, ACTIVE_CLS)
},
_calculateHeight() {
const list = this.$refs.listGroup
if (!list) {
this.groupList = this.$el.querySelectorAll('.cube-index-list-group')
if (!this.groupList) {
return
}
this.listHeight = []
let height = TITLE_HEIGHT
let height = this.titleHeight
this.listHeight.push(height)
for (let i = 0; i < list.length; i++) {
let item = list[i]
for (let i = 0; i < this.groupList.length; i++) {
let item = this.groupList[i]
height += item.clientHeight
this.listHeight.push(height)
}
......@@ -156,18 +149,24 @@
} else if (index > this.listHeight.length - 2) {
index = this.listHeight.length - 2
}
this.$refs.indexList.scrollToElement(this.$refs.listGroup[index], 0)
this.$refs.indexList.scrollToElement(this.groupList[index], 0)
this.scrollY = this.$refs.indexList.scroll.y
}
},
watch: {
data() {
setTimeout(() => {
this.$nextTick(() => {
this._calculateHeight()
}, 20)
})
},
title(newVal) {
this.$nextTick(() => {
this.titleHeight = newVal && this.$refs.title ? getRect(this.$refs.title).height : 0
this._calculateHeight()
})
},
diff(newVal) {
let fixedTop = (newVal > 0 && newVal < SUBTITLE_HEIGHT) ? newVal - SUBTITLE_HEIGHT : 0
let fixedTop = (newVal > 0 && newVal < this.subTitleHeight) ? newVal - this.subTitleHeight : 0
if (this.fixedTop === fixedTop) {
return
}
......@@ -177,7 +176,7 @@
scrollY(newY) {
const listHeight = this.listHeight
// top
if (newY > -TITLE_HEIGHT) {
if (newY > -this.titleHeight) {
this.currentIndex = 0
return
}
......
import IndexList from '../../components/index-list/index-list.vue'
import IndexListGroup from '../../components/index-list/index-list-group.vue'
import IndexListItem from '../../components/index-list/index-list-item.vue'
IndexList.install = function (Vue) {
Vue.component(IndexList.name, IndexList)
Vue.component(IndexListGroup.name, IndexListGroup)
Vue.component(IndexListItem.name, IndexListItem)
}
IndexList.group = IndexListGroup
IndexList.item = IndexListItem
export default IndexList
......@@ -28,15 +28,17 @@ describe('IndexList', () => {
vm = null
}
})
it('use', () => {
Vue.use(IndexList)
expect(Vue.component(IndexList.name))
.to.be.a('function')
})
it('should render correct contents', () => {
vm = createIndexList()
expect(vm.$el.querySelector('.cube-index-list-title').textContent.trim())
.to.equal('当前城市:北京市')
vm = createIndexList({
data
})
const navItems = vm.$el.querySelectorAll('.cube-index-list-nav li')
expect(navItems.length)
.to.equal(9)
......@@ -60,6 +62,9 @@ describe('IndexList', () => {
const titleClickHandler = sinon.spy()
vm = createIndexList({
title,
data
}, {
select: selectHandler,
'title-click': titleClickHandler
})
......@@ -75,7 +80,7 @@ describe('IndexList', () => {
it('should fixed title', function () {
this.timeout(10000)
vm = createIndexList({}, [])
vm = createIndexList()
return new Promise((resolve) => {
setTimeout(() => {
vm.$parent.updateRenderData({
......@@ -125,9 +130,26 @@ describe('IndexList', () => {
})
})
it('run normal when group or item undefined', () => {
vm = createIndexList({
data: [
undefined, // props group in index-list-group.vue
{
name: 'default',
items: [
undefined // props item in index-list-item.vue
]
}
]
})
})
it('should handle condition of unexpected param', function () {
this.timeout(10000)
vm = createIndexList()
vm = createIndexList({
title,
data
})
return new Promise((resolve) => {
setTimeout(() => {
const bEl = vm.$el.querySelector('.cube-index-list-nav li[data-index="2"]')
......@@ -171,8 +193,7 @@ describe('IndexList', () => {
})
})
function createIndexList (events = {}, _data = data) {
const props = {title: title, data: _data}
function createIndexList (props = {}, events = {}) {
return instantiateComponent(Vue, IndexList, {
props: props,
on: events
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册