fast-mobile-app & uni-app
fast-mobile-app — это фреймворк для разработки мобильных приложений на основе uni-app. Он абстрагирует и инкапсулирует 80% стандартной бизнес-логики, используемой в повседневной разработке, что позволяет разработчикам не писать сложный и трудноподдерживаемый код.
fast-mobile-app предоставляет разработчикам полный набор надёжных функций, позволяя создать полноценное приложение всего за одну минуту.
Фреймворк следует принципу приоритета конфигурации, освобождая разработчиков от сложной бизнес-логики и делая детали более понятными и контролируемыми. API, предоставляемые самим фреймворком, реализованы через механизм регистрации сервисов. В любом месте можно использовать uni.$[имя API] для доступа к ним, например: uni.$getUserInfo().
├─bootstrap |
│ ├─boots |
│ │ ├─es6 |
│ │ ├─native |
│ │ │ ├─floatings |
│ │ │ ├─base.js |
│ │ │ ├─location.js |
│ │ │ ├─mixin.js |
│ │ │ ├─ui.js |
│ │ │ ├─user.js |
│ │ │ └─... |
│ │ ├─config.js |
│ │ ├─downrefresh.js |
│ │ ├─event.js |
│ │ ├─http.js |
│ │ ├─map-api.js |
│ │ ├─middleware.js |
│ │ ├─promise-cache.js |
│ │ └─util.js |
│ |
│ ├─http |
│ │ ├─request.js |
│ │ ├─uploader.js |
│ │ ├─logins |
│ │ │ ├─account.js |
│ │ │ ├─official.js |
│ │ │ ├─basic.js |
│ │ │ └─... |
│ │ └─... |
│ |
│ ├─libs |
│ │ ├─qqmap-wx-jssdk.min.js |
│ │ ├─bignumber.js |
│ │ └─... |
│ |
│ ├─util |
│ │ ├─collection.js |
│ │ ├─function.js |
│ │ ├─number.js |
│ │ ├─string.js |
│ │ ├─time.js |
│ |
│ ├─$.js |
│ ├─cache.js |
│ ├─events.js |
│ ├─middleware.js |
│ ├─publisher.js |
│ ├─uploader.js |
│ └─validate.js |
├─common |
│ ├─config |
│ │ ├─https |
│ │ │ ├─basic.request.interceptor.js |
│ │ │ ├─basic.response.interceptor.js |
│ │ │ └─... |
│ │ ├─middlewares |
│ │ │ ├─app-show-params.js |
│ │ │ └─... |
│ │ ├─app.js |
│ │ ├─http.js |
│ │ ├─middleware.js |
│ │ ├─page.js |
│ │ ├─component.js |
│ │ └─upload.js |
В файле main.js в приложении Vue добавьте строку import "./bootstrap/index";
, чтобы подключить глобальный API bootstrap/index.js, настроить загрузку и т. д.
// main.js
import "./bootstrap/index"
// Все API автоматически добавляются к переменной uni.$
Все бизнес-конфигурации находятся в каталоге common/config.
common/config/app.js
// Базовая конфигурация приложения
// Получает конфигурацию uni.$config
module.exports = {
// Идентификатор приложения
accessId: '',
// Ключ приложения
accessKey: '',
// Тип подписи
signType: 'md5',
// Версия
version: '1.0',
// Массивы идентификаторов шаблонов сообщений подписки
tmplIds: [],
// Автоподписка на шаблоны сообщений
autoSubscribeTmplMsg: true,
// Логин пользователя — ключ кэша
userInfoKey: '__USER_INFO__',
// Сеанс пользователя — ключ
sessionIdKey: '__SESSION__',
// Обратный вызов после успешного входа
onLogged: function(res) {
console.info('app.onLogged', res)
},
// Обратный вызов после выхода
onLogout: function(res) {
console.info('app.onLogout', res)
},
// Изменение информации о текущем пользователе
onUserChange: function({detail: user}) {
console.info('user info change:', user);
},
// Переход по ссылке
onLinkTo: function(url, type) {
},
// Ключи карты Tencent
QQMapKeys: [],
// Завершение обновления с подсказкой звука
stopPullDownRefreshAudio: '',
};
common/config/http.js
import $ from '../../bootstrap/$';
// Конфигурация HTTP
// const baseURL = 'http://localhost/api';
module.exports = {
// Параметры по умолчанию
defaults: {
// Базовый URL для сетевых запросов
baseURL: baseURL,
// Возвращать исходные данные
returnRaw: false,
// Отображать ли сообщение об ошибке
isShowErrorTips: true,
},
// Использовать оригинальный логин для мобильных приложений
// #ifdef MP
login: uni.$logins.weapp, // Оригинальный логин для мобильных приложений
loginUrl: baseURL + '/weapp_login', // Адрес для входа
loginUserInfo: true, // Получать ли информацию о пользователе при входе
// #endif
// Использовать аккаунт для входа
// #ifdef H5
login: uni.$logins.account, // Вход через аккаунт
loginUrl: baseURL + '/login', // Адрес для входа
loginPage: '/pages/auth/login', // Пользовательская страница входа
// #endif
// Обратные вызовы для всех запросов
onRequest: function(config) {
},
// Код успеха
successCode: 1,
// Обработка успешного выполнения (все успешные запросы вызывают эту функцию)
onSuccess: function(data, response) {
},
// Текст загрузки по умолчанию
loadingText: 'Пожалуйста, подождите...',
errorTips: 'Ошибка сети, пожалуйста, повторите попытку позже~', // Текст ошибки по умолчанию
loginAuthTips: 'Эта операция требует вашего разрешения на доступ к основным данным', // Текст подсказки авторизации
loginAuthFailedTips: 'Сначала предоставьте разрешение, а затем повторите попытку~', // Текст при неудачной попытке авторизации
loginFailedMsg: 'Не удалось войти в систему, попробуйте ещё раз позже~', // Сообщение об ошибке при входе
// Код ошибки при недействительном входе
loginInvalidCode: -1,
// Максимальное количество попыток входа
loginMaxCount: 1,
// Тайм-аут при входе
onLoginTimout: function(config, response) {
uni.showModal({
content: 'Тайм-аут входа, пожалуйста, попробуйте позже~',
showCancel: false
});
},
// Код ошибки без разрешения
unauthorizedCode: -10,
// Обработка без разрешения
onUnauthorized: function(config, response) {
uni.$http.resolveModal(config)({
title: 'Напоминание',
content: 'Нет разрешения, подробности см. в руководстве по разрешениям?',
showCancel: true,
confirmColor: '#2E8B57',
confirmText: 'Узнать больше',
success: (res) => {
if (res.cancel) {
return;
}
uni.navigateTo({
url: '/pages/auth/unauthorized'
});
}
});
},
// Другие обработчики бизнес-логики
logicErrors: {
// '40000': function(data, response) { // Ошибка проверки данных
// }
},
// Обработчик ошибок HTTP по умолчанию
statusErrors: {
'404': function(config, response) {
if (config.method.toUpperCase() === 'GET') {
uni.navigateBack();
}
},
// '500': function(response) {
// },
},
//
``` **Запрос-перехватчик**
```requestInterceptors: [
uni.$http.basicRequestInterceptor,
],
// Ответ-перехватчик
responseInterceptors: [
uni.$http.basicResponseInterceptor
]
};
common/config/upload.js
// Конфигурация загрузки
module.exports = {
// По умолчанию диск
disk: 'qiniu',
// Диски для загрузки
disks: {
// Загрузка на удалённый сервер
remote: {
driver: 'remote',
url: '/upload'
},
// Загрузка в Qiniu
qiniu: {
driver: 'qiniu',
// Получение информации о токене, наивысший приоритет
tokenInfoUrl: '/upload/token',
// Конфигурация Qiniu (получение адреса токена)
// uptokenURL: 'https://yourserver.com/api/uptoken',
// uptoken: 'xxxx',
// domain: 'http://yourserver.com/'
// region: 'NCN', // Северный Китай
}
}
};
Основные запросы
// GET запрос
uni.$http.get(uri, data, options).then(() => console.log, err => console.error);
// POST запрос
uni.$http.post(uri, data, options).then(() => console.log, err => console.error);
// PUT запрос
uni.$http.put(uri, data, options).then(() => console.log, err => console.error);
// DELETE запрос
uni.$http.delete(uri, data, options).then(() => console.log, err => console.error);
Описание параметров
// Описание опций
const options = {
// Отображение сообщения об ошибке
isShowErrorTips: true,
// Возврат исходных данных
returnRaw: false,
// Отображение успешного сообщения
successTips: undefined, // Для POST и PUT значение true, для остальных — false
// Подсказки
hint: {
hintSuccess: function(msg) {
},
hintError: function(msg) {
}
},
// Модальное окно с предупреждением
modal: function(options: ModalOptions) {
},
// Отображать ли окно загрузки
loading: Boolean | String | {
showLoading: function() {
},
hideLoading: function() {
}
},
// Текст окна загрузки
loadingText: String,
// Ошибки HTTP статуса
statusErrors: {
'404': function(config, response) {
}
},
// Бизнес-ошибки приложения
logicErrors: {
'40040': function(data, response) {
}
}
}
Загрузка файлов
Помимо основных сетевых запросов, загрузка файлов является частой операцией в повседневной разработке. В каждом месте загрузки приходится писать много кода для обработки загрузки. Теперь загрузка становится проще.
// Загрузить файл
uni.$upload({
filePath: '',
formData: {},
name: 'file'
}).then(() => console.log, err => console.error)
// Расширение метода Promise
Promise.prototype.finally(callback);
// Получить информацию о системе
uni.$systemInfo;
// Определить, работает ли приложение в режиме разработчика
uni.$isDev;
• Определить, отклонён ли доступ
uni.$isAuthDeny(err);
• Определить, отображается ли текущая страница
uni.$isShowPage(pageObj);
• Получить текущую страницу
uni.$getCurrentPage();
• Нужна ли текущей странице кнопка «Вернуться домой»
uni.$isShowHomeButton();
• Вернуться к предыдущей странице
uni.$prePage(cb);
• Преобразовать массив в объект
uni.$arr2obj(prefix, data, initIndex = 0);
• Добавить поддержку Promise для оригинальных API от WeChat
uni.$promise.xxx;
• Отложить возврат на предыдущую страницу
uni.$back(delay = 1500, options = {});
• Вывести сообщение об ошибке
uni.$hintError(msg);
• Вывести успешное сообщение
uni.$hintSuccess(msg);
• Получить информацию о пользователе
uni.$getUserInfo(options = {});
• Попытаться подписаться на сообщения
uni.$tryRequestSubscribeMessage(options);
• Автоматически попытаться подписаться на шаблонные сообщения
uni.$autoRequestSubscribeMessage();
• Получить экземпляр карты Tencent
uni.$getQQMap();
• Библиотека для работы с десятичными числами
uni.$BigNumber();
• MD5
uni.$md5();
• Создать экземпляр QR-кода
uni.$QRCode();
• Общие методы
uni.$random();
uni.$isEmpty(obj);
uni.$isArray(obj);
uni.$isObject(obj);
uni.$toObject(obj);
uni.$assign(obj, newObj);
Передача данных между страницами больше не требует использования getApp().globalData. Это может привести к путанице и затруднить обслуживание. Передача данных через события позволяет разблокировать больше сценариев.
В этом фреймворке механизм аутентификации пользователя также основан на событиях.
Пример кода
// Прослушать событие
uni.$emitter.on('choose.address', function(address) {
console.log(address);
});
// Запустить событие
uni.$emitter.emit('choose.address', {
adddress: 'Чжэнчжоу Чжэндун Синьцюнь...'
});
• Прослушать событие один раз
uni.$emitter.once('choose.address', function(address) {
console.log(address);
});
• Удалить прослушиватель событий
uni.$emitter.off('choose.address');
``` **Глобальные события**
> Глобальные события хранятся в каталоге common/event/, централизованно экспортируются из index.js.
**Пример кода**
```javascript
// Глобальное событие
module.exports = {
// Обработка события «пользователь авторизовался»
'sys.getUserInfo.to': function() {
console.log('sys.getUserInfo.to...');
const page = uni.$getCurrentPage();
if (page.onLogin && page.onLogin(options) !== false) {
return;
}
uni.navigateTo({
url: '/pages/auth/auth'
});
}
};
В рамках фреймворка реализован простой обработчик кэша, который поддерживает автоматическое удаление данных из кэша по истечении срока действия. Это особенно полезно на некоторых страницах, где требуются данные.
Пример кода
// Получение данных из кеша
uni.$cache.get(key, defaultValue = null);
// Сохранение данных в кеш
uni.$cache.set(key, value, ttl = 3600)
// Очистка кеша
uni.$cache.forget(key)
Реализован механизм аутентификации пользователей, ранее использовавшийся getApp().globalData, глобальная переменная была заменена на внутреннюю частную управляемую переменную. Использование внутренних частных переменных обеспечивает определённую изоляцию и лаконичность.
Пример кода
// Получить текущий sessionID
uni.$getSessionId()
// Установить текущий sessionID
uni.$setSessionId(sessionId)
// Информация о пользователе
uni.$user.value();
uni.$user.notify(data);
uni.$user.subscribe(callback);
uni.$user.unsubscribe(callback);
// Активный вызов сервера для входа
uni.$login(options); // Внутренняя реализация логики немного сложна, рекомендуется просмотреть её самостоятельно
// Активно ли пользователь вошёл в систему
uni.$isLogged();
// Выйти из системы
uni.$logout()
Информация о пользователях основана на механизме подписчиков. В некоторых сценариях нескольким вашим страницам может потребоваться синхронизация с актуальной информацией о пользователе в реальном времени, чтобы избежать чрезмерных сетевых запросов и нагрузки на сервер.
Экземпляр модели обычно используется для проверки перед отправкой формы.
// Правила проверки, формат: поле:[правила проверки1,[правила проверки с параметрами, параметры]...]
const rules = {
'title': ['require', ['len', '3,48'], 'chsDash'],
'name': ['require', ['len', '2,24'], 'alphaDash'],
'age': ['require', ['egt', 18], ['elt', 32]]
};
// Сообщения об ошибках
const messages = {
'title.len': 'Длина заголовка должна быть от 3 до 48 символов.'
};
// Соответствие полей их китайским названиям
const fields = {
'title': '标题',
'name': '名称',
'age': '年龄'
};
// Создание экземпляра валидатора
const validate = new uni.$Validate(rules, messages, fields);
// Данные для проверки
const data = {
title: '你好',
name: 'helloworld',
age: '45'
};
// Проверка данных
if (validate.check(data)) {
console.log('Проверка прошла успешно!');
} else {
console.error('Ошибка проверки:', validate.getError());
}
Статический вызов обычно используется для специальной проверки одного поля.
console.log('Обязательное поле:', uni.$Validate.is(undefined, 'require'));
console.log('Только буквы:', uni.$Validate.is('abcd', 'alpha'));
console.log('Буквы и цифры:', uni.$Validate.is('abcd124', 'alphaNum'));
console.log('Буквы, цифры и символы подчёркивания и дефиса:', uni.$Validate.is('abcd124--', 'alphaDash'));
console.log('Китайские иероглифы:', uni.$Validate.is('abcd124', 'chs'));
console.log('Китайские иероглифы и буквы:', uni.$Validate.is('abcd124', 'chsAlpha'));
console.log('Китайские иероглифы, буквы и цифры:', uni.$Validate.is('abcd124', 'chsAlphaNum'));
console.log('Китайские иероглифы, буквы, цифры, символы подчёркивания и дефиса:', uni.$Validate.is('abcd124', 'chsAlphaNum'));
console.log('Является ли это адресом электронной почты:', uni.$Validate.is('110@.com', 'email'));
console.log('Проверяет, является ли это 11-значным номером мобильного телефона:', uni.$Validate.is('13673679989', 'mobile'));
console.log('Проверяет, является ли это номером стационарного телефона:', uni.$Validate.is('0371-4569-225', 'tel'));
console.log('Является ли это IP-адресом:', uni.$Validate.is('127.0.0.1', 'ip'));
console.log('Является ли это URL-адресом:', uni.$Validate.is('127.0.0.1', 'url'));
console.log('Является ли это числом с плавающей точкой:', uni.$Validate.is('127.0.0.1', 'float'));
console.log('Числовое ли это значение:', uni.$Validate.is('48.56', 'number'));
console.log('Целое ли это число:', uni.$Validate.is('48.56', 'integer'));
console.log('Булево ли это значение:', uni.$Validate.is('false', 'boolean'));
console.log('Массив ли это:', uni.$Validate.is([], 'array'));
Эта модель не является настоящей моделью в строгом смысле этого слова, она не реализует характеристики ORM, а представляет собой своего рода оболочку для интерфейса сервера. Его цель — уменьшить количество написанного кода интерфейса и обработать результаты интерфейса, что особенно полезно при переключении между различными серверными интерфейсами или серверными фреймворками.
Все модели хранятся в каталоге /common/models/ и централизованно экспортируются через index.js, они также доступны в переменной uni.$model. При использовании они очень удобны.
Пример кода
uni.$models.user.get();
uni.$models.user.set();
uni.$models.basic.config();
// Дополнительные методы моделей см. в файлах каталога /common/models/.
Этот сервис не выполняет слишком много обработки, он работает аналогично модели данных, но вместо этого экспортируется через переменную uni.$service. Сервисы полезны, когда нет сильной зависимости от бизнеса или когда вам нужно предоставить некоторые API, к которым можно получить доступ из любого места.
Пример кода
uni.$service.xxx
// Случайным образом перемешивает массив
uni.$collectionUtil.shuffle(arr)
// Извлекает случайный элемент из списка. Если передано число n, возвращает n случайных элементов. В противном случае возвращается один случайный элемент.
uni.$collectionUtil.sample(arr, n, guard)
// Сглаживает многомерный массив.
uni.$collectionUtil.flatten(array, shallow)
// Возвращает пересечение массивов arr. Каждый элемент в результате присутствует во всех массивах arr.
uni.$collectionUtil.intersection(...arr)
// Получает разницу двух массивов.
``` **uni.$collectionUtil.difference(...arr)** — разница между двумя массивами.
**uni.$collectionUtil.mapObject(obj, iteratee)** — преобразование каждого свойства объекта.
**uni.$functionUtil.safeCallback(func, param, thisArg)** — попытка выполнить метод.
**uni.$functionUtil.throttle(func, wait, options)** — создание и возврат функции, которая при повторном вызове будет выполняться не чаще, чем один раз в wait миллисекунд. Полезно для управления событиями с высокой частотой.
**uni.$functionUtil.debounce(func, wait, immediate)** — возвращение «защищённой» версии функции func, выполнение которой будет отложено на wait миллисекунд после последнего вызова. Последний вызов запоминается и возвращается.
**uni.$functionUtil.before(func, count)** — функция, которая может быть вызвана не более count раз. После достижения предела последний результат вызова запоминается и возвращается.
**uni.$functionUtil.once(func)** — функция, которую можно вызвать только один раз. Повторные вызовы не имеют эффекта, всегда возвращается результат первого вызова.
**uni.$functionUtil.after(func, count)** — функция, которая начинает действовать только после того, как была вызвана count раз. Используется для обработки асинхронных запросов.
**uni.$functionUtil.gtFuture(func, wait, context)** — выполнение функции в будущем, когда время ожидания больше указанного.
**uni.$functionUtil.ltFuture(func, wait, context)** — выполнение функции в будущем, когда время ожидания меньше указанного.
**uni.$stringUtil.leftFill(str, num, fillStr)** — заполнение строки слева.
**uni.$stringUtil.rightFill(str, num, fillStr)** — заполнение строки справа.
**uni.$stringUtil.uuid(prefix = '')** — генерация уникального идентификатора.
**uni.$stringUtil.orderedUuid(prefix = '')** — создание уникального идентификатора, похожего на заказ.
**uni.$stringUtil.parseUrl(url)** — анализ URL.
**uni.$stringUtil.parseUrlQuery(str)** — разбор строки запроса URL.
**uni.$stringUtil.buildUrl(obj)** — сборка URL из объекта.
**uni.$numberUtil.toDecimal(number, dotNum = 2)** — сохранение десятичных знаков.
**uni.$numberUtil.toSimplify(num, isLetter = false)** — упрощение числа.
**uni.$timeUtil.format(formatStr = 'yyyy-MM-dd hh:mm:ss', date = new Date())** — форматирование даты.
**uni.$timeUtil.todayStart(date = new Date())**, **uni.$timeUtil.todayEnd(date = new Date())**, **uni.$timeUtil.today(start = new Date(), end = new Date())** — получение времени начала и окончания текущего дня.
### Промежуточное ПО
> common/config/middleware.js — промежуточное ПО.
> В ближайшее время будет удалено: в повседневной разработке промежуточное ПО практически не используется, а его применение сложно для понимания. Вместо этого рекомендуется использовать прослушиватели событий.
```javascript
// Промежуточное ПО конфигурации
// Создание промежуточного ПО uni.$middleware();
// Список встроенных промежуточных ПО uni.$middlewares
import bindUser from './bind-user';
import loadConfig from './load-config';
module.exports = {
appLaunch: [
bindUser,
loadConfig
],
appShow: [
bindUser
],
appHide: [],
appRoute: [],
appRouteDone: [],
appUnhang: []
};
common/mixins/page.js — расширение методов экземпляра страницы.
module.exports = {
// Установка значения data
setValue: function(e) {
this.setData(e.target.dataset);
}
};
common/mixins/component.js — расширение методов компонента.
module.exports = {};
// Вызов функции жизненного цикла
Vue.prototype.$callHook(name)
// Фильтр цен
Vue.filter('price', function(price, fixed = 0){});
// Дата
Vue.filter('date', function(timeStamp, isSeconds = false){})
// Дружественная дата
Vue.filter('firendlyDate', function(timeStamp) {})
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )