Heim > WeChat-Applet > Mini-Programmentwicklung > So rendern Sie HTML-Inhalte im WeChat-Applet (Codebeispiel)

So rendern Sie HTML-Inhalte im WeChat-Applet (Codebeispiel)

不言
Freigeben: 2018-10-25 16:29:24
nach vorne
5117 Leute haben es durchsucht

Der Inhalt dieses Artikels befasst sich mit dem Rendern von HTML-Inhalten (Codebeispiele) in WeChat-Miniprogrammen. Ich hoffe, dass er für Sie hilfreich ist. .

Der Rich-Text-Inhalt der meisten Webanwendungen wird in Form von HTML-Strings gespeichert. Die Anzeige von HTML-Inhalten über HTML-Dokumente ist kein Problem. Wie soll dieser Teil des Inhalts jedoch im WeChat-Miniprogramm (im Folgenden „Miniprogramm“ genannt) gerendert werden?

Lösung

wxParse

Als das Applet zum ersten Mal gestartet wurde, war es unmöglich, HTML-Inhalte direkt zu rendern, daher wurde eine Bibliothek namens „wxParse“ geboren. Sein Prinzip besteht darin, HTML-Code in baumstrukturierte Daten zu analysieren und die Daten dann über die Vorlage des Miniprogramms zu rendern.

Rich-Text

Später fügte das Miniprogramm die „Rich-Text“-Komponente hinzu, um Rich-Text-Inhalte anzuzeigen. Allerdings weist diese Komponente eine große Einschränkung auf: Das Ereignis aller Knoten wird innerhalb der Komponente blockiert. Mit anderen Worten: In dieser Komponente kann nicht einmal eine einfache Funktion wie „Vorschaubild“ implementiert werden.

Web-Ansicht

Später ermöglicht das Miniprogramm das Verschachteln von Webseiten über die „Web-Ansicht“-Komponente. Die Anzeige von HTML-Inhalten über Webseiten ist die kompatibelste Lösung. Da jedoch eine weitere Seite geladen werden muss, ist die Leistung schlecht.

Wenn „WePY“ auf „wxParse“ trifft

Basierend auf Benutzererfahrung und Überlegungen zur funktionalen Interaktion haben wir die beiden nativen Komponenten „Rich-Text“ und „Web-View“ aufgegeben und „wxParse“ ausgewählt ". Nach der Verwendung stellte ich jedoch fest, dass „wxParse“ die Anforderungen nicht gut erfüllen kann:

  • Unser kleines Programm basiert auf dem „WePY“-Framework und „wxParse“ basiert darauf Geschrieben von einem nativen Applet. Um die beiden kompatibel zu machen, muss der Quellcode von „wxParse“ geändert werden.

  • „wxParse“ zeigt einfach das Bild des ursprünglichen IMG-Elements über die Bildkomponente an und zeigt eine Vorschau an. Bei der tatsächlichen Verwendung kann die Cloud-Speicherschnittstelle verwendet werden, um die Größe des Bildes zu reduzieren, um den Zweck „ Anzeige mit einem kleinen Bild und Vorschau mit dem Originalbild “ zu erreichen.

  • „wxParse“ verwendet direkt die Videokomponente des Miniprogramms, um Videos anzuzeigen, aber die Ebenenprobleme der Videokomponente führen häufig zu Anomalien der Benutzeroberfläche (z. B. dem Ersetzen eines feststehendes Element blockiert).

Darüber hinaus zeigt ein kurzer Blick auf das Code-Repository von „wxParse“, dass es seit zwei Jahren nicht mehr iteriert wurde. So entstand die Idee, eine Rich-Text-Komponente basierend auf dem „WePY“-Komponentenmodell neu zu schreiben, und das Ergebnis war das „WePY HTML“-Projekt.

Implementierungsprozess

HTML analysieren

Zuerst muss die HTML-Zeichenfolge in baumstrukturierte Daten analysiert werden. Ich verwende die „Sonderzeichentrennungsmethode“. Die Sonderzeichen in HTML sind „“, ersteres ist das Startzeichen und letzteres ist das Endzeichen.

•Wenn der zu analysierende Inhalt mit einem Startzeichen beginnt, wird der Inhalt zwischen dem Startzeichen und dem Endzeichen abgefangen und als Knoten analysiert.
•Wenn der zu analysierende Inhalt nicht mit einem Startzeichen beginnt, wird der Inhalt vom Anfang bis vor dem Startzeichen (oder bis zum Ende, wenn das Startzeichen nicht vorhanden ist) abgefangen und als einfacher Text analysiert.
•Der verbleibende Inhalt gelangt in die nächste Analyserunde, bis kein verbleibender Inhalt mehr vorhanden ist.
Wie in der Abbildung unten gezeigt:

So rendern Sie HTML-Inhalte im WeChat-Applet (Codebeispiel)

Um eine Baumstruktur zu bilden, wird ein Kontextknoten (standardmäßig der Wurzelknoten) benötigt während des Analysevorgangs beibehalten:

•Wenn der abgefangene Inhalt ein Start-Tag ist, wird ein untergeordneter Knoten unter dem aktuellen Kontextknoten basierend auf dem übereinstimmenden Tag-Namen und den Attributen erstellt. Wenn es sich bei dem Tag nicht um ein selbstschließendes Tag handelt (br, img usw.), wird der Kontextknoten auf den neuen Knoten gesetzt.
•Wenn es sich bei dem abgefangenen Inhalt um ein End-Tag handelt, schließen Sie den aktuellen Kontextknoten entsprechend dem Tag-Namen (legen Sie den Kontextknoten als übergeordneten Knoten fest).
•Wenn es sich um einfachen Text handelt, wird unter dem aktuellen Kontextknoten ein Textknoten erstellt und der Kontextknoten bleibt unverändert.
Der Prozess ist wie in der folgenden Tabelle dargestellt:

So rendern Sie HTML-Inhalte im WeChat-Applet (Codebeispiel)

Nach dem obigen Prozess wird die HTML-Zeichenfolge in einen Knotenbaum analysiert.

Vergleich
Vergleichen Sie den obigen Algorithmus mit anderen ähnlichen Parsing-Algorithmen (Leistung wird durch „Parsen von HTML-Code mit 10.000 Längen“ gemessen):

So rendern Sie HTML-Inhalte im WeChat-Applet (Codebeispiel)

可见,在不考虑容错性(产生错误的结果,而非抛出异常)的情况下,本组件的算法与其余两者相比有压倒性的优势,符合小程序「 小而快 」的需要。而一般情况下,富文本编辑器所生成的代码也不会出现语法错误。因此,即使容错性较差,问题也不大(但这是需要改进的)。

模板渲染

树结构的渲染,必然会涉及到子节点的 递归 处理。然而,小程序的模板并不支持递归,这下仿佛掉入了一个大坑。

看了一下「wxParse」模板的实现,它采用简单粗暴的方式解决这个问题:通过13个长得几乎一模一样的模板进行嵌套调用(1调用2,2调用3,……,12调用13),也就是说最多可以支持12次嵌套。一般来说,这个深度也足够了。

由于「WePY」框架本身是有构建机制的,所以不必手写十来个几乎一模一样的模板,通过一个构建的插件去生成即可。

以下为需要重复嵌套的模板(精简过),在其代码的开始前和结束后分别插入特殊注释进行标识,并在需要嵌入下一层模板的地方以另一段特殊注释(「」)标识:

<!-- wepyhtml-repeat start -->
<template>
    <block>
        <block>
            <view>
                <!-- next template -->
            </view>
        </block>
        <block>{{ item.text }}</block>
    </block>
</template>
<!-- wepyhtml-repeat end -->
Nach dem Login kopieren

以下是对应的构建代码(需要安装「 wepy-plugin-replace 」):

// wepy.config.js
{
    plugins: {
        replace: {
            filter: /\.wxml$/,
            config: {
                find: /([\W\w]+?)/,
                replace(match, tpl) {
                    let result = '';
                    // 反正不要钱,直接写个20层嵌套
                    for (let i = 0; i /g, () => {
                                return i === 20 ?
                                    '' :
                                    `<template></template>`;
                            });
                    }
                    return result;
                }
            }
        }
    }
}
Nach dem Login kopieren

然而,运行起来后发现,第二层及更深层级的节点都没有渲染出来,说明嵌套失败了。再看一下dist目录下生成的wxml文件可以发现,变量名与组件源代码的并不相同:

<block></block>
Nach dem Login kopieren

「WePY」在生成组件代码时,为了避免组件数据与页面数据的变量名冲突,会 根据一定的规则给组件的变量名增加前缀 (如上面代码中的「$htmlContent$wepyHtml$」)。所以在生成嵌套模板时,也必须使用带前缀的变量名。

先在组件代码中增加一个变量「thisIsMe」用于识别前缀:

<!-- wepyhtml-repeat start -->
<template>
    {{ thisIsMe }}
    <block>
        <block>
            <view>
                <!-- next template -->
            </view>
        </block>
        <block>{{ item.text }}</block>
    </block>
</template>
<!-- wepyhtml-repeat end -->
Nach dem Login kopieren

然后修改构建代码:

replace(match, tpl) {
    let result = '';
    let prefix = '';

    // 匹配 thisIsMe 的前缀
    tpl = tpl.replace(/\{\{\s*(\$.*?\$)thisIsMe\s*\}\}/, (match, p) => {
        prefix = p;
        return '';
    });

    for (let i = 0; i /g, () => {
                return i === 20 ?
                    '' :
                    `<template></template>`;
            });
    }

    return result;
}
Nach dem Login kopieren

至此,渲染问题就解决了。

图片
为了节省流量和提高加载速度,展示富文本内容时,一般都会按照所需尺寸对里面的图片进行缩小,点击小图进行预览时才展示原图。这主要涉及节点属性的修改:

•把图片原路径(src属性值)存到自定义属性(例如「src」)中,并将其添加到预览图数组。
•把图片的src属性值修改为缩小后的图片URL(一般云服务商都有提供此类URL规则)。
•点击图片时,使用自定义属性的值进行预览。
为了实现这个需求,本组件在解析节点时提供了一个钩子( onNodeCreate ):

onNodeCreate(name, attrs) {
    if (name === 'img') {
        attrs['src'] = attrs.src;
        // 预览图数组
        this.previewImgs.push(attrs.src);
        // 缩图
        attrs.src = resizeImg(attrs.src, 640);
    }
}
Nach dem Login kopieren

对应的模板和事件处理逻辑如下:

<template>
    <image></image>
</template>
Nach dem Login kopieren
// 点击小图看大图
imgTap(e) {
    wepy.previewImage({
        current: e.currentTarget.dataset.src,
        urls: this.previewImgs
    });
}
Nach dem Login kopieren

视频

在小程序中,video组件的层级是较高的(且无法降低)。如果页面设计上存在着可能挡住视频的元素,处理起来就需要一些技巧了:

•隐藏video组件,用image组件(视频封面)占位;
•点击图片时,让视频全屏播放;
•如果退出了全屏,则暂停播放。
相关代码如下:

<template>
    <view>
        <!-- 视频封面 -->
        <image></image>
        <!-- 播放图标 -->
        <image></image>
        <!-- 视频组件 -->
        <video></video>
    </view>
</template>
Nach dem Login kopieren
{
    // 点击封面图,播放视频
    videoTap(e) {
        const nodeId = e.currentTarget.dataset.nodeid;
        const context = wepy.createVideoContext('wepyhtml-video-' + nodeId);
        context.play();
        // 在安卓微信下,如果视频不可见,则调用play()也无法播放
        // 需要再调用全屏方法
        if (wepy.getSystemInfoSync().platform === 'android') {
            context.requestFullScreen();
        }
    },
    // 视频层级较高,为防止遮挡其他特殊定位元素,造成界面异常,
    // 强制全屏播放
    videoPlay(e) {
        wepy.createVideoContext(e.currentTarget.id).requestFullScreen();
    },
    // 退出全屏则暂停
    videoFullscreenChange(e) {
        if (!e.detail.fullScreen) {
            wepy.createVideoContext(e.currentTarget.id).pause();
        }
    }
}
Nach dem Login kopieren


Das obige ist der detaillierte Inhalt vonSo rendern Sie HTML-Inhalte im WeChat-Applet (Codebeispiel). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:segmentfault.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage