# 3.5 侧边导航(Side Nav)

用于让用户在不同的视图中进行切换。

# 纵向导航栏

多用于插件页二级页面存在多种分类的场景中,位于页面左侧
标签文字:建议控制在 2-7 个字内
标签数量:不限
颜色:白色或 #F6F7F9 背景时用黑色文字和黑色标识;深色背景时用白色文字和白色标识
滑动规律:
1、点击纵向选项卡中的某一选项卡,右侧页面应跳转到相应页面
2、若右侧页面可以滑动,当滑动右侧页面时,左侧选项卡应变更到相应位置
3、当纵向选项卡类别占位超过页面的一半,点击超过屏幕一半位置的选项卡,此时纵向选项卡应上移,使得被选中的选项卡处于页面中央位置。



# dof-side-nav

# 实例

# 基础用法

<template>
  <div>
    <div ref="titleBar">
      <dof-minibar title="侧边导航" @dofMinibarRightButtonClicked="reloadHandler"> </dof-minibar>
    </div>
    <!-- ios版本样式 -->
    <list
      class="right-content-ios"
      @scroll="scrollHandler"
      show-scrollbar="false"
      :style="{ 'padding-left': contentLeftDis + 'px' }"
      v-if="!isAndroid"
    >
      <cell v-for="(item, index) in contentData" :key="index" :ref="'item-' + item.proId" style="padding-top: 10px">
        <text @appear="onappearHandler(index)" class="item-title">{{ item.name }}</text>
        <div class="list-image">
          <image
            :src="cItem"
            class="cell-image"
            :aria-hidden="true"
            v-for="(cItem, cIndex) in item.list0"
            :key="cIndex"
          ></image>
        </div>
        <!-- 放一条细线监听元素是否disappear -->
        <div class="line-red" @disappear="ondisappearHandler(index)"></div>
      </cell>
    </list>
    <div class="demo-content-ios" :style="{ top: titleBarHeight + 'px' }" v-if="!isAndroid">
      <dof-side-nav
        :items="dataList"
        :default-style="defaultStyle"
        :height="deviceHeight"
        :background-color="backgroundColor"
        @dofItemClick="dofItemClick"
        :active-font-size="activeFontSize"
        :active-text-color="activeTextColor"
        :active-block-color="activeBlockColor"
        :active-index="activeIndex"
      ></dof-side-nav>
    </div>
    <!-- 安卓版本样式 -->
    <div class="column-center-top" v-if="isAndroid">
      <div class="demo-content">
        <dof-side-nav
          :items="dataList"
          :default-style="defaultStyle"
          :height="deviceHeight"
          :background-color="backgroundColor"
          @dofItemClick="dofItemClick"
          :active-font-size="activeFontSize"
          :active-text-color="activeTextColor"
          :active-block-color="activeBlockColor"
          :active-index="activeIndex"
        ></dof-side-nav>
        <list class="right-content" @scroll="scrollHandler" :style="{ height: contentHeight }">
          <cell v-for="(item, index) in contentData" :key="index" :ref="'item-' + item.proId" style="padding-top: 10px">
            <text @appear="onappearHandler(index)" class="item-title">{{ item.name }}</text>
            <div class="list-image">
              <image
                :src="cItem"
                class="cell-image"
                :aria-hidden="true"
                v-for="(cItem, cIndex) in item.list0"
                :key="cIndex"
              ></image>
            </div>
            <!-- 放一条细线监听元素是否disappear -->
            <div class="line-red" @disappear="ondisappearHandler(index)"></div>
          </cell>
        </list>
      </div>
    </div>
  </div>
</template>

<style scoped>
.demo-content-ios {
  position: absolute;
  left: 0;
}
.column-center-top {
  display: flex;
}
.demo-content {
  display: flex;
  flex-direction: row;
}

.right-content-ios {
  padding: 30px 30px 0 30px;
}
.right-content {
  flex: 1;
  padding: 0 30px;
}

.cell-image {
  width: 200px;
  height: 200px;
  margin: 0 20px 20px 0;
}
.list-image {
  margin: 30px 0;
  width: auto;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
}
.line-red {
  width: auto;
  height: 1px;
  margin-bottom: 20px;
}
.item-title {
  color: #1e2e37;
}
</style>
<script>
import { DofMinibar, DofSideNav } from 'dolphin-intl-ui'
const dom = weex.requireModule('dom')
const modal = weex.requireModule('modal')
const isAndroid = weex.config.env.platform == 'android' ? true : false
let remote_pic =
  'https://bpic.588ku.com/element_list_pic/19/03/06/b933751940fe6ff5ee29c42e7d1edbcb.jpg!/fw/253/quality/90/unsharp/true/compress/true'

export default {
  components: { DofMinibar, DofSideNav },
  data: () => ({
    leftButton: 'http://dolphin-weex-dev.msmartlife.cn/cdn/images/header/icon_back_white@3x.png',
    dataList: ['空调', '冰箱', '洗衣机', '厨房大电', '厨房小电', '热水器', '净水/饮水', '生活护理'],
    contentData: [
      {
        name: '空调',
        proId: 10,
        list0: [remote_pic, remote_pic]
      },
      {
        name: '冰箱',
        proId: 11,
        list0: [remote_pic, remote_pic, remote_pic]
      },
      {
        name: '洗衣机',
        proId: 12,
        list0: [remote_pic]
      },
      {
        name: '厨房大电',
        proId: 13,
        list0: [remote_pic, remote_pic, remote_pic, remote_pic, remote_pic]
      },
      {
        name: '厨房小电',
        proId: 14,
        list0: [remote_pic, remote_pic, remote_pic, remote_pic, remote_pic]
      },
      {
        name: '热水器',
        proId: 15,
        list0: [remote_pic, remote_pic, remote_pic, remote_pic]
      },
      {
        name: '净水/饮水',
        proId: 16,
        list0: [remote_pic, remote_pic]
      },
      {
        name: '生活护理',
        proId: 17,
        list0: [remote_pic, remote_pic]
      },
      {
        name: '家居家装',
        proId: 18,
        list0: [
          remote_pic,
          remote_pic,
          remote_pic,
          remote_pic,
          remote_pic,
          remote_pic,
          remote_pic,
          remote_pic,
          remote_pic,
          remote_pic,
          remote_pic
        ]
      }
    ],
    defaultStyle: {
      width: 200,
      height: 92,
      fontSize: 24,
      color: '#8E969B'
    },
    activeFontSize: 28,
    backgroundColor: '#F6F7F9',
    activeTextColor: '#1E2E37',
    activeBlockColor: '#1E2E37',
    proName: '',
    activeIndex: 0,
    preScrollY: 0,
    scrollDirection: '',
    titleBarHeight: 0,
    dofItemClickFlag: false, //左边item点击标识
    setTimeoutHandler: null,
    isAndroid,
    remote_pic:
      'https://bpic.588ku.com/element_list_pic/19/03/06/b933751940fe6ff5ee29c42e7d1edbcb.jpg!/fw/253/quality/90/unsharp/true/compress/true'
  }),

  created() {},
  computed: {
    deviceHeight() {
      return weex.config.env.realDeviceHeight || weex.config.env.deviceHeight
    },
    contentHeight() {
      return this.deviceHeight - this.titleBarHeight
    },
    contentLeftDis() {
      return this.defaultStyle.width + 20
    }
  },
  mounted() {
    this.$nextTick(() => {
      let ele = this.$refs.titleBar
      this.getEleHeight(ele.children[0])
    })
  },
  methods: {
    dofItemClick(value) {
      let self = this
      if (this.setTimeoutHandler) {
        clearTimeout(this.setTimeoutHandler)
      }
      this.proName = value.item
      this.activeIndex = value.index
      //对应右边滑动
      this.dofItemClickFlag = true
      this.makeScrollToELe(this.activeIndex)
      this.setTimeoutHandler = setTimeout(() => {
        self.dofItemClickFlag = false
        clearTimeout(self.setTimeoutHandler)
      }, 500)
    },
    makeScrollToELe(index) {
      let currId = this.contentData[index]['proId']
      let currItemId = `item-${currId}`
      let el = this.$refs[currItemId][0]
      dom.scrollToElement(el, {}, () => {
        modal.toast({
          message: 'finish'
        })
      })
    },
    scrollHandler(e) {
      let currScrollY = parseInt(e.contentOffset.y)
      if (currScrollY > this.preScrollY) {
        //页面向下滑
        this.scrollDirection = 'down'
      } else {
        //页面向上滑
        this.scrollDirection = 'up'
      }
      this.preScrollY = currScrollY
    },
    onappearHandler(index) {
      if (this.scrollDirection == 'down' && !this.dofItemClickFlag) {
        this.activeIndex = index
      }
    },
    ondisappearHandler(index) {
      if (this.scrollDirection == 'up' && !this.dofItemClickFlag) {
        this.activeIndex = index + 1
      }
    },
    getEleHeight(ele) {
      let self = this
      dom.getComponentRect(ele, result => {
        let size = result.size || {}
        let height = parseInt(size.height)
        if (!height) {
          self.getEleHeight(ele)
        } else {
          self.titleBarHeight = height
        }
      })
    }
  }
}
</script>



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295

# Attributes

Prop Type Required Default Description
width Number | String N 100 组件宽度;当前渲染使用 default-style.width
height Number | String N 600 组件高度
items Array N [] 数据列表
active-font-size Number N 28 选中时文字大小
active-index Number N 0 当前选中索引
active-text-color String N '' 选中时文字颜色;未设置时使用主题默认值
active-block-color String N '' 选中标识颜色;未设置时使用主题默认值
default-style Object N { width: 200, height: 96, fontSize: 28 } 默认项样式
background-color String N '' 组件整体背景颜色;未设置时使用主题默认值
need-dark-mode Boolean N false 是否启用 M-dark/T-dark 内置暗黑适配
text-color String N '' 文字颜色
active-background-color String N '' 激活项背景色
isRTL Boolean N false 是否启用 RTL(从右到左)布局;默认关闭 ^2.5.10

设置 :need-dark-mode="true" 可启用内置暗黑配色,主题初始化与构建配置见 接入说明。

颜色属性为空时使用内置配色;业务显式颜色和样式覆盖优先于默认配色,关闭暗黑适配后仍有效。

defaultStyle.color 优先于默认文字配色。

# Events

事件名 说明 回调参数
dofItemClick 点击选项 { item, index }