Comment développer un composant de couche élastique globale dans uni-app ? L'article suivant vous présentera, à travers des exemples, comment implémenter un composant de couche élastique globale dans uni-app. J'espère qu'il vous sera utile !
La société dispose d'une application écrite à l'aide du framework uni-app. La couche élastique à l'intérieur utilise essentiellement l'uni.showModal officiel et d'autres API pour implémenter la couche élastique. Elle se comporte comme une couche élastique native sur l'appareil. À la demande du client, il a fallu le modifier selon le style conçu, nous avons donc commencé à mettre en œuvre un tel composant.
Selon les méthodes et méthodes fréquemment utilisées par la couche élastique, les attributs et méthodes dont elle a besoin peuvent être grossièrement listés :
alerte/confirmation
, etc. alert/confirm
等promise
,可以使用$api.xx().then
前几项就很好做,就在data
中定义好字段,外层直接拿官方的轮子uni-popup
,这样少写一些控制弹出的逻辑(懒的),这样大致结构就写好了
// template部分 <uni-popup ref="popup" :maskClick="maskClick"> <view class="st-layer" :style="{ width: width }"> <view class="st-layer__content"> <!-- #ifndef APP-NVUE --> <text class="st-layer__icon" :class="option.iconClass || getIconClass()" v-if="option.type !== 'none' && option.showIcon"></text> <!-- #endif --> <view class="st-layer__msg" v-if="option.msg"> <text>{{ option.msg }}</text> </view> </view> <view class="st-layer__footer" :class="{'is-reverse-cofirmcancel' : isReverseConfirmCancel}" v-if="option.showConfirmButton || option.showCancelButton"> <view class="st-layer__footer__btn st-layer__footer__btn--confirm" @tap.stop="confirmClick" v-if="option.showConfirmButton"><text>确认</text></view> <view class="st-layer__footer__btn st-layer__footer__btn--cancel" @tap.stop="cancelClick" v-if="option.showCancelButton"><text>取消</text></view> </view> </view> </uni-popup>
然后js部分先简单实现了一些open和close方法
data() { return { option: {} } }, methods: { open(option) { let defaultOption = { showCancelButton: false, // 是否显示取消按钮 cancelButtonText: '取消', // 取消按钮文字 showConfirmButton: true, // 是否显示确认按钮 confirmButtonText: '取消', // 确认按钮文字 showIcon: true, // 是否显示图标 iconClass: null, // 图标class自定义 type: 'none', // 类型 confirm: null, // 点击确认后的逻辑 cancel: null, // 点击取消后的逻辑 msg: '' } this.option = Object.assign({}, defaultOption, option) this.$refs.popup.open() }, close() { this.$refs.popup.close() }, confirmClick() { const confirmHandler = this.option.confirm if (confirmHandler && typeof confirmHandler === 'function') { confirmHandler() } this.close() this.$emit('confirm') }, cancelClick() { const cancelHandler = this.option.cancel if (cancelHandler && typeof cancelHandler === 'function') { cancelHandler() } this.close() this.$emit('cancel') } }
目前在其他页面已经可以使用
// test.vue 可以使用uni-app的 [easycom组件规范](https://uniapp.dcloud.io/component/README?id=easycom%e7%bb%84%e4%bb%b6%e8%a7%84%e8%8c%83),不用写import语句 <st-layer ref="stLayer"></st-layer> // js部分 this.$refs.stLayer.open({ msg: '测试', confirm: () => { console.log('点击了确认') }, cancel: () => { console.log('点击了取消') } })
现在基本功能已经实现,但是有人要说了,这样调用不方便,我想这样调用
open(msg).then(() => { console.log('点击了确认') }).catch(() => { console.log('点击了取消') })
那如何实现promise
化呢?最简单的方法就是让open方法返回一个promise
。如何点击确认或取消的时候进入then
方法呢,看下面的写法
... open() { return new promise((reoslve, reject) => { ... this.option.confirm = this.option.confirm || function confirmResolve () { resolve() } this.option.cancel = this.option.cancel || function cancelReject () { reject() } }) } ...
如果要封装其他单独的方法,比如confirm
之类,可以在open基础上扩展:
confirm(msg, option = {}) { if (typeof msg === 'object') { option = msg } else { option.msg = msg } return this.open({ ...option, showCancelButton: true, type: 'confirm' }) } // 调用方式 this.$refs.stLayer.confirm('是否确认?').then().catch()
这样基本的弹层组件已经实现。下面也就是最后一步全局使用
原有vue项目写的layer组件要全局使用通常是采用下面的方法注入到页面中
import main from './main.vue' const LayerConstructor = vue.extend(main) const initInstance = () => { instance = new LayerConstructor({ el: document.createElement('div') }) instance.callback = defaultCallback document.getElementById('app').appendChild(instance.$el) }
直接拉过来用,结果报错,提示error: document is undefined
,才想起uni-app
跟普通vue项目的有一个很大的区别,在它的运行原理中有介绍:
uni-app
逻辑层和视图层分离,在非H5端运行时,从架构上分为逻辑层和视图层两个部分。逻辑层负责执行业务逻辑,也就是运行js代码,视图层负责页面渲染。虽然开发者在一个vue页面里写js和css,但其实,编译时就已经将它们拆分了。逻辑层是运行在一个独立的jscore里的,它不依赖于本机的webview,所以一方面它没有浏览器兼容问题,可以在Android4.4上跑es6代码,另一方面,它无法运行window、document、navigator、localstorage等浏览器专用的js API。
所以这种注册全局的方法已经不可用。那该如何在uni-app
中实现呢?
翻看官方论坛,找到了一个实现loadervue-inset-loader
,实现原理就是获取sfc模板内容,在指定位置插入自定义内容(也就是需要全局的组件),使用方式如下:
// 第一步 npm install vue-inset-loader --save-dev // 第二步 在vue.config.js(hbuilderx创建的项目没有的话新建一个)中注入loader module.export = { chainWebpack: config => { // 超级全局组件 config.module .rule('vue') .test(/\.vue$/) .use() .loader(path.resolve(__dirname, "./node_modules/vue-inset-loader")) .end() } } // 支持自定义pages.json文件路径 // options: { // pagesPath: path.resolve(__dirname,'./src/pages.json') // } // 第三步 pages.json配置文件中添加insetLoader "insetLoader": { "config":{ "confirm": "<BaseConfirm ref='confirm'></BaseConfirm>", "abc": "<BaseAbc ref='BaseAbc'></BaseAbc>" }, // 全局配置 "label":["confirm"], "rootEle":"div" }
config
(default: {}
)
定义标签名称和内容的键值对
label
(default: []
)
需要全局引入的标签,打包后会在所有页面引入此标签
rootEle
(default: "div"
)
根元素的标签类型,缺省值为div,支持正则,比如匹配任意标签 ".*"
label
和 rootEle
Peut être appelé par apiPrend en charge la
promesse
, vous pouvez utiliser $api.xx().then
Les premiers éléments sont faciles à faire, juste dans data Définissez les champs dans
et utilisez directement la roue officielle uni-popup
dans la couche externe. Cela vous évitera d'écrire une logique de contrôle pop-up. (paresseux), et la structure générale sera écrite
promesse
? Le moyen le plus simple est de laisser la méthode open renvoyer une promesse
. Comment saisir la méthode then
en cliquant sur confirmer ou annuler ? Voir la méthode d'écriture ci-dessous🎜rrreee🎜Si vous souhaitez encapsuler d'autres méthodes distinctes, telles que confirmer
, vous pouvez ouvrir l'extension supérieure de base : 🎜rrreee🎜 Un tel composant de couche élastique de base a été implémenté. Voici la dernière étape utilisation globale
Si le composant de couche écrit dans le projet vue d'origine doit être utilisé globalement, il est généralement injecté dans la page en utilisant la méthode suivante 🎜rrreee🎜 Extrayez-le directement et utilisez-le, et le résultat est une erreur, provoquant une erreur : le document n'est pas défini
, puis je me suis souvenu que uni-app
est très différent du projet vue ordinaire, qui est introduit dans son principe de fonctionnement : 🎜🎜🎜uni -app
La couche logique et la couche vue sont séparées Lorsqu'elle est exécutée du côté non-H5, elle est divisée en deux parties : la couche logique et la vue. couche. La couche logique est responsable de l'exécution de la logique métier, c'est-à-dire de l'exécution du code js, et la couche vue est responsable du rendu des pages. Bien que les développeurs écrivent js et css dans une page vue, ils sont en fait divisés lors de la compilation. La couche logique s'exécute dans un jscore indépendant. Elle ne dépend pas de la vue Web locale, donc d'une part elle n'a aucun problème de compatibilité avec le navigateur et peut exécuter du code es6 sur Android 4.4. D'autre part, elle ne peut pas exécuter Windows, Browser-. API js spécifiques telles que document, navigateur et stockage local. 🎜🎜🎜Cette méthode d'inscription globale n'est donc plus disponible. Alors, comment l'implémenter dans uni-app
?
En parcourant le forum officiel, j'ai trouvé une implémentation de loadervue-inset-loader
🎜, principe de mise en œuvre Il s'agit d'obtenir le contenu du modèle sfc et d'insérer du contenu personnalisé (c'est-à-dire des composants globaux) à l'emplacement spécifié. La méthode d'utilisation est la suivante : 🎜rrreee{}
)label
(par défaut : []
)rootEle
code>(par défaut : "div" code>)
Le type d'étiquette de l'élément racine, la valeur par défaut est div, prend en charge les règles régulières, telles que la correspondance avec n'importe quelle étiquette ".*" 🎜🎜 label
et rootEle
Configuré dans le style d'une page séparée, la priorité est supérieure à la configuration globale 🎜🎜🎜🎜 À ce stade, le composant peut être utilisé globalement. pas besoin d'écrire des balises sur chaque page pour l'utiliser. Il suffit d'appeler l'API. 🎜🎜Vous pouvez l'optimiser plus tard en fonction de l'utilisation. Le niveau est limité, les conseils de chacun sont les bienvenus. 🎜🎜Recommandé : "🎜Tutoriel uniapp🎜"🎜Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!