Maison  >  Article  >  Applet WeChat  >  Comment restituer le contenu HTML dans l'applet WeChat (exemple de code)

Comment restituer le contenu HTML dans l'applet WeChat (exemple de code)

不言
不言avant
2018-10-25 16:29:075098parcourir

Le contenu de cet article explique comment restituer du contenu HTML (exemples de code) dans les mini-programmes WeChat. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer. .

Le contenu textuel riche de la plupart des applications Web est stocké sous forme de chaînes HTML. Il n'y a aucun problème pour afficher le contenu HTML via des documents HTML. Cependant, comment cette partie du contenu doit-elle être restituée dans le mini-programme WeChat (ci-après dénommé « mini-programme ») ?

Solution

wxParse

Lorsque l'applet a été lancée pour la première fois, il était impossible de restituer directement le contenu HTML, c'est pourquoi une bibliothèque appelée "wxParse" est née. Son principe est d'analyser le code HTML en données arborescentes, puis de restituer les données via le modèle du mini programme.

rich-text

Plus tard, le mini-programme a ajouté le composant "rich-text" pour afficher du contenu en texte enrichi. Cependant, ce composant présente une énorme limitation : L'événement de tous les nœuds est bloqué au sein du composant. En d'autres termes, dans ce composant, même une fonction simple telle que « image d'aperçu » ne peut pas être implémentée.

web-view

Plus tard, le mini programme permet d'imbriquer des pages Web via le composant "web-view". L'affichage de contenu HTML via des pages Web est la solution la plus compatible. Cependant, comme une page supplémentaire doit être chargée, les performances sont médiocres.

Quand "WePY" rencontre "wxParse"

Sur la base de considérations d'expérience utilisateur et d'interaction fonctionnelle, nous avons abandonné les deux composants natifs "rich-text" et "web-view", sélectionné "wxParse ". Cependant, après l'avoir utilisé, j'ai constaté que "wxParse" ne pouvait pas bien répondre aux besoins :

  • Notre applet est développée sur la base du framework "WePY", et "wxParse" est basée sur Written par applet native. Pour rendre les deux compatibles, le code source de "wxParse" doit être modifié.

  • "wxParse" affiche et prévisualise simplement l'image de l'élément img d'origine via le composant image. En utilisation réelle, l'interface de stockage cloud peut être utilisée pour réduire l'image afin d'atteindre l'objectif de " afficher avec une petite image et utiliser l'image originale pour prévisualiser ".

  • "wxParse" utilise directement le composant vidéo du mini-programme pour afficher des vidéos, mais les problèmes de niveau du composant vidéo entraînent souvent des anomalies de l'interface utilisateur (comme le remplacement d'un élément fixe bloqué).

De plus, un rapide coup d'œil au référentiel de code de « wxParse » montre qu'il n'a pas été itéré depuis deux ans. C'est ainsi qu'est née l'idée de réécrire un composant de texte enrichi basé sur le modèle de composant "WePY", et le résultat a été le projet "WePY HTML".

Processus d'implémentation

Analyse HTML

La première étape consiste à analyser la chaîne HTML en données arborescentes. J'utilise la "méthode de séparation des caractères spéciaux". Les caractères spéciaux en HTML sont "", le premier est le caractère de début et le second est le caractère de fin.

•Si le contenu à analyser commence par un caractère de début, le contenu entre le caractère de début et le caractère de fin sera intercepté et analysé en tant que nœuds.
•Si le contenu à analyser ne commence pas par un caractère de début, le contenu du début jusqu'à avant le caractère de début (ou la fin si le caractère de début n'existe pas) sera intercepté et analysé sous forme de texte brut.
•Le contenu restant entrera dans le prochain cycle d'analyse jusqu'à ce qu'il n'y ait plus de contenu restant.
Comme le montre la figure ci-dessous :

Comment restituer le contenu HTML dans lapplet WeChat (exemple de code)

Afin de former une arborescence, un nœud de contexte (le nœud racine par défaut) est conservé pendant le processus d'analyse :

•Si le contenu intercepté est une balise de début, un nœud enfant sera créé sous le nœud de contexte actuel en fonction du nom et des attributs de la balise correspondant. Si la balise n'est pas une balise à fermeture automatique (br, img, etc.), le nœud contextuel est défini sur le nouveau nœud.
•Si le contenu intercepté est une balise de fin, fermez le nœud de contexte actuel en fonction du nom de la balise (définissez le nœud de contexte comme son nœud parent).
•S'il s'agit de texte brut, un nœud de texte est créé sous le nœud de contexte actuel et le nœud de contexte reste inchangé.
Le processus est présenté dans le tableau ci-dessous :

Comment restituer le contenu HTML dans lapplet WeChat (exemple de code)

Après le processus ci-dessus, la chaîne HTML est analysée dans une arborescence de nœuds.

Comparaison
Comparez l'algorithme ci-dessus avec d'autres algorithmes d'analyse similaires (les performances sont mesurées en "analysant un code HTML de 10 000 longueurs") :

Comment restituer le contenu HTML dans lapplet WeChat (exemple de code)

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

模板渲染

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

看了一下「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 -->

以下是对应的构建代码(需要安装「 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;
                }
            }
        }
    }
}

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

<block></block>

「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 -->

然后修改构建代码:

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;
}

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

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

•把图片原路径(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);
    }
}

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

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

视频

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

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

<template>
    <view>
        <!-- 视频封面 -->
        <image></image>
        <!-- 播放图标 -->
        <image></image>
        <!-- 视频组件 -->
        <video></video>
    </view>
</template>
{
    // 点击封面图,播放视频
    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();
        }
    }
}


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!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer