Heim  >  Artikel  >  Web-Frontend  >  So entwickeln Sie eine globale elastische Schichtkomponente in Uni-App (Codebeispiel)

So entwickeln Sie eine globale elastische Schichtkomponente in Uni-App (Codebeispiel)

青灯夜游
青灯夜游nach vorne
2022-03-07 19:59:585495Durchsuche

Wie entwickle ich eine globale elastische Schichtkomponente in der Uni-App? Der folgende Artikel stellt Ihnen anhand von Beispielen vor, wie Sie eine globale elastische Layer-Komponente in Uni-App implementieren. Ich hoffe, er wird Ihnen hilfreich sein!

So entwickeln Sie eine globale elastische Schichtkomponente in Uni-App (Codebeispiel)

Das Unternehmen verfügt über eine App, die mit dem Uni-App-Framework geschrieben wurde. Die elastische Schicht im Inneren verwendet im Wesentlichen die offizielle uni.showModal und andere APIs, um die elastische Schicht auf dem Gerät zu implementieren. Auf Wunsch des Kunden musste es an den entworfenen Stil angepasst werden, also begannen wir mit der Implementierung einer solchen Komponente.

Entsprechend den von der elastischen Schicht häufig verwendeten Methoden und Methoden können die von ihr benötigten Attribute und Methoden grob aufgelistet werden:

  • Typ: alert/confirm usw. alert/confirm
  • 展示图标 icon
  • 展示内容 content
  • 可以api调用
  • 支持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 !== &#39;none&#39; && 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="{&#39;is-reverse-cofirmcancel&#39; : 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: &#39;取消&#39;, // 取消按钮文字
                showConfirmButton: true, // 是否显示确认按钮
                confirmButtonText: &#39;取消&#39;, // 确认按钮文字
                showIcon: true, // 是否显示图标
                iconClass: null, // 图标class自定义
                type: &#39;none&#39;, // 类型
                confirm: null, // 点击确认后的逻辑
                cancel: null, // 点击取消后的逻辑
                msg: &#39;&#39;
        }
        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 === &#39;function&#39;) {
                    confirmHandler()
            }
            this.close()
            this.$emit(&#39;confirm&#39;)
    },
    cancelClick() {
            const cancelHandler = this.option.cancel
            if (cancelHandler && typeof cancelHandler === &#39;function&#39;) {
                    cancelHandler()
            }
            this.close()
            this.$emit(&#39;cancel&#39;)
    }
}

目前在其他页面已经可以使用

// 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: &#39;测试&#39;,
    confirm: () => {
        console.log(&#39;点击了确认&#39;)
    },
    cancel: () => {
        console.log(&#39;点击了取消&#39;)
    }
})

现在基本功能已经实现,但是有人要说了,这样调用不方便,我想这样调用

open(msg).then(() => {
    console.log(&#39;点击了确认&#39;)
}).catch(() => {
     console.log(&#39;点击了取消&#39;)
})

那如何实现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 === &#39;object&#39;) {
                option = msg
        } else {
                option.msg = msg
        }
        return this.open({
                ...option,
                showCancelButton: true,
                type: &#39;confirm&#39;
        })
}
// 调用方式
this.$refs.stLayer.confirm(&#39;是否确认?&#39;).then().catch()

这样基本的弹层组件已经实现。下面也就是最后一步全局使用原有vue项目写的layer组件要全局使用通常是采用下面的方法注入到页面中

import main from &#39;./main.vue&#39;

const LayerConstructor = vue.extend(main)

const initInstance = () => {
  instance = new LayerConstructor({
    el: document.createElement(&#39;div&#39;)
  })

  instance.callback = defaultCallback
  document.getElementById(&#39;app&#39;).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(&#39;vue&#39;)
                    .test(/\.vue$/)
                    .use()
                    .loader(path.resolve(__dirname, "./node_modules/vue-inset-loader"))
                    .end()
	} 
}
// 支持自定义pages.json文件路径  
// options: {  
//     pagesPath: path.resolve(__dirname,&#39;./src/pages.json&#39;)  
// } 
// 第三步 pages.json配置文件中添加insetLoader
"insetLoader": {  
    "config":{  
        "confirm": "<BaseConfirm ref=&#39;confirm&#39;></BaseConfirm>",  
        "abc": "<BaseAbc ref=&#39;BaseAbc&#39;></BaseAbc>"  
    },  
    // 全局配置  
    "label":["confirm"],  
    "rootEle":"div"  
}

配置说明

  • config (default: {})
    定义标签名称和内容的键值对

  • label(default: [])
    需要全局引入的标签,打包后会在所有页面引入此标签

  • rootEle(default: "div")
    根元素的标签类型,缺省值为div,支持正则,比如匹配任意标签 ".*" 

     label 和 rootEle

    Symbolsymbol anzeigen
Inhalt anzeigen

Kann per API aufgerufen werden

Unterstützt promise, Sie können $api.xx().then verwenden

Die ersten paar Punkte sind einfach Um dies zu tun, müssen Sie nur in data die Felder in definieren und direkt das offizielle Rad uni-popup in der äußeren Ebene verwenden. Dadurch ersparen Sie sich das Schreiben einiger Popup-Steuerungslogik (faul), und die allgemeine Struktur wird geschrieben sagte, dass es unpraktisch ist, es so zu nennen. Ich möchte es so nennen. Der einfachste Weg besteht darin, die Methode open ein promise zurückgeben zu lassen. Wie gebe ich die Methode then ein, wenn ich auf „Bestätigen“ oder „Abbrechen“ klicke? Siehe die Schreibmethode unten

rrreee🎜Wenn Sie andere separate Methoden wie bestätigen kapseln möchten, können Sie diese öffnen die grundlegende obere Erweiterung: 🎜rrreee🎜 Eine solche grundlegende elastische Schichtkomponente wurde implementiert. Das Folgende ist der letzte Schritt globale Verwendung Wenn die im ursprünglichen Vue-Projekt geschriebene Ebenenkomponente global verwendet werden muss, wird sie normalerweise mit der folgenden Methode in die Seite eingefügt: 🎜rrreee🎜 Ziehen Sie sie direkt über und Verwenden Sie es, und das Ergebnis ist ein Fehler, der Fehler: Dokument ist undefiniert auffordert. Dann fiel mir ein, dass sich uni-app stark von gewöhnlichen Vue-Projekten unterscheidet, die in eingeführt werden Sein Funktionsprinzip: 🎜🎜🎜uni -app Die Logikschicht und die Ansichtsschicht sind getrennt. Bei der Ausführung auf der Nicht-H5-Seite ist sie in zwei Teile unterteilt: die Logikschicht und die Ansichtsschicht . Die Logikschicht ist für die Ausführung der Geschäftslogik verantwortlich, dh für die Ausführung von JS-Code, und die Ansichtsschicht ist für das Rendern von Seiten verantwortlich. Obwohl Entwickler JS und CSS auf einer Vue-Seite schreiben, werden sie beim Kompilieren tatsächlich aufgeteilt. Die Logikschicht wird in einem unabhängigen JScore ausgeführt, sodass einerseits keine Browserkompatibilitätsprobleme auftreten und es6-Code unter Android 4.4 ausgeführt werden kann. Andererseits kann sie kein Fenster, kein Dokument usw. ausführen. Navigator, Localstorage und andere browserspezifische JS-APIs. 🎜🎜🎜Daher ist diese Methode der globalen Registrierung nicht mehr verfügbar. Wie implementiert man es also in uni-app? Als ich das offizielle Forum durchstöberte, fand ich eine Implementierung von Loadervue-inset-loader🎜, Implementierungsprinzip Es dient dazu, den Inhalt der SFC-Vorlage abzurufen und benutzerdefinierten Inhalt (d. h. globale Komponenten) an der angegebenen Stelle einzufügen. Die Verwendungsmethode lautet wie folgt: 🎜rrreee

Konfigurationsanweisungen🎜🎜🎜config (Standard: {})
Schlüssel-Wert-Paare, die den Labelnamen und den Inhalt definieren🎜🎜🎜🎜label (Standard: [])
Ein Tag, der global eingeführt werden muss. Dieses Tag wird nach dem Packen auf allen Seiten eingeführt🎜🎜🎜🎜rootElecode>(Standard: "div" code>)
Der Beschriftungstyp des Stammelements, der Standardwert ist div, unterstützt reguläre Regeln, z. B. die Übereinstimmung mit jeder Beschriftung „.*“ 🎜🎜 label
und rootEle werden im Stil einer separaten Seite konfiguriert, die Priorität ist höher als die globale Konfiguration. Zu diesem Zeitpunkt kann die Komponente nicht global verwendet werden Um Tags auf jede Seite zu schreiben, müssen Sie nur die API aufrufen. 🎜🎜Sie können es später je nach Nutzung optimieren. Das Niveau ist begrenzt, jeder Rat ist willkommen. 🎜🎜Empfohlen: „🎜uniapp-Tutorial🎜“🎜

Das obige ist der detaillierte Inhalt vonSo entwickeln Sie eine globale elastische Schichtkomponente in Uni-App (Codebeispiel). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:juejin.cn. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen