목차
Solution
wxParse
rich-text
web-view
"WePY"가 "wxParse"를 만났을 때
구현 과정
HTML 구문 분석
模板渲染
视频
위챗 애플릿 미니 프로그램 개발 WeChat 애플릿에서 HTML 콘텐츠를 렌더링하는 방법(코드 예)

WeChat 애플릿에서 HTML 콘텐츠를 렌더링하는 방법(코드 예)

Oct 25, 2018 pm 04:29 PM
css html html5

이 기사의 내용은 WeChat 미니 프로그램에서 HTML 콘텐츠(코드 예제)를 렌더링하는 방법에 대한 것입니다. 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.

대부분의 웹 애플리케이션의 서식 있는 텍스트 콘텐츠는 HTML 문자열 형식으로 저장됩니다. HTML 문서를 통해 HTML 콘텐츠를 표시하는 데 문제가 없습니다. 그런데 위챗 미니 프로그램(이하 '미니 프로그램')에서는 이 부분의 콘텐츠를 어떻게 렌더링해야 할까요?

Solution

wxParse

애플릿이 처음 출시되었을 때 HTML 콘텐츠를 직접 렌더링하는 것이 불가능하여 "wxParse"라는 라이브러리가 탄생했습니다. 그 원리는 HTML 코드를 트리 구조의 데이터로 구문 분석한 다음 미니 프로그램의 템플릿을 통해 데이터를 렌더링하는 것입니다.

rich-text

나중에 미니 프로그램은 리치 텍스트 콘텐츠를 표시하기 위해 "리치 텍스트" 구성 요소를 추가했습니다. 그러나 이 구성 요소에는 큰 제한이 있습니다. 모든 노드의 이벤트가 구성 요소 내에서 차단됩니다. 즉, 이 컴포넌트에서는 '미리보기 이미지'와 같은 간단한 기능조차 구현할 수 없습니다.

web-view

나중에 미니 프로그램에서는 "web-view" 구성 요소를 통해 웹 페이지를 중첩할 수 있게 되었으며, 웹 페이지를 통해 HTML 콘텐츠를 표시하는 것이 가장 호환되는 솔루션이었습니다. 하지만 한 페이지를 더 로드해야 하기 때문에 성능이 좋지 않습니다.

"WePY"가 "wxParse"를 만났을 때

사용자 경험과 기능적 상호 작용 고려 사항을 바탕으로 우리는 두 가지 기본 구성 요소인 "rich-text"와 "web-view"를 버리고 "wxParse"를 선택했습니다. 그러나 사용해 본 결과 "wxParse"는 요구 사항을 잘 충족할 수 없다는 것을 알게 되었습니다.

  • 저희 애플릿은 "WePY" 프레임워크를 기반으로 개발된 반면 "wxParse"는 기본 애플릿을 기반으로 작성되었습니다. 두 가지를 호환되게 하려면 "wxParse"의 소스 코드를 수정해야 합니다.

  • "wxParse"는 이미지 구성 요소를 통해 원본 img 요소의 이미지를 단순히 표시하고 미리 봅니다. 실제 사용에서는 "작은 이미지로 표시하고 원본 이미지로 미리보기"라는 목적을 달성하기 위해 클라우드 저장소 인터페이스를 사용하여 이미지를 축소할 수 있습니다.

  • "wxParse"는 미니 프로그램의 비디오 구성 요소를 직접 사용하여 비디오를 표시하지만 비디오 구성 요소의 레벨 문제로 인해 UI 이상(고정 위치 요소 차단 등)이 발생하는 경우가 많습니다.

그리고 “wxParse”의 코드 저장소를 잠깐 살펴보면 2년 동안 반복되지 않았음을 알 수 있습니다. 그래서 "WePY" 컴포넌트 모델을 기반으로 리치 텍스트 컴포넌트를 다시 작성하자는 아이디어가 나왔고, 그 결과물이 "WePY HTML" 프로젝트였습니다.

구현 과정

HTML 구문 분석

첫 번째 단계는 HTML 문자열을 트리 구조의 데이터로 구문 분석하는 것입니다. 저는 "특수 문자 분리 방법"을 사용합니다. HTML의 특수 문자는 ""이며, 전자는 시작 문자이고 후자는 끝 문자입니다.

•파싱할 콘텐츠가 시작 문자로 시작하는 경우 시작 문자와 끝 문자 사이의 콘텐츠를 가로채서 노드로 구문 분석합니다.
•파싱할 콘텐츠가 시작 문자로 시작하지 않는 경우 시작 문자 이전(또는 시작 문자가 없는 경우 끝)까지의 콘텐츠를 가로채서 일반 텍스트로 구문 분석합니다.
•남은 콘텐츠가 없을 때까지 남은 콘텐츠는 다음 분석에 들어갑니다.
아래 그림과 같이:

WeChat 애플릿에서 HTML 콘텐츠를 렌더링하는 방법(코드 예)

트리 구조를 형성하기 위해서는 구문 분석 과정에서 컨텍스트 노드(기본값은 루트 노드)가 유지되어야 합니다.

•차단된 콘텐츠가 다음과 같은 경우 시작 태그는 일치 항목을 기반으로 출력됩니다. 태그 이름과 속성은 현재 컨텍스트 노드 아래에 하위 노드를 생성합니다. 태그가 자체 닫는 태그(br, img 등)가 아닌 경우 컨텍스트 노드는 새 노드로 설정됩니다.
•가로챈 콘텐츠가 종료 태그인 경우 태그 이름에 따라 현재 컨텍스트 노드를 닫습니다(컨텍스트 노드를 상위 노드로 설정).
•일반 텍스트인 경우 현재 컨텍스트 노드 아래에 텍스트 노드가 생성되고 컨텍스트 노드는 변경되지 않습니다.
과정은 아래 표와 같습니다.

WeChat 애플릿에서 HTML 콘텐츠를 렌더링하는 방법(코드 예)

위 과정 후에 HTML 문자열이 노드 트리로 파싱됩니다.

비교
위 알고리즘을 다른 유사한 구문 분석 알고리즘과 비교합니다(성능은 "10,000 길이의 HTML 코드 구문 분석"으로 측정):

WeChat 애플릿에서 HTML 콘텐츠를 렌더링하는 방법(코드 예)

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

模板渲染

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

看了一下「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();
        }
    }
}
로그인 후 복사


위 내용은 WeChat 애플릿에서 HTML 콘텐츠를 렌더링하는 방법(코드 예)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

부트 스트랩 버튼을 사용하는 방법 부트 스트랩 버튼을 사용하는 방법 Apr 07, 2025 pm 03:09 PM

부트 스트랩 버튼을 사용하는 방법? 부트 스트랩 CSS를 소개하여 버튼 요소를 만들고 부트 스트랩 버튼 클래스를 추가하여 버튼 텍스트를 추가하십시오.

부트 스트랩 크기를 조정하는 방법 부트 스트랩 크기를 조정하는 방법 Apr 07, 2025 pm 03:18 PM

부트 스트랩에서 요소의 크기를 조정하려면 다음을 포함하여 차원 클래스를 사용할 수 있습니다.

부트 스트랩을위한 프레임 워크를 설정하는 방법 부트 스트랩을위한 프레임 워크를 설정하는 방법 Apr 07, 2025 pm 03:27 PM

부트 스트랩 프레임 워크를 설정하려면 다음 단계를 따라야합니다. 1. CDN을 통해 부트 스트랩 파일 참조; 2. 자신의 서버에서 파일을 다운로드하여 호스팅하십시오. 3. HTML에 부트 스트랩 파일을 포함; 4. 필요에 따라 Sass/Less를 컴파일하십시오. 5. 사용자 정의 파일을 가져옵니다 (선택 사항). 설정이 완료되면 Bootstrap의 그리드 시스템, 구성 요소 및 스타일을 사용하여 반응 형 웹 사이트 및 응용 프로그램을 만들 수 있습니다.

부트 스트랩에 사진을 삽입하는 방법 부트 스트랩에 사진을 삽입하는 방법 Apr 07, 2025 pm 03:30 PM

Bootstrap에 이미지를 삽입하는 방법에는 여러 가지가 있습니다. HTML IMG 태그를 사용하여 이미지를 직접 삽입하십시오. 부트 스트랩 이미지 구성 요소를 사용하면 반응 형 이미지와 더 많은 스타일을 제공 할 수 있습니다. 이미지 크기를 설정하고 IMG-Fluid 클래스를 사용하여 이미지를 적응할 수 있도록하십시오. IMG 통과 클래스를 사용하여 테두리를 설정하십시오. 둥근 모서리를 설정하고 IMG 라운드 클래스를 사용하십시오. 그림자를 설정하고 그림자 클래스를 사용하십시오. CSS 스타일을 사용하여 이미지를 조정하고 배치하십시오. 배경 이미지를 사용하여 배경 이미지 CSS 속성을 사용하십시오.

부트 스트랩 날짜를 보는 방법 부트 스트랩 날짜를 보는 방법 Apr 07, 2025 pm 03:03 PM

답 : 부트 스트랩의 날짜 선택기 구성 요소를 사용하여 페이지에서 날짜를 볼 수 있습니다. 단계 : 부트 스트랩 프레임 워크를 소개하십시오. HTML에서 날짜 선택기 입력 상자를 만듭니다. 부트 스트랩은 선택기에 스타일을 자동으로 추가합니다. JavaScript를 사용하여 선택한 날짜를 얻으십시오.

부트 스트랩 날짜를 확인하는 방법 부트 스트랩 날짜를 확인하는 방법 Apr 07, 2025 pm 03:06 PM

부트 스트랩의 날짜를 확인하려면 다음 단계를 따르십시오. 필요한 스크립트와 스타일을 소개하십시오. 날짜 선택기 구성 요소를 초기화합니다. 검증을 활성화하려면 데이터 BV 날짜 속성을 설정합니다. 검증 규칙 (예 : 날짜 형식, 오류 메시지 등) 구성; 부트 스트랩 검증 프레임 워크를 통합하고 양식이 제출 된 경우 날짜 입력을 자동으로 확인하십시오.

부트 스트랩에 분할 라인을 작성하는 방법 부트 스트랩에 분할 라인을 작성하는 방법 Apr 07, 2025 pm 03:12 PM

부트 스트랩 분할 라인을 만드는 두 가지 방법이 있습니다 : 태그를 사용하여 수평 분할 라인이 생성됩니다. CSS 테두리 속성을 사용하여 사용자 정의 스타일 분할 라인을 만듭니다.

부트 스트랩 내비게이션 바를 설정하는 방법 부트 스트랩 내비게이션 바를 설정하는 방법 Apr 07, 2025 pm 01:51 PM

Bootstrap은 내비게이션 막대 설정을위한 간단한 안내서를 제공합니다. 내비게이션 바 컨테이너 추가 브랜드 아이덴티티 추가 내비게이션 링크 추가 (선택 사항) 스타일 조정 스타일 (선택 사항)

See all articles