1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/dotton-WXDropDownMenu

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
Внести вклад в разработку кода
Синхронизировать код
Отмена
Подсказка: Поскольку Git не поддерживает пустые директории, создание директории приведёт к созданию пустого файла .keep.
Loading...
README.md

Сначала рассмотрим примерный внешний вид:

Примерный внешний вид

Основные идеи и шаги:

Для макета используется список dl, где первичные пункты находятся в dt, а вторичные — внутри dd с использованием ul и li. В плане взаимодействия, при клике на любой первичный пункт меню закрываются все братские вторичные пункты, а при клике на второй уровень меню закрываются все пункты.

  1. Используйте dt для создания первичных пунктов меню.

  2. Используйте dd для вложения вторичных пунктов меню, начальное скрытие, положение absolute и z-index для плавного выхода за границы страницы.

/* Общий контейнер меню */
.menu {
	display: block;
	height: 38px;
}

/* Первичные пункты меню */
.menu dt {
	font-size: 15px;
	float: left;
	/* Hack */
	width: 33%;
	height: 38px;
	border-right: 1px solid #d2d2d2;
	border-bottom: 1px solid #d2d2d2;
	text-align: center;
	background-color: #f4f4f4;
	color: #5a5a5a;
	line-height: 38px;
}

/* Внешний контейнер вторичных пунктов меню */
.menu dd{
	position: absolute;
	width: 100%;
	/* Hack */
	top: 39px;
	left: 0;
	z-index: 999;
}

/* Обычный стиль вторичных пунктов меню */
.menu li{
	font-size: 14px;
	line-height: 34px;
	color: #575757;
	height: 34px;
	display: block;
	padding-left: 8px;
	background-color: #fff;
	border-bottom: 1px solid #dbdbdb;
}

Просмотрите результат, затем реализуйте событие нажатия.

Как показано на рисунке ниже:

Статическое меню3. Элемент dt привязывается к событию tapMainMenu, а флаг управляет отображением toggle, предоставляя два класса hidden и show для управления отображением. Примечание: элемент dt также может быть связан с событием tap, а не только с view.```css /* Отображение и скрытие */ .show { display: block; }

.hidden { display: none; }


4. Закройте все первичные пункты меню, каждый из которых имеет уникальный index, передаваемый через событие tapMainMenu, который соответствует массиву subMenuDisplay. Текущий элемент subMenuDisplay[index] решает, будет ли он отображен или скрыт, в зависимости от его текущего состояния.

Ключевые части кода:

```html
<dl class="menu">
    <dt data-index="0" bindtap="tapMainMenu">Цена</dt>
    <dd class="{{subMenuDisplay[0]}}">
        <ul><li>Подпункт 1</li><li>Подпункт 2</li></ul>
    </dd>
</dl>
``````javascript
// Use the function to initialize an array which helps avoid issues with deep copy and makes the approach more flexible as you can use different methods and quantities of elements.
function initSubMenuDisplay() {
    return ['hidden', 'hidden', 'hidden'];
}
``````markdown
Страница({
	данные: {
		subMenuDisplay: initSubMenuDisplay()
	},
	нажатиеГлавногоМеню: function(e) {
		// Get the current index of the displayed main menu item
		var index = parseInt(e.currentTarget.dataset.index);
		// Create a new array with hidden state for all items
		var новыйSubmenuDisplay = initSubMenuDisplay();
		// If the current state of the element is hidden, change it to show,
		// otherwise change it to hidden, and also hide all other elements
		if (this.данные.subMenuDisplay[index] === 'hidden') {
			новыйSubmenuDisplay[index] = 'show';
		} else {
			новыйSubmenuDisplay[index] = 'hidden';
		}
		// Set the new array as the value of subMenuDisplay
		this.setData({
			subMenuDisplay: новыйSubmenuDisplay
		});
	}
});

Выберите текущий пункт вторичного меню, но при этом используйте системный значок и измените цвет фона, сделайте текст жирным. Также измените заголовок первого уровня меню. В демонстрационном режиме показаны всплывающие окна.Объявите метод tapSubMenu для отслеживания событий клика по пункту вторичного меню:

    tapSubMenu: function(e) {
        // Получение текущего значения первичного меню
        var index = parseInt(e.currentTarget.dataset.index);
        console.log(index);
        // Скрытие всех первичных меню
        this.setData({
            subMenuDisplay: initSubMenuDisplay()
        });
    }

Добавьте эффект выделения:

/* Выделенный стиль для пунктов вторичного меню */
.menu li.highlight {
    background-color: #f4f4f4;
}

Для реализации выделения с использованием двумерного массива, чтобы можно было точно определить, какой пункт вторичного меню был выбран, а также какое первичное меню должно быть видимым, измените файл разметки следующим образом:

<dd class="{{subMenuDisplay[0]}}">
    <ul>
        <li class="{{subMenuHighLight[0][0]}}" data-index="0-0" bindtap="tapSubMenu">100以内</li>
        <li class="{{subMenuHighLight[0][1]}}" data-index="0-1" bindtap="tapSubMenu">100–500</li>
        <li class="{{subMenuHighLight[0][2]}}" data-index="0-2" bindtap="tapSubMenu">500–1000</li>
        <li class="{{subMenuHighLight[0][3]}}" data-index="0-3" bindtap="tapSubMenu">1000–3000</li>
        <li class="{{subMenuHighLight[0][4]}}" data-index="0-4" bindtap="tapSubMenu">3000以上</li>
    </ul>
</dd>

Эффект представлен на следующем рисунке:

Выделение пункта вторичного меню

Соответствующий JavaScript код следует оформить так:

// Объявление начального состояния выделения массива
function initSubMenuHighLight() {
    return [
        ['','','','',''],
        ['',''],
        ['','','']
    ];
}
```Клик событие:

```javascript
tapSubMenu: function(e) {
    // Скрытие всех первичных меню
    this.setData({
        subMenuDisplay: initSubMenuDisplay()
    });
    // Обработка вторичного меню, получаем текущее значение вторичного меню
    var indexArray = e.currentTarget.dataset.index.split('-');
    console.log("indexArray : " + indexArray);
    var newSubMenuHighLight = initSubMenuHighLight();
    // Для первого уровня меню нет необходимости проверять текущее состояние, достаточно присвоить класс highlight
    newSubMenuHighLight[indexArray[0]][indexArray[1]] = 'highlight';
    console.log(newSubMenuHighLight);
    // Установка нового массива
    this.setData({
        subMenuHighLight: newSubMenuHighLight
    });
}

Таким образом, была реализована возможность выделения и снятия выделения. Однако это ещё не всё, поскольку для вторичного меню отличается от первого уровня — братские пункты вторичного меню не являются взаимоисключающими, то есть выбор одного пункта вторичного меню не должен автоматически снимать выделение других пунктов. Поэтому мы дорабатываем наш JavaScript код. Способ объявления, замените на переменную для удобства хранения.

// Определение начальных данных для хранения при выполнении
var initSubMenuHighLight = [
        ['','','','',''],
        ['',''],
        ['','','']
    ];

Обработка события нажатия```javascript tapSubMenu: function(e) { // Скрыть все первичные меню this.setData({ subMenuDisplay: initSubMenuDisplay() }); // Обработка вторичных меню, сначала получаем текущий показатель вторичного меню var indexArray = e.currentTarget.dataset.index.split('-'); // Инициализация состояния // var newSubMenuHighlight = initSubMenuHighlight; for (var i = 0; i < initSubMenuHighlight.length; i++) { // Если выбрано первичное меню, то сначала очистить состояние, затем выделить выбранное вторичное меню; если это не текущее меню, то игнорировать его. Таким образом можно сохранить выделение других меню if (indexArray[0] === i) { for (var j = 0; j < initSubMenuHighlight[i].length; j++) { // Очистка initSubMenuHighlight[i][j] = ''; } // Возврат вторичного меню в начальное состояние } } }

    // Для вторичных меню нет необходимости проверять текущее состояние, достаточно присвоить класс highlight после клика
    initSubMenuHighLight[indexArray[0]][indexArray[1]] = 'highlight';
    // Установка нового массива
    this.setData({
        subMenuHighLight: initSubMenuHighLight
    });
}
```

Необходимые доработки:

1. Добавление анимации при отображении и скрытии (вниз)

2. Абстрагирование, использование обратного вызова для прослушивания каждого клика вторичного меню

3. Отделение источника данных от представления, ключи и значения первичных и вторичных меню должны быть разделены, система должна распознавать только индекс, а затем выполнять действия по кликам, переходы страниц и фильтрацию результатов

[2016-10-18]

Официальная документация: [https://mp.weixin.qq.com/debug/wxadoc/dev/api/api-animation.html](https://mp.weixin.qq.com/debug/wxadoc/dev/api/api-animation.html)

![Иллюстрация](https://static.oschina.net/uploads/img/201610/19094056_owgS.gif "Эффект")

Для реализации анимированной версии требуется поддержка анимации перемещения и маски. Предположительный подход следующий:

1. Вторичное меню начинается скрытым и находится за пределами экрана устройства

2. При выборе первичного меню вторичное меню перемещается вниз до тех пор, пока верхний край вторичного меню не совпадает нижним краем первичного меню. Используется линейная анимация

3. При выборе самого себя или другого первичного меню выполняются противоположные действия
```4. Маска используется с анимацией ease-in/ease-out

Шаг 1: Изменение стилей, установка свойства top

Шаг 2: Объявление анимации

Основной код:```python
    animation: function(index) {
        // Определение анимации
        var animation = wx.createAnimation({
            duration: 400,
            timingFunction: 'linear',
        })
        // Отображение или скрытие
        var flag = this.data.subMenuDisplay[index] === 'show' ? 1 : -1;
        // flag = 1;
        console.log(flag)
        // Движение вдоль оси Y
        animation.translateY(flag * (initSubMenuHighLight[index].length * 34) + 8).step();
        // Экспортирование данных для привязки к свойству view
        this.setData({
            animationData: animation.export()
        });
    }
```

После завершения анимации необходимо один раз вызвать `step()`, независимо от того, является ли это одной группой или несколькими.

Шаг 3: Объявление массива data и связывание с wxml

```
    animationData: {}
```

в wxml:

```
    <dd animation="{{animationData}}">
```

Проблема z-index может закрывать первичное меню, установите значение равным `-999`, чтобы поместить его ниже уровня первого меню.

Используйте `bottom: 0;` для начального положения вровень с нижней границей первого меню.

Установите `dl` как `position: relative;` для соответствия вторичному меню, которое имеет позицию `absolute`.

Шаг 4: При клике на первичное меню вызывается анимация

```
    // Установка анимации
    this.animation(index);
```

Шаг 5: При клике на вторичное меню вызывается анимация

```
    // Установка анимации
    this.animation(indexArray[0]);
```Шаг 6: Атрибут `display` следует заменить на `visibility`.

```markdown
/* Отображение и скрытие */
.show {
    /*display: block;*/
    visibility: visible;
}

.hidden {
    /*display: none;*/
    visibility: hidden;
}
```

> Сохраните место, ширину и высоту, иначе при отсутствии анимационного эффекта после клика.

Скачать исходный код: подписаться на следующий официальный аккаунт -> ответить цифрой 1006

Друзьям, интересующимся разработкой мини-приложений, рекомендую подписаться на официальный аккаунт: `huangxiujie85`, QQ группа: `575136499`, WeChat: `small_application`, мы будем продолжать выпускать больше работ.

![Официальный аккаунт](https://static.oschina.net/uploads/img/201610/07111145_qD6d.jpg "Код QR")

Комментарии ( 0 )

Вы можете оставить комментарий после Вход в систему

Введение

Программа имеет выпадающее меню, которое можно использовать для фильтрации. Развернуть Свернуть
Отмена

Обновления

Пока нет обновлений

Участники

все

Недавние действия

Загрузить больше
Больше нет результатов для загрузки
1
https://api.gitlife.ru/oschina-mirror/dotton-WXDropDownMenu.git
git@api.gitlife.ru:oschina-mirror/dotton-WXDropDownMenu.git
oschina-mirror
dotton-WXDropDownMenu
dotton-WXDropDownMenu
master