chore(deps): 升级mp-html为最新版2.5.2
This commit is contained in:
@@ -1,194 +1,259 @@
|
|||||||
## 为减小组件包的大小,默认组件包中不包含编辑、latex 公式等扩展功能,需要使用扩展功能的请参考下方的 插件扩展 栏的说明
|
# mp-html
|
||||||
|
|
||||||
## 功能介绍
|
> 一个强大的小程序富文本组件
|
||||||
- 全端支持(含 `v3、NVUE`)
|
|
||||||
- 支持丰富的标签(包括 `table`、`video`、`svg` 等)
|

|
||||||
- 支持丰富的事件效果(自动预览图片、链接处理等)
|

|
||||||
- 支持设置占位图(加载中、出错时、预览时)
|
[](https://www.npmjs.com/package/mp-html)
|
||||||
- 支持锚点跳转、长按复制等丰富功能
|

|
||||||
- 支持大部分 *html* 实体
|
[](https://coveralls.io/github/jin-yufeng/mp-html?branch=master)
|
||||||
- 丰富的插件(关键词搜索、内容编辑、`latex` 公式等)
|

|
||||||
- 效率高、容错性强且轻量化
|
[](https://standardjs.com)
|
||||||
|
|
||||||
查看 [功能介绍](https://jin-yufeng.gitee.io/mp-html/#/overview/feature) 了解更多
|
## 功能介绍
|
||||||
|
- 支持在多个主流的小程序平台和 `uni-app` 中使用
|
||||||
## 使用方法
|
- 支持丰富的标签(包括 `table`、`video`、`svg` 等)
|
||||||
- `uni_modules` 方式
|
- 支持丰富的事件效果(自动预览图片、链接处理等)
|
||||||
1. 点击右上角的 `使用 HBuilder X 导入插件` 按钮直接导入项目或点击 `下载插件 ZIP` 按钮下载插件包并解压到项目的 `uni_modules/mp-html` 目录下
|
- 支持设置占位图(加载中、出错时、预览时)
|
||||||
2. 在需要使用页面的 `(n)vue` 文件中添加
|
- 支持锚点跳转、长按复制等丰富功能
|
||||||
```html
|
- 支持大部分 *html* 实体
|
||||||
<!-- 不需要引入,可直接使用 -->
|
- 丰富的插件(关键词搜索、内容编辑、`latex` 公式等)
|
||||||
<mp-html :content="html" />
|
- 效率高、容错性强且轻量化(`≈25KB`,`9KB gzipped`)
|
||||||
```
|
|
||||||
```javascript
|
查看 [功能介绍](https://jin-yufeng.github.io/mp-html/#/overview/feature) 了解更多
|
||||||
export default {
|
|
||||||
data() {
|
## 使用方法
|
||||||
return {
|
### 原生平台
|
||||||
html: '<div>Hello World!</div>'
|
- `npm` 方式
|
||||||
}
|
1. 在项目目录下安装组件包
|
||||||
}
|
|
||||||
}
|
```bash
|
||||||
```
|
npm install mp-html
|
||||||
3. 需要更新版本时在 `HBuilder X` 中右键 `uni_modules/mp-html` 目录选择 `从插件市场更新` 即可
|
```
|
||||||
|
2. 开发者工具中勾选 `使用 npm 模块`(若没有此选项则不需要)并点击 `工具 - 构建 npm`
|
||||||
- 源码方式
|
3. 在需要使用页面的 `json` 文件中添加
|
||||||
1. 从 [github](https://github.com/jin-yufeng/mp-html/tree/master/dist/uni-app) 或 [gitee](https://gitee.com/jin-yufeng/mp-html/tree/master/dist/uni-app) 下载源码
|
|
||||||
插件市场的 **非 uni_modules 版本** 无法更新,不建议从插件市场获取
|
```json
|
||||||
2. 在需要使用页面的 `(n)vue` 文件中添加
|
{
|
||||||
```html
|
"usingComponents": {
|
||||||
<mp-html :content="html" />
|
"mp-html": "mp-html"
|
||||||
```
|
}
|
||||||
```javascript
|
}
|
||||||
import mpHtml from '@/components/mp-html/mp-html'
|
```
|
||||||
export default {
|
4. 在需要使用页面的 `wxml` 文件中添加
|
||||||
// HBuilderX 2.5.5+ 可以通过 easycom 自动引入
|
|
||||||
components: {
|
```html
|
||||||
mpHtml
|
<mp-html content="{{html}}" />
|
||||||
},
|
```
|
||||||
data() {
|
5. 在需要使用页面的 `js` 文件中添加
|
||||||
return {
|
|
||||||
html: '<div>Hello World!</div>'
|
```javascript
|
||||||
}
|
Page({
|
||||||
}
|
onLoad () {
|
||||||
}
|
this.setData({
|
||||||
```
|
html: '<div>Hello World!</div>'
|
||||||
|
})
|
||||||
- npm 方式
|
}
|
||||||
1. 在项目根目录下执行
|
})
|
||||||
```bash
|
```
|
||||||
npm install mp-html
|
- 源码方式
|
||||||
```
|
1. 将源码中对应平台的代码包(`dist/platform`)拷贝到 `components` 目录下,更名为 `mp-html`
|
||||||
2. 在需要使用页面的 `(n)vue` 文件中添加
|
2. 在需要使用页面的 `json` 文件中添加
|
||||||
```html
|
|
||||||
<mp-html :content="html" />
|
```json
|
||||||
```
|
{
|
||||||
```javascript
|
"usingComponents": {
|
||||||
import mpHtml from 'mp-html/dist/uni-app/components/mp-html/mp-html'
|
"mp-html": "/components/mp-html/index"
|
||||||
export default {
|
}
|
||||||
// 不可省略
|
}
|
||||||
components: {
|
```
|
||||||
mpHtml
|
|
||||||
},
|
后续步骤同上
|
||||||
data() {
|
|
||||||
return {
|
查看 [快速开始](https://jin-yufeng.github.io/mp-html/#/overview/quickstart) 了解更多
|
||||||
html: '<div>Hello World!</div>'
|
|
||||||
}
|
### uni-app
|
||||||
}
|
- 源码方式
|
||||||
}
|
1. 将源码中 `dist/uni-app` 内的内容拷贝到项目根目录下
|
||||||
```
|
可以直接通过 [插件市场](https://ext.dcloud.net.cn/plugin?id=805) 引入
|
||||||
3. 需要更新版本时执行以下命令即可
|
2. 在需要使用页面的 `vue` 文件中添加
|
||||||
```bash
|
|
||||||
npm update mp-html
|
```vue
|
||||||
```
|
<template>
|
||||||
|
<view>
|
||||||
使用 *cli* 方式运行的项目,通过 *npm* 方式引入时,需要在 *vue.config.js* 中配置 *transpileDependencies*,详情可见 [#330](https://github.com/jin-yufeng/mp-html/issues/330#issuecomment-913617687)
|
<mp-html :content="html" />
|
||||||
如果在 **nvue** 中使用还要将 `dist/uni-app/static` 目录下的内容拷贝到项目的 `static` 目录下,否则无法运行
|
</view>
|
||||||
|
</template>
|
||||||
查看 [快速开始](https://jin-yufeng.gitee.io/mp-html/#/overview/quickstart) 了解更多
|
<script>
|
||||||
|
import mpHtml from '@/components/mp-html/mp-html'
|
||||||
## 组件属性
|
export default {
|
||||||
|
// HBuilderX 2.5.5+ 可以通过 easycom 自动引入
|
||||||
| 属性 | 类型 | 默认值 | 说明 |
|
components: {
|
||||||
|:---:|:---:|:---:|---|
|
mpHtml
|
||||||
| container-style | String | | 容器的样式([2.1.0+](https://jin-yufeng.gitee.io/mp-html/#/changelog/changelog#v210)) |
|
},
|
||||||
| content | String | | 用于渲染的 html 字符串 |
|
data () {
|
||||||
| copy-link | Boolean | true | 是否允许外部链接被点击时自动复制 |
|
return {
|
||||||
| domain | String | | 主域名(用于链接拼接) |
|
html: '<div>Hello World!</div>'
|
||||||
| error-img | String | | 图片出错时的占位图链接 |
|
}
|
||||||
| lazy-load | Boolean | false | 是否开启图片懒加载 |
|
}
|
||||||
| loading-img | String | | 图片加载过程中的占位图链接 |
|
}
|
||||||
| pause-video | Boolean | true | 是否在播放一个视频时自动暂停其他视频 |
|
</script>
|
||||||
| preview-img | Boolean | true | 是否允许图片被点击时自动预览 |
|
```
|
||||||
| scroll-table | Boolean | false | 是否给每个表格添加一个滚动层使其能单独横向滚动 |
|
- `npm` 方式
|
||||||
| selectable | Boolean | false | 是否开启文本长按复制 |
|
1. 在项目目录下安装组件包
|
||||||
| set-title | Boolean | true | 是否将 title 标签的内容设置到页面标题 |
|
|
||||||
| show-img-menu | Boolean | true | 是否允许图片被长按时显示菜单 |
|
```bash
|
||||||
| tag-style | Object | | 设置标签的默认样式 |
|
npm install mp-html
|
||||||
| use-anchor | Boolean | false | 是否使用锚点链接 |
|
```
|
||||||
|
2. 在需要使用页面的 `vue` 文件中添加
|
||||||
查看 [属性](https://jin-yufeng.gitee.io/mp-html/#/basic/prop) 了解更多
|
|
||||||
|
```vue
|
||||||
## 组件事件
|
<template>
|
||||||
|
<view>
|
||||||
| 名称 | 触发时机 |
|
<mp-html :content="html" />
|
||||||
|:---:|---|
|
</view>
|
||||||
| load | dom 树加载完毕时 |
|
</template>
|
||||||
| ready | 图片加载完毕时 |
|
<script>
|
||||||
| error | 发生渲染错误时 |
|
import mpHtml from 'mp-html/dist/uni-app/components/mp-html/mp-html'
|
||||||
| imgtap | 图片被点击时 |
|
export default {
|
||||||
| linktap | 链接被点击时 |
|
// 不可省略
|
||||||
| play | 音视频播放时 |
|
components: {
|
||||||
|
mpHtml
|
||||||
查看 [事件](https://jin-yufeng.gitee.io/mp-html/#/basic/event) 了解更多
|
},
|
||||||
|
data () {
|
||||||
## api
|
return {
|
||||||
组件实例上提供了一些 `api` 方法可供调用
|
html: '<div>Hello World!</div>'
|
||||||
|
}
|
||||||
| 名称 | 作用 |
|
}
|
||||||
|:---:|---|
|
}
|
||||||
| in | 将锚点跳转的范围限定在一个 scroll-view 内 |
|
</script>
|
||||||
| navigateTo | 锚点跳转 |
|
```
|
||||||
| getText | 获取文本内容 |
|
|
||||||
| getRect | 获取富文本内容的位置和大小 |
|
使用 `cli` 方式运行的项目,通过 `npm` 方式引入时,需要在 `vue.config.js` 中配置 `transpileDependencies`,详情可见 [#330](https://github.com/jin-yufeng/mp-html/issues/330#issuecomment-913617687)
|
||||||
| setContent | 设置富文本内容 |
|
如果在 `nvue` 中使用还要将 `dist/uni-app/static` 目录下的内容拷贝到项目的 `static` 目录下,否则无法运行
|
||||||
| imgList | 获取所有图片的数组 |
|
|
||||||
| pauseMedia | 暂停播放音视频([2.2.2+](https://jin-yufeng.gitee.io/mp-html/#/changelog/changelog#v222)) |
|
查看 [快速开始](https://jin-yufeng.github.io/mp-html/#/overview/quickstart) 了解更多
|
||||||
| setPlaybackRate | 设置音视频播放速率([2.4.0+](https://jin-yufeng.gitee.io/mp-html/#/changelog/changelog#v240)) |
|
|
||||||
|
## 组件属性
|
||||||
查看 [api](https://jin-yufeng.gitee.io/mp-html/#/advanced/api) 了解更多
|
|
||||||
|
| 属性 | 类型 | 默认值 | 说明 |
|
||||||
## 插件扩展
|
|:---:|:---:|:---:|---|
|
||||||
除基本功能外,本组件还提供了丰富的扩展,可按照需要选用
|
| container-style | String | | 容器的样式([2.1.0+](https://jin-yufeng.github.io/mp-html/#/changelog/changelog#v210)) |
|
||||||
|
| content | String | | 用于渲染的 html 字符串 |
|
||||||
| 名称 | 作用 |
|
| copy-link | Boolean | true | 是否允许外部链接被点击时自动复制 |
|
||||||
|:---:|---|
|
| domain | String | | 主域名(用于链接拼接) |
|
||||||
| audio | 音乐播放器 |
|
| error-img | String | | 图片出错时的占位图链接 |
|
||||||
| editable | 富文本 **编辑**([示例项目](https://mp-html.oss-cn-hangzhou.aliyuncs.com/editable.zip)) |
|
| lazy-load | Boolean | false | 是否开启图片懒加载 |
|
||||||
| emoji | 解析 emoji |
|
| loading-img | String | | 图片加载过程中的占位图链接 |
|
||||||
| highlight | 代码块高亮显示 |
|
| pause-video | Boolean | true | 是否在播放一个视频时自动暂停其他视频 |
|
||||||
| markdown | 渲染 markdown |
|
| preview-img | Boolean | true | 是否允许图片被点击时自动预览 |
|
||||||
| search | 关键词搜索 |
|
| scroll-table | Boolean | false | 是否给每个表格添加一个滚动层使其能单独横向滚动 |
|
||||||
| style | 匹配 style 标签中的样式 |
|
| selectable | Boolean | false | 是否开启文本长按复制 |
|
||||||
| txv-video | 使用腾讯视频 |
|
| set-title | Boolean | true | 是否将 title 标签的内容设置到页面标题 |
|
||||||
| img-cache | 图片缓存 by [@PentaTea](https://github.com/PentaTea) |
|
| show-img-menu | Boolean | true | 是否允许图片被长按时显示菜单 |
|
||||||
| latex | 渲染 latex 公式 by [@Zeng-J](https://github.com/Zeng-J) |
|
| tag-style | Object | | 设置标签的默认样式 |
|
||||||
|
| use-anchor | Boolean | false | 是否使用锚点链接 |
|
||||||
从插件市场导入的包中 **不含有** 扩展插件,使用插件需通过微信小程序 `富文本插件` 获取或参考以下方法进行打包:
|
|
||||||
1. 获取完整组件包
|
查看 [属性](https://jin-yufeng.github.io/mp-html/#/basic/prop) 了解更多
|
||||||
```bash
|
|
||||||
npm install mp-html
|
## 组件事件
|
||||||
```
|
|
||||||
2. 编辑 `tools/config.js` 中的 `plugins` 项,选择需要的插件
|
| 名称 | 触发时机 |
|
||||||
3. 生成新的组件包
|
|:---:|---|
|
||||||
在 `node_modules/mp-html` 目录下执行
|
| load | dom 树加载完毕时 |
|
||||||
```bash
|
| ready | 图片加载完毕时 |
|
||||||
npm install
|
| error | 发生渲染错误时 |
|
||||||
npm run build:uni-app
|
| imgtap | 图片被点击时 |
|
||||||
```
|
| linktap | 链接被点击时 |
|
||||||
4. 拷贝 `dist/uni-app` 中的内容到项目根目录
|
| play | 音视频播放时([2.3.0+](https://jin-yufeng.github.io/mp-html/#/changelog/changelog#v230)) |
|
||||||
|
| pause | 音视频暂停时([2.5.2+](https://jin-yufeng.github.io/mp-html/#/changelog/changelog#v252)) |
|
||||||
查看 [插件](https://jin-yufeng.gitee.io/mp-html/#/advanced/plugin) 了解更多
|
| fullscreenchange | 视频全屏变化时([2.5.2+](https://jin-yufeng.github.io/mp-html/#/changelog/changelog#v252)) |
|
||||||
|
|
||||||
## 关于 nvue
|
查看 [事件](https://jin-yufeng.github.io/mp-html/#/basic/event) 了解更多
|
||||||
`nvue` 使用原生渲染,不支持部分 `css` 样式,为实现和 `html` 相同的效果,组件内部通过 `web-view` 进行渲染,性能上差于原生,根据 `weex` 官方建议,`web` 标签仅应用在非常规的降级场景。因此,如果通过原生的方式(如 `richtext`)能够满足需要,则不建议使用本组件,如果有较多的富文本内容,则可以直接使用 `vue` 页面
|
|
||||||
由于渲染方式与其他端不同,有以下限制:
|
## api
|
||||||
1. 不支持 `lazy-load` 属性
|
组件实例上提供了一些 `api` 方法可供调用
|
||||||
2. 视频不支持全屏播放
|
|
||||||
3. 如果在 `flex-direction: row` 的容器中使用,需要给组件设置宽度或设置 `flex: 1` 占满剩余宽度
|
| 名称 | 作用 |
|
||||||
|
|:---:|---|
|
||||||
纯 `nvue` 模式下,[此问题](https://ask.dcloud.net.cn/question/119678) 修复前,不支持通过 `uni_modules` 引入,需要本地引入(将 [dist/uni-app](https://github.com/jin-yufeng/mp-html/tree/master/dist/uni-app) 中的内容拷贝到项目根目录下)
|
| in | 将锚点跳转的范围限定在一个 scroll-view 内 |
|
||||||
|
| navigateTo | 锚点跳转 |
|
||||||
## 立即体验
|
| getText | 获取文本内容 |
|
||||||

|
| getRect | 获取富文本内容的位置和大小 |
|
||||||
|
| setContent | 设置富文本内容 |
|
||||||
## 问题反馈
|
| imgList | 获取所有图片的数组 |
|
||||||
遇到问题时,请先查阅 [常见问题](https://jin-yufeng.gitee.io/mp-html/#/question/faq) 和 [issue](https://github.com/jin-yufeng/mp-html/issues) 中是否已有相同的问题
|
| pauseMedia | 暂停播放音视频([2.2.2+](https://jin-yufeng.github.io/mp-html/#/changelog/changelog#v222)) |
|
||||||
可通过 [issue](https://github.com/jin-yufeng/mp-html/issues/new/choose) 、插件问答或发送邮件到 [mp_html@126.com](mailto:mp_html@126.com) 提问,不建议在评论区提问(不方便回复)
|
| setPlaybackRate | 设置音视频播放速率([2.4.0+](https://jin-yufeng.github.io/mp-html/#/changelog/changelog#v240)) |
|
||||||
提问请严格按照 [issue 模板](https://github.com/jin-yufeng/mp-html/issues/new/choose) ,描述清楚使用环境、`html` 内容或可复现的 `demo` 项目以及复现方式,对于 **描述不清**、**无法复现** 或重复的问题将不予回复
|
|
||||||
|
查看 [api](https://jin-yufeng.github.io/mp-html/#/advanced/api) 了解更多
|
||||||
欢迎加入 `QQ` 交流群:
|
|
||||||
群1(已满):`699734691`
|
## 插件扩展
|
||||||
群2(已满):`778239129`
|
除基本功能外,本组件还提供了丰富的扩展,可按照需要选用
|
||||||
群3:`960265313`
|
|
||||||
|
| 名称 | 作用 |
|
||||||
查看 [问题反馈](https://jin-yufeng.gitee.io/mp-html/#/question/feedback) 了解更多
|
|:---:|---|
|
||||||
|
| audio | 音乐播放器 |
|
||||||
|
| editable | 富文本编辑 |
|
||||||
|
| emoji | 解析 emoji |
|
||||||
|
| highlight | 代码块高亮显示 |
|
||||||
|
| markdown | 渲染 markdown |
|
||||||
|
| search | 关键词搜索 |
|
||||||
|
| style | 匹配 style 标签中的样式 |
|
||||||
|
| txv-video | 使用腾讯视频 |
|
||||||
|
| img-cache | 图片缓存 by [@PentaTea](https://github.com/PentaTea) |
|
||||||
|
| latex | 渲染 latex 公式 by [@Zeng-J](https://github.com/Zeng-J) |
|
||||||
|
| card | 卡片展示 by [@whoooami](https://github.com/whoooami) |
|
||||||
|
|
||||||
|
查看 [插件](https://jin-yufeng.github.io/mp-html/#/advanced/plugin) 了解更多
|
||||||
|
|
||||||
|
## 使用案例
|
||||||
|
|
||||||
|
| [官方示例](https://github.com/jin-yufeng/mp-html-demo) | 欢喜商城 | 多么生活 | 食法查 | 微慕 | 科学复习 |
|
||||||
|
|:---:|:---:|:---:|:---:|:---:|:---:|
|
||||||
|
|  |  |  |  |  |  |
|
||||||
|
|
||||||
|
| [程序员技术之旅](https://github.com/fendoudebb/z-blog-wx) | 典典博客 | 优秀笔记 | 同城共享书 | [技术源 share](https://github.com/wangsrGit119/mini-blog-halo) | 你的代码写的真棒 |
|
||||||
|
|:---:|:---:|:---:|:---:|:---:|:---:|
|
||||||
|
|  |  |  |  |  |  |
|
||||||
|
|
||||||
|
| 谛否 | 小莫唐尼 | [模版演示](https://github.com/zhihuifanqiechaodan/miniprogram-template) | AI瓦力 | 豆流便签 | 前端八股通 |
|
||||||
|
|:---:|:---:|:---:|:---:|:---:|:---:|
|
||||||
|
|  |  |  |  |  |  |
|
||||||
|
|
||||||
|
以上排名不分先后,更多可见 [使用案例收集](https://github.com/jin-yufeng/mp-html/issues/27)(欢迎添加)
|
||||||
|
|
||||||
|
## 许可与支持
|
||||||
|
- 许可
|
||||||
|
您可以免费的使用(包括商用)、复制或修改本组件 [MIT License](https://github.com/jin-yufeng/mp-html/blob/master/LICENSE)
|
||||||
|
在用于生产环境前务必经过充分测试,由插件 `bug` 带来的损失概不负责(可以自行修改源码)
|
||||||
|
|
||||||
|
- 联系
|
||||||
|
欢迎加入 `QQ` 交流群:
|
||||||
|
群1(已满):`699734691`
|
||||||
|
群2(已满):`778239129`
|
||||||
|
群3:`960265313`
|
||||||
|

|
||||||
|
|
||||||
|
- 支持
|
||||||
|

|
||||||
|
|
||||||
|
## 更新日志
|
||||||
|
- v2.5.2 (20251214)
|
||||||
|
1. `A` 增加了音视频暂停 [pause](https://jin-yufeng.github.io/mp-html/#/basic/event?id=pause) 和视频全屏 [fullscreenchange](https://jin-yufeng.github.io/mp-html/#/basic/event?id=fullscreenchange) 事件 [#495](https://github.com/jin-yufeng/mp-html/issues/495) [#595](https://github.com/jin-yufeng/mp-html/issues/595)
|
||||||
|
2. `U` 优化了 [流式输出](https://jin-yufeng.github.io/mp-html/#/overview/feature?id=stream) 效果,通过差量更新解决闪烁问题 [详细](https://github.com/jin-yufeng/mp-html/issues/657)
|
||||||
|
3. `U` `latex` 插件更新字体文件 [详细](https://github.com/jin-yufeng/mp-html/pull/647) by [@JiuyeXD](https://github.com/JiuyeXD)
|
||||||
|
4. `U` 更新 `markdown` 插件中 `marked.js` 版本 [详细](https://github.com/jin-yufeng/mp-html/issues/672)
|
||||||
|
5. `U` 微信小程序替换遗漏的废弃 `api` `getSystemInfoSync` [详细](https://github.com/jin-yufeng/mp-html/pull/653) by [@zcSkr](https://github.com/zcSkr)
|
||||||
|
6. `F` 修复了 `markdown` 插件加粗文本遇到中文符号无效的问题 [详细](https://github.com/jin-yufeng/mp-html/pull/664) by [@qp666](https://github.com/qp666)
|
||||||
|
|
||||||
|
- v2.5.1 (20250420)
|
||||||
|
1. `U` `uni-app` 包适配鸿蒙 `APP` [详细](https://github.com/jin-yufeng/mp-html/issues/615)
|
||||||
|
2. `U` 微信小程序替换废弃 `api` `getSystemInfoSync` [详细](https://github.com/jin-yufeng/mp-html/issues/613)
|
||||||
|
3. `F` 修复了微信小程序 `glass-easel` 框架下真机换行异常的问题 [详细](https://github.com/jin-yufeng/mp-html/pull/607) by [@PaperStrike](https://github.com/PaperStrike)
|
||||||
|
4. `F` 修复了 `uni-app` 包 `app` 端播放视频可能报错的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/617)
|
||||||
|
5. `F` 修复了 `latex` 插件可能出现 `xxx can be used only in display mode` 的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/632)
|
||||||
|
6. `F` 修复了 `uni-app` 包 `latex` 公式可能不显示的问题 [#599](https://github.com/jin-yufeng/mp-html/issues/599)、[#627](https://github.com/jin-yufeng/mp-html/issues/627)
|
||||||
|
|
||||||
|
从 `1.x` 的升级方法可见 [更新指南](https://jin-yufeng.github.io/mp-html/#/changelog/changelog?id=v200)
|
||||||
|
|
||||||
|
查看 [更新日志](https://jin-yufeng.github.io/mp-html/#/changelog/changelog) 了解更多
|
||||||
|
|||||||
@@ -1,498 +1,500 @@
|
|||||||
<template>
|
<template>
|
||||||
<view id="_root" :class="(selectable?'_select ':'')+'_root'" :style="containerStyle">
|
<view id="_root" :class="(selectable?'_select ':'')+'_root'" :style="containerStyle">
|
||||||
<slot v-if="!nodes[0]" />
|
<slot v-if="!nodes[0]" />
|
||||||
<!-- #ifndef APP-PLUS-NVUE -->
|
<!-- #ifndef APP-PLUS-NVUE -->
|
||||||
<node v-else :childs="nodes" :opts="[lazyLoad,loadingImg,errorImg,showImgMenu,selectable]" name="span" />
|
<node v-else :childs="nodes" :opts="[lazyLoad,loadingImg,errorImg,showImgMenu,selectable]" name="span" />
|
||||||
<!-- #endif -->
|
<!-- #endif -->
|
||||||
<!-- #ifdef APP-PLUS-NVUE -->
|
<!-- #ifdef APP-PLUS-NVUE -->
|
||||||
<web-view ref="web" src="/uni_modules/mp-html/static/app-plus/mp-html/local.html" :style="'margin-top:-2px;height:' + height + 'px'" @onPostMessage="_onMessage" />
|
<web-view ref="web" src="/static/app-plus/mp-html/local.html" :style="'margin-top:-2px;height:' + height + 'px'" @onPostMessage="_onMessage" />
|
||||||
<!-- #endif -->
|
<!-- #endif -->
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
/**
|
/**
|
||||||
* mp-html v2.5.0
|
* mp-html v2.5.2
|
||||||
* @description 富文本组件
|
* @description 富文本组件
|
||||||
* @tutorial https://github.com/jin-yufeng/mp-html
|
* @tutorial https://github.com/jin-yufeng/mp-html
|
||||||
* @property {String} container-style 容器的样式
|
* @property {String} container-style 容器的样式
|
||||||
* @property {String} content 用于渲染的 html 字符串
|
* @property {String} content 用于渲染的 html 字符串
|
||||||
* @property {Boolean} copy-link 是否允许外部链接被点击时自动复制
|
* @property {Boolean} copy-link 是否允许外部链接被点击时自动复制
|
||||||
* @property {String} domain 主域名,用于拼接链接
|
* @property {String} domain 主域名,用于拼接链接
|
||||||
* @property {String} error-img 图片出错时的占位图链接
|
* @property {String} error-img 图片出错时的占位图链接
|
||||||
* @property {Boolean} lazy-load 是否开启图片懒加载
|
* @property {Boolean} lazy-load 是否开启图片懒加载
|
||||||
* @property {string} loading-img 图片加载过程中的占位图链接
|
* @property {string} loading-img 图片加载过程中的占位图链接
|
||||||
* @property {Boolean} pause-video 是否在播放一个视频时自动暂停其他视频
|
* @property {Boolean} pause-video 是否在播放一个视频时自动暂停其他视频
|
||||||
* @property {Boolean} preview-img 是否允许图片被点击时自动预览
|
* @property {Boolean} preview-img 是否允许图片被点击时自动预览
|
||||||
* @property {Boolean} scroll-table 是否给每个表格添加一个滚动层使其能单独横向滚动
|
* @property {Boolean} scroll-table 是否给每个表格添加一个滚动层使其能单独横向滚动
|
||||||
* @property {Boolean | String} selectable 是否开启长按复制
|
* @property {Boolean | String} selectable 是否开启长按复制
|
||||||
* @property {Boolean} set-title 是否将 title 标签的内容设置到页面标题
|
* @property {Boolean} set-title 是否将 title 标签的内容设置到页面标题
|
||||||
* @property {Boolean} show-img-menu 是否允许图片被长按时显示菜单
|
* @property {Boolean} show-img-menu 是否允许图片被长按时显示菜单
|
||||||
* @property {Object} tag-style 标签的默认样式
|
* @property {Object} tag-style 标签的默认样式
|
||||||
* @property {Boolean | Number} use-anchor 是否使用锚点链接
|
* @property {Boolean | Number} use-anchor 是否使用锚点链接
|
||||||
* @event {Function} load dom 结构加载完毕时触发
|
* @event {Function} load dom 结构加载完毕时触发
|
||||||
* @event {Function} ready 所有图片加载完毕时触发
|
* @event {Function} ready 所有图片加载完毕时触发
|
||||||
* @event {Function} imgtap 图片被点击时触发
|
* @event {Function} imgtap 图片被点击时触发
|
||||||
* @event {Function} linktap 链接被点击时触发
|
* @event {Function} linktap 链接被点击时触发
|
||||||
* @event {Function} play 音视频播放时触发
|
* @event {Function} play 音视频播放时触发
|
||||||
* @event {Function} error 媒体加载出错时触发
|
* @event {Function} error 媒体加载出错时触发
|
||||||
*/
|
* @event {Function} pause 音视频暂停时触发
|
||||||
// #ifndef APP-PLUS-NVUE
|
* @event {Function} fullscreenchange 视频全屏状态变化时触发
|
||||||
import node from './node/node'
|
*/
|
||||||
// #endif
|
// #ifndef APP-PLUS-NVUE
|
||||||
import Parser from './parser'
|
import node from './node/node'
|
||||||
const plugins=[]
|
// #endif
|
||||||
// #ifdef APP-PLUS-NVUE
|
import Parser from './parser'
|
||||||
const dom = weex.requireModule('dom')
|
const plugins = []
|
||||||
// #endif
|
// #ifdef APP-PLUS-NVUE
|
||||||
export default {
|
const dom = weex.requireModule('dom')
|
||||||
name: 'mp-html',
|
// #endif
|
||||||
data () {
|
export default {
|
||||||
return {
|
name: 'mp-html',
|
||||||
nodes: [],
|
data () {
|
||||||
// #ifdef APP-PLUS-NVUE
|
return {
|
||||||
height: 3
|
nodes: [],
|
||||||
// #endif
|
// #ifdef APP-PLUS-NVUE
|
||||||
}
|
height: 3
|
||||||
},
|
// #endif
|
||||||
props: {
|
}
|
||||||
containerStyle: {
|
},
|
||||||
type: String,
|
props: {
|
||||||
default: ''
|
containerStyle: {
|
||||||
},
|
type: String,
|
||||||
content: {
|
default: ''
|
||||||
type: String,
|
},
|
||||||
default: ''
|
content: {
|
||||||
},
|
type: String,
|
||||||
copyLink: {
|
default: ''
|
||||||
type: [Boolean, String],
|
},
|
||||||
default: true
|
copyLink: {
|
||||||
},
|
type: [Boolean, String],
|
||||||
domain: String,
|
default: true
|
||||||
errorImg: {
|
},
|
||||||
type: String,
|
domain: String,
|
||||||
default: ''
|
errorImg: {
|
||||||
},
|
type: String,
|
||||||
lazyLoad: {
|
default: ''
|
||||||
type: [Boolean, String],
|
},
|
||||||
default: false
|
lazyLoad: {
|
||||||
},
|
type: [Boolean, String],
|
||||||
loadingImg: {
|
default: false
|
||||||
type: String,
|
},
|
||||||
default: ''
|
loadingImg: {
|
||||||
},
|
type: String,
|
||||||
pauseVideo: {
|
default: ''
|
||||||
type: [Boolean, String],
|
},
|
||||||
default: true
|
pauseVideo: {
|
||||||
},
|
type: [Boolean, String],
|
||||||
previewImg: {
|
default: true
|
||||||
type: [Boolean, String],
|
},
|
||||||
default: true
|
previewImg: {
|
||||||
},
|
type: [Boolean, String],
|
||||||
scrollTable: [Boolean, String],
|
default: true
|
||||||
selectable: [Boolean, String],
|
},
|
||||||
setTitle: {
|
scrollTable: [Boolean, String],
|
||||||
type: [Boolean, String],
|
selectable: [Boolean, String],
|
||||||
default: true
|
setTitle: {
|
||||||
},
|
type: [Boolean, String],
|
||||||
showImgMenu: {
|
default: true
|
||||||
type: [Boolean, String],
|
},
|
||||||
default: true
|
showImgMenu: {
|
||||||
},
|
type: [Boolean, String],
|
||||||
tagStyle: Object,
|
default: true
|
||||||
useAnchor: [Boolean, Number]
|
},
|
||||||
},
|
tagStyle: Object,
|
||||||
// #ifdef VUE3
|
useAnchor: [Boolean, Number]
|
||||||
emits: ['load', 'ready', 'imgtap', 'linktap', 'play', 'error'],
|
},
|
||||||
// #endif
|
// #ifdef VUE3
|
||||||
// #ifndef APP-PLUS-NVUE
|
emits: ['load', 'ready', 'imgtap', 'linktap', 'play', 'error'],
|
||||||
components: {
|
// #endif
|
||||||
node
|
// #ifndef APP-PLUS-NVUE
|
||||||
},
|
components: {
|
||||||
// #endif
|
node
|
||||||
watch: {
|
},
|
||||||
content (content) {
|
// #endif
|
||||||
this.setContent(content)
|
watch: {
|
||||||
}
|
content (content) {
|
||||||
},
|
this.setContent(content)
|
||||||
created () {
|
}
|
||||||
this.plugins = []
|
},
|
||||||
for (let i = plugins.length; i--;) {
|
created () {
|
||||||
this.plugins.push(new plugins[i](this))
|
this.plugins = []
|
||||||
}
|
for (let i = plugins.length; i--;) {
|
||||||
},
|
this.plugins.push(new plugins[i](this))
|
||||||
mounted () {
|
}
|
||||||
if (this.content && !this.nodes.length) {
|
},
|
||||||
this.setContent(this.content)
|
mounted () {
|
||||||
}
|
if (this.content && !this.nodes.length) {
|
||||||
},
|
this.setContent(this.content)
|
||||||
beforeDestroy () {
|
}
|
||||||
this._hook('onDetached')
|
},
|
||||||
},
|
beforeDestroy () {
|
||||||
methods: {
|
this._hook('onDetached')
|
||||||
/**
|
},
|
||||||
* @description 将锚点跳转的范围限定在一个 scroll-view 内
|
methods: {
|
||||||
* @param {Object} page scroll-view 所在页面的示例
|
/**
|
||||||
* @param {String} selector scroll-view 的选择器
|
* @description 将锚点跳转的范围限定在一个 scroll-view 内
|
||||||
* @param {String} scrollTop scroll-view scroll-top 属性绑定的变量名
|
* @param {Object} page scroll-view 所在页面的示例
|
||||||
*/
|
* @param {String} selector scroll-view 的选择器
|
||||||
in (page, selector, scrollTop) {
|
* @param {String} scrollTop scroll-view scroll-top 属性绑定的变量名
|
||||||
// #ifndef APP-PLUS-NVUE
|
*/
|
||||||
if (page && selector && scrollTop) {
|
in (page, selector, scrollTop) {
|
||||||
this._in = {
|
// #ifndef APP-PLUS-NVUE
|
||||||
page,
|
if (page && selector && scrollTop) {
|
||||||
selector,
|
this._in = {
|
||||||
scrollTop
|
page,
|
||||||
}
|
selector,
|
||||||
}
|
scrollTop
|
||||||
// #endif
|
}
|
||||||
},
|
}
|
||||||
|
// #endif
|
||||||
/**
|
},
|
||||||
* @description 锚点跳转
|
|
||||||
* @param {String} id 要跳转的锚点 id
|
/**
|
||||||
* @param {Number} offset 跳转位置的偏移量
|
* @description 锚点跳转
|
||||||
* @returns {Promise}
|
* @param {String} id 要跳转的锚点 id
|
||||||
*/
|
* @param {Number} offset 跳转位置的偏移量
|
||||||
navigateTo (id, offset) {
|
* @returns {Promise}
|
||||||
return new Promise((resolve, reject) => {
|
*/
|
||||||
if (!this.useAnchor) {
|
navigateTo (id, offset) {
|
||||||
reject(Error('Anchor is disabled'))
|
return new Promise((resolve, reject) => {
|
||||||
return
|
if (!this.useAnchor) {
|
||||||
}
|
reject(Error('Anchor is disabled'))
|
||||||
offset = offset || parseInt(this.useAnchor) || 0
|
return
|
||||||
// #ifdef APP-PLUS-NVUE
|
}
|
||||||
if (!id) {
|
offset = offset || parseInt(this.useAnchor) || 0
|
||||||
dom.scrollToElement(this.$refs.web, {
|
// #ifdef APP-PLUS-NVUE
|
||||||
offset
|
if (!id) {
|
||||||
})
|
dom.scrollToElement(this.$refs.web, {
|
||||||
resolve()
|
offset
|
||||||
} else {
|
})
|
||||||
this._navigateTo = {
|
resolve()
|
||||||
resolve,
|
} else {
|
||||||
reject,
|
this._navigateTo = {
|
||||||
offset
|
resolve,
|
||||||
}
|
reject,
|
||||||
this.$refs.web.evalJs('uni.postMessage({data:{action:"getOffset",offset:(document.getElementById(' + id + ')||{}).offsetTop}})')
|
offset
|
||||||
}
|
}
|
||||||
// #endif
|
this.$refs.web.evalJs('uni.postMessage({data:{action:"getOffset",offset:(document.getElementById(' + id + ')||{}).offsetTop}})')
|
||||||
// #ifndef APP-PLUS-NVUE
|
}
|
||||||
let deep = ' '
|
// #endif
|
||||||
// #ifdef MP-WEIXIN || MP-QQ || MP-TOUTIAO
|
// #ifndef APP-PLUS-NVUE
|
||||||
deep = '>>>'
|
let deep = ' '
|
||||||
// #endif
|
// #ifdef MP-WEIXIN || MP-QQ || MP-TOUTIAO
|
||||||
const selector = uni.createSelectorQuery()
|
deep = '>>>'
|
||||||
// #ifndef MP-ALIPAY
|
// #endif
|
||||||
.in(this._in ? this._in.page : this)
|
const selector = uni.createSelectorQuery()
|
||||||
// #endif
|
// #ifndef MP-ALIPAY
|
||||||
.select((this._in ? this._in.selector : '._root') + (id ? `${deep}#${id}` : '')).boundingClientRect()
|
.in(this._in ? this._in.page : this)
|
||||||
if (this._in) {
|
// #endif
|
||||||
selector.select(this._in.selector).scrollOffset()
|
.select((this._in ? this._in.selector : '._root') + (id ? `${deep}#${id}` : '')).boundingClientRect()
|
||||||
.select(this._in.selector).boundingClientRect()
|
if (this._in) {
|
||||||
} else {
|
selector.select(this._in.selector).scrollOffset()
|
||||||
// 获取 scroll-view 的位置和滚动距离
|
.select(this._in.selector).boundingClientRect()
|
||||||
selector.selectViewport().scrollOffset() // 获取窗口的滚动距离
|
} else {
|
||||||
}
|
// 获取 scroll-view 的位置和滚动距离
|
||||||
selector.exec(res => {
|
selector.selectViewport().scrollOffset() // 获取窗口的滚动距离
|
||||||
if (!res[0]) {
|
}
|
||||||
reject(Error('Label not found'))
|
selector.exec(res => {
|
||||||
return
|
if (!res[0]) {
|
||||||
}
|
reject(Error('Label not found'))
|
||||||
const scrollTop = res[1].scrollTop + res[0].top - (res[2] ? res[2].top : 0) + offset
|
return
|
||||||
if (this._in) {
|
}
|
||||||
// scroll-view 跳转
|
const scrollTop = res[1].scrollTop + res[0].top - (res[2] ? res[2].top : 0) + offset
|
||||||
this._in.page[this._in.scrollTop] = scrollTop
|
if (this._in) {
|
||||||
} else {
|
// scroll-view 跳转
|
||||||
// 页面跳转
|
this._in.page[this._in.scrollTop] = scrollTop
|
||||||
uni.pageScrollTo({
|
} else {
|
||||||
scrollTop,
|
// 页面跳转
|
||||||
duration: 300
|
uni.pageScrollTo({
|
||||||
})
|
scrollTop,
|
||||||
}
|
duration: 300
|
||||||
resolve()
|
})
|
||||||
})
|
}
|
||||||
// #endif
|
resolve()
|
||||||
})
|
})
|
||||||
},
|
// #endif
|
||||||
|
})
|
||||||
/**
|
},
|
||||||
* @description 获取文本内容
|
|
||||||
* @return {String}
|
/**
|
||||||
*/
|
* @description 获取文本内容
|
||||||
getText (nodes) {
|
* @return {String}
|
||||||
let text = '';
|
*/
|
||||||
(function traversal (nodes) {
|
getText (nodes) {
|
||||||
for (let i = 0; i < nodes.length; i++) {
|
let text = '';
|
||||||
const node = nodes[i]
|
(function traversal (nodes) {
|
||||||
if (node.type === 'text') {
|
for (let i = 0; i < nodes.length; i++) {
|
||||||
text += node.text.replace(/&/g, '&')
|
const node = nodes[i]
|
||||||
} else if (node.name === 'br') {
|
if (node.type === 'text') {
|
||||||
text += '\n'
|
text += node.text.replace(/&/g, '&')
|
||||||
} else {
|
} else if (node.name === 'br') {
|
||||||
// 块级标签前后加换行
|
text += '\n'
|
||||||
const isBlock = node.name === 'p' || node.name === 'div' || node.name === 'tr' || node.name === 'li' || (node.name[0] === 'h' && node.name[1] > '0' && node.name[1] < '7')
|
} else {
|
||||||
if (isBlock && text && text[text.length - 1] !== '\n') {
|
// 块级标签前后加换行
|
||||||
text += '\n'
|
const isBlock = node.name === 'p' || node.name === 'div' || node.name === 'tr' || node.name === 'li' || (node.name[0] === 'h' && node.name[1] > '0' && node.name[1] < '7')
|
||||||
}
|
if (isBlock && text && text[text.length - 1] !== '\n') {
|
||||||
// 递归获取子节点的文本
|
text += '\n'
|
||||||
if (node.children) {
|
}
|
||||||
traversal(node.children)
|
// 递归获取子节点的文本
|
||||||
}
|
if (node.children) {
|
||||||
if (isBlock && text[text.length - 1] !== '\n') {
|
traversal(node.children)
|
||||||
text += '\n'
|
}
|
||||||
} else if (node.name === 'td' || node.name === 'th') {
|
if (isBlock && text[text.length - 1] !== '\n') {
|
||||||
text += '\t'
|
text += '\n'
|
||||||
}
|
} else if (node.name === 'td' || node.name === 'th') {
|
||||||
}
|
text += '\t'
|
||||||
}
|
}
|
||||||
})(nodes || this.nodes)
|
}
|
||||||
return text
|
}
|
||||||
},
|
})(nodes || this.nodes)
|
||||||
|
return text
|
||||||
/**
|
},
|
||||||
* @description 获取内容大小和位置
|
|
||||||
* @return {Promise}
|
/**
|
||||||
*/
|
* @description 获取内容大小和位置
|
||||||
getRect () {
|
* @return {Promise}
|
||||||
return new Promise((resolve, reject) => {
|
*/
|
||||||
uni.createSelectorQuery()
|
getRect () {
|
||||||
// #ifndef MP-ALIPAY
|
return new Promise((resolve, reject) => {
|
||||||
.in(this)
|
uni.createSelectorQuery()
|
||||||
// #endif
|
// #ifndef MP-ALIPAY
|
||||||
.select('#_root').boundingClientRect().exec(res => res[0] ? resolve(res[0]) : reject(Error('Root label not found')))
|
.in(this)
|
||||||
})
|
// #endif
|
||||||
},
|
.select('#_root').boundingClientRect().exec(res => res[0] ? resolve(res[0]) : reject(Error('Root label not found')))
|
||||||
|
})
|
||||||
/**
|
},
|
||||||
* @description 暂停播放媒体
|
|
||||||
*/
|
/**
|
||||||
pauseMedia () {
|
* @description 暂停播放媒体
|
||||||
for (let i = (this._videos || []).length; i--;) {
|
*/
|
||||||
this._videos[i].pause()
|
pauseMedia () {
|
||||||
}
|
for (let i = (this._videos || []).length; i--;) {
|
||||||
// #ifdef APP-PLUS
|
this._videos[i].pause()
|
||||||
const command = 'for(var e=document.getElementsByTagName("video"),i=e.length;i--;)e[i].pause()'
|
}
|
||||||
// #ifndef APP-PLUS-NVUE
|
// #ifdef APP-PLUS
|
||||||
let page = this.$parent
|
const command = 'for(var e=document.getElementsByTagName("video"),i=e.length;i--;)e[i].pause()'
|
||||||
while (!page.$scope) page = page.$parent
|
// #ifndef APP-PLUS-NVUE
|
||||||
page.$scope.$getAppWebview().evalJS(command)
|
let page = this.$parent
|
||||||
// #endif
|
while (!page.$scope) page = page.$parent
|
||||||
// #ifdef APP-PLUS-NVUE
|
page.$scope.$getAppWebview().evalJS(command)
|
||||||
this.$refs.web.evalJs(command)
|
// #endif
|
||||||
// #endif
|
// #ifdef APP-PLUS-NVUE
|
||||||
// #endif
|
this.$refs.web.evalJs(command)
|
||||||
},
|
// #endif
|
||||||
|
// #endif
|
||||||
/**
|
},
|
||||||
* @description 设置媒体播放速率
|
|
||||||
* @param {Number} rate 播放速率
|
/**
|
||||||
*/
|
* @description 设置媒体播放速率
|
||||||
setPlaybackRate (rate) {
|
* @param {Number} rate 播放速率
|
||||||
this.playbackRate = rate
|
*/
|
||||||
for (let i = (this._videos || []).length; i--;) {
|
setPlaybackRate (rate) {
|
||||||
this._videos[i].playbackRate(rate)
|
this.playbackRate = rate
|
||||||
}
|
for (let i = (this._videos || []).length; i--;) {
|
||||||
// #ifdef APP-PLUS
|
this._videos[i].playbackRate(rate)
|
||||||
const command = 'for(var e=document.getElementsByTagName("video"),i=e.length;i--;)e[i].playbackRate=' + rate
|
}
|
||||||
// #ifndef APP-PLUS-NVUE
|
// #ifdef APP-PLUS
|
||||||
let page = this.$parent
|
const command = 'for(var e=document.getElementsByTagName("video"),i=e.length;i--;)e[i].playbackRate=' + rate
|
||||||
while (!page.$scope) page = page.$parent
|
// #ifndef APP-PLUS-NVUE
|
||||||
page.$scope.$getAppWebview().evalJS(command)
|
let page = this.$parent
|
||||||
// #endif
|
while (!page.$scope) page = page.$parent
|
||||||
// #ifdef APP-PLUS-NVUE
|
page.$scope.$getAppWebview().evalJS(command)
|
||||||
this.$refs.web.evalJs(command)
|
// #endif
|
||||||
// #endif
|
// #ifdef APP-PLUS-NVUE
|
||||||
// #endif
|
this.$refs.web.evalJs(command)
|
||||||
},
|
// #endif
|
||||||
|
// #endif
|
||||||
/**
|
},
|
||||||
* @description 设置内容
|
|
||||||
* @param {String} content html 内容
|
/**
|
||||||
* @param {Boolean} append 是否在尾部追加
|
* @description 设置内容
|
||||||
*/
|
* @param {String} content html 内容
|
||||||
setContent (content, append) {
|
* @param {Boolean} append 是否在尾部追加
|
||||||
if (!append || !this.imgList) {
|
*/
|
||||||
this.imgList = []
|
setContent (content, append) {
|
||||||
}
|
if (!append || !this.imgList) {
|
||||||
const nodes = new Parser(this).parse(content)
|
this.imgList = []
|
||||||
// #ifdef APP-PLUS-NVUE
|
}
|
||||||
if (this._ready) {
|
const nodes = new Parser(this).parse(content)
|
||||||
this._set(nodes, append)
|
// #ifdef APP-PLUS-NVUE
|
||||||
}
|
if (this._ready) {
|
||||||
// #endif
|
this._set(nodes, append)
|
||||||
this.$set(this, 'nodes', append ? (this.nodes || []).concat(nodes) : nodes)
|
}
|
||||||
|
// #endif
|
||||||
// #ifndef APP-PLUS-NVUE
|
this.$set(this, 'nodes', append ? (this.nodes || []).concat(nodes) : nodes)
|
||||||
this._videos = []
|
|
||||||
this.$nextTick(() => {
|
// #ifndef APP-PLUS-NVUE
|
||||||
this._hook('onLoad')
|
this._videos = []
|
||||||
this.$emit('load')
|
this.$nextTick(() => {
|
||||||
})
|
this._hook('onLoad')
|
||||||
|
this.$emit('load')
|
||||||
if (this.lazyLoad || this.imgList._unloadimgs < this.imgList.length / 2) {
|
})
|
||||||
// 设置懒加载,每 350ms 获取高度,不变则认为加载完毕
|
|
||||||
let height = 0
|
if (this.lazyLoad || this.imgList._unloadimgs < this.imgList.length / 2) {
|
||||||
const callback = rect => {
|
// 设置懒加载,每 350ms 获取高度,不变则认为加载完毕
|
||||||
if (!rect || !rect.height) rect = {}
|
let height = 0
|
||||||
// 350ms 总高度无变化就触发 ready 事件
|
const callback = rect => {
|
||||||
if (rect.height === height) {
|
if (!rect || !rect.height) rect = {}
|
||||||
this.$emit('ready', rect)
|
// 350ms 总高度无变化就触发 ready 事件
|
||||||
} else {
|
if (rect.height === height) {
|
||||||
height = rect.height
|
this.$emit('ready', rect)
|
||||||
setTimeout(() => {
|
} else {
|
||||||
this.getRect().then(callback).catch(callback)
|
height = rect.height
|
||||||
}, 350)
|
setTimeout(() => {
|
||||||
}
|
this.getRect().then(callback).catch(callback)
|
||||||
}
|
}, 350)
|
||||||
this.getRect().then(callback).catch(callback)
|
}
|
||||||
} else {
|
}
|
||||||
// 未设置懒加载,等待所有图片加载完毕
|
this.getRect().then(callback).catch(callback)
|
||||||
if (!this.imgList._unloadimgs) {
|
} else {
|
||||||
this.getRect().then(rect => {
|
// 未设置懒加载,等待所有图片加载完毕
|
||||||
this.$emit('ready', rect)
|
if (!this.imgList._unloadimgs) {
|
||||||
}).catch(() => {
|
this.getRect().then(rect => {
|
||||||
this.$emit('ready', {})
|
this.$emit('ready', rect)
|
||||||
})
|
}).catch(() => {
|
||||||
}
|
this.$emit('ready', {})
|
||||||
}
|
})
|
||||||
// #endif
|
}
|
||||||
},
|
}
|
||||||
|
// #endif
|
||||||
/**
|
},
|
||||||
* @description 调用插件钩子函数
|
|
||||||
*/
|
/**
|
||||||
_hook (name) {
|
* @description 调用插件钩子函数
|
||||||
for (let i = plugins.length; i--;) {
|
*/
|
||||||
if (this.plugins[i][name]) {
|
_hook (name) {
|
||||||
this.plugins[i][name]()
|
for (let i = plugins.length; i--;) {
|
||||||
}
|
if (this.plugins[i][name]) {
|
||||||
}
|
this.plugins[i][name]()
|
||||||
},
|
}
|
||||||
|
}
|
||||||
// #ifdef APP-PLUS-NVUE
|
},
|
||||||
/**
|
|
||||||
* @description 设置内容
|
// #ifdef APP-PLUS-NVUE
|
||||||
*/
|
/**
|
||||||
_set (nodes, append) {
|
* @description 设置内容
|
||||||
this.$refs.web.evalJs('setContent(' + JSON.stringify(nodes).replace(/%22/g, '') + ',' + JSON.stringify([this.containerStyle.replace(/(?:margin|padding)[^;]+/g, ''), this.errorImg, this.loadingImg, this.pauseVideo, this.scrollTable, this.selectable]) + ',' + append + ')')
|
*/
|
||||||
},
|
_set (nodes, append) {
|
||||||
|
this.$refs.web.evalJs('setContent(' + JSON.stringify(nodes).replace(/%22/g, '') + ',' + JSON.stringify([this.containerStyle.replace(/(?:margin|padding)[^;]+/g, ''), this.errorImg, this.loadingImg, this.pauseVideo, this.scrollTable, this.selectable]) + ',' + append + ')')
|
||||||
/**
|
},
|
||||||
* @description 接收到 web-view 消息
|
|
||||||
*/
|
/**
|
||||||
_onMessage (e) {
|
* @description 接收到 web-view 消息
|
||||||
const message = e.detail.data[0]
|
*/
|
||||||
switch (message.action) {
|
_onMessage (e) {
|
||||||
// web-view 初始化完毕
|
const message = e.detail.data[0]
|
||||||
case 'onJSBridgeReady':
|
switch (message.action) {
|
||||||
this._ready = true
|
// web-view 初始化完毕
|
||||||
if (this.nodes) {
|
case 'onJSBridgeReady':
|
||||||
this._set(this.nodes)
|
this._ready = true
|
||||||
}
|
if (this.nodes) {
|
||||||
break
|
this._set(this.nodes)
|
||||||
// 内容 dom 加载完毕
|
}
|
||||||
case 'onLoad':
|
break
|
||||||
this.height = message.height
|
// 内容 dom 加载完毕
|
||||||
this._hook('onLoad')
|
case 'onLoad':
|
||||||
this.$emit('load')
|
this.height = message.height
|
||||||
break
|
this._hook('onLoad')
|
||||||
// 所有图片加载完毕
|
this.$emit('load')
|
||||||
case 'onReady':
|
break
|
||||||
this.getRect().then(res => {
|
// 所有图片加载完毕
|
||||||
this.$emit('ready', res)
|
case 'onReady':
|
||||||
}).catch(() => {
|
this.getRect().then(res => {
|
||||||
this.$emit('ready', {})
|
this.$emit('ready', res)
|
||||||
})
|
}).catch(() => {
|
||||||
break
|
this.$emit('ready', {})
|
||||||
// 总高度发生变化
|
})
|
||||||
case 'onHeightChange':
|
break
|
||||||
this.height = message.height
|
// 总高度发生变化
|
||||||
break
|
case 'onHeightChange':
|
||||||
// 图片点击
|
this.height = message.height
|
||||||
case 'onImgTap':
|
break
|
||||||
this.$emit('imgtap', message.attrs)
|
// 图片点击
|
||||||
if (this.previewImg) {
|
case 'onImgTap':
|
||||||
uni.previewImage({
|
this.$emit('imgtap', message.attrs)
|
||||||
current: parseInt(message.attrs.i),
|
if (this.previewImg) {
|
||||||
urls: this.imgList
|
uni.previewImage({
|
||||||
})
|
current: parseInt(message.attrs.i),
|
||||||
}
|
urls: this.imgList
|
||||||
break
|
})
|
||||||
// 链接点击
|
}
|
||||||
case 'onLinkTap': {
|
break
|
||||||
const href = message.attrs.href
|
// 链接点击
|
||||||
this.$emit('linktap', message.attrs)
|
case 'onLinkTap': {
|
||||||
if (href) {
|
const href = message.attrs.href
|
||||||
// 锚点跳转
|
this.$emit('linktap', message.attrs)
|
||||||
if (href[0] === '#') {
|
if (href) {
|
||||||
if (this.useAnchor) {
|
// 锚点跳转
|
||||||
dom.scrollToElement(this.$refs.web, {
|
if (href[0] === '#') {
|
||||||
offset: message.offset
|
if (this.useAnchor) {
|
||||||
})
|
dom.scrollToElement(this.$refs.web, {
|
||||||
}
|
offset: message.offset
|
||||||
} else if (href.includes('://')) {
|
})
|
||||||
// 打开外链
|
}
|
||||||
if (this.copyLink) {
|
} else if (href.includes('://')) {
|
||||||
plus.runtime.openWeb(href)
|
// 打开外链
|
||||||
}
|
if (this.copyLink) {
|
||||||
} else {
|
plus.runtime.openWeb(href)
|
||||||
uni.navigateTo({
|
}
|
||||||
url: href,
|
} else {
|
||||||
fail () {
|
uni.navigateTo({
|
||||||
uni.switchTab({
|
url: href,
|
||||||
url: href
|
fail () {
|
||||||
})
|
uni.switchTab({
|
||||||
}
|
url: href
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
break
|
}
|
||||||
}
|
}
|
||||||
case 'onPlay':
|
break
|
||||||
this.$emit('play')
|
}
|
||||||
break
|
case 'onPlay':
|
||||||
// 获取到锚点的偏移量
|
this.$emit('play')
|
||||||
case 'getOffset':
|
break
|
||||||
if (typeof message.offset === 'number') {
|
// 获取到锚点的偏移量
|
||||||
dom.scrollToElement(this.$refs.web, {
|
case 'getOffset':
|
||||||
offset: message.offset + this._navigateTo.offset
|
if (typeof message.offset === 'number') {
|
||||||
})
|
dom.scrollToElement(this.$refs.web, {
|
||||||
this._navigateTo.resolve()
|
offset: message.offset + this._navigateTo.offset
|
||||||
} else {
|
})
|
||||||
this._navigateTo.reject(Error('Label not found'))
|
this._navigateTo.resolve()
|
||||||
}
|
} else {
|
||||||
break
|
this._navigateTo.reject(Error('Label not found'))
|
||||||
// 点击
|
}
|
||||||
case 'onClick':
|
break
|
||||||
this.$emit('tap')
|
// 点击
|
||||||
this.$emit('click')
|
case 'onClick':
|
||||||
break
|
this.$emit('tap')
|
||||||
// 出错
|
this.$emit('click')
|
||||||
case 'onError':
|
break
|
||||||
this.$emit('error', {
|
// 出错
|
||||||
source: message.source,
|
case 'onError':
|
||||||
attrs: message.attrs
|
this.$emit('error', {
|
||||||
})
|
source: message.source,
|
||||||
}
|
attrs: message.attrs
|
||||||
}
|
})
|
||||||
// #endif
|
}
|
||||||
}
|
}
|
||||||
}
|
// #endif
|
||||||
</script>
|
}
|
||||||
|
}
|
||||||
<style>
|
</script>
|
||||||
/* #ifndef APP-PLUS-NVUE */
|
|
||||||
/* 根节点样式 */
|
<style>
|
||||||
._root {
|
/* #ifndef APP-PLUS-NVUE */
|
||||||
padding: 1px 0;
|
/* 根节点样式 */
|
||||||
overflow-x: auto;
|
._root {
|
||||||
overflow-y: hidden;
|
padding: 1px 0;
|
||||||
-webkit-overflow-scrolling: touch;
|
overflow-x: auto;
|
||||||
}
|
overflow-y: hidden;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
/* 长按复制 */
|
}
|
||||||
._select {
|
|
||||||
user-select: text;
|
/* 长按复制 */
|
||||||
}
|
._select {
|
||||||
/* #endif */
|
user-select: text;
|
||||||
</style>
|
}
|
||||||
|
/* #endif */
|
||||||
|
</style>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,76 +1,74 @@
|
|||||||
{
|
{
|
||||||
"id": "mp-html",
|
"name": "mp-html",
|
||||||
"displayName": "mp-html 富文本组件【全端支持,支持编辑、latex等扩展】",
|
"version": "2.5.2",
|
||||||
"version": "v2.5.0",
|
"description": "小程序富文本组件",
|
||||||
"description": "一个强大的富文本组件,高效轻量,功能丰富",
|
"miniprogram": "dist/mp-weixin",
|
||||||
"keywords": [
|
"repository": "https://github.com/jin-yufeng/mp-html",
|
||||||
"富文本",
|
"author": "Jin Yufeng",
|
||||||
"编辑器",
|
"license": "MIT",
|
||||||
"html",
|
"keywords": [
|
||||||
"rich-text",
|
"miniprogram",
|
||||||
"editor"
|
"rich-text",
|
||||||
],
|
"html"
|
||||||
"repository": "https://github.com/jin-yufeng/mp-html",
|
],
|
||||||
"dcloudext": {
|
"standard": {
|
||||||
"sale": {
|
"globals": ["App", "Page", "Component", "wx", "requirePlugin", "uni", "plus", "weex"],
|
||||||
"regular": {
|
"envs": ["jest", "browser"]
|
||||||
"price": "0.00"
|
},
|
||||||
},
|
"jest": {
|
||||||
"sourcecode": {
|
"testEnvironment": "jsdom",
|
||||||
"price": "0.00"
|
"collectCoverageFrom": [
|
||||||
}
|
"dev/mp-weixin/components/mp-html/**/*.js"
|
||||||
},
|
]
|
||||||
"contact": {
|
},
|
||||||
"qq": ""
|
"scripts": {
|
||||||
},
|
"lint": "node lint.js",
|
||||||
"declaration": {
|
"lintcss": "npx stylelint src/**/*.wxss",
|
||||||
"ads": "无",
|
"build:weixin": "gulp build --mp-weixin",
|
||||||
"data": "无",
|
"build:qq": "gulp build --mp-qq",
|
||||||
"permissions": "无"
|
"build:baidu": "gulp build --mp-baidu",
|
||||||
},
|
"build:alipay": "gulp build --mp-alipay",
|
||||||
"npmurl": "https://www.npmjs.com/package/mp-html",
|
"build:toutiao": "gulp build --mp-toutiao",
|
||||||
"type": "component-vue"
|
"build:uni-app": "gulp build --uni-app",
|
||||||
},
|
"build": "gulp build --mp-weixin & gulp build --mp-qq & gulp build --mp-baidu & gulp build --mp-alipay & gulp build --mp-toutiao & gulp build --uni-app",
|
||||||
"uni_modules": {
|
"watch:weixin": "gulp watch --mp-weixin --dev",
|
||||||
"platforms": {
|
"watch:qq": "gulp watch --mp-qq --dev",
|
||||||
"cloud": {
|
"watch:baidu": "gulp watch --mp-baidu --dev",
|
||||||
"tcb": "y",
|
"watch:alipay": "gulp watch --mp-alipay --dev",
|
||||||
"aliyun": "y"
|
"watch:toutiao": "gulp watch --mp-toutiao --dev",
|
||||||
},
|
"watch:uni-app": "gulp watch --uni-app --dev",
|
||||||
"client": {
|
"dev:weixin": "gulp dev --mp-weixin --dev",
|
||||||
"App": {
|
"dev:qq": "gulp dev --mp-qq --dev",
|
||||||
"app-vue": "y",
|
"dev:baidu": "gulp dev --mp-baidu --dev",
|
||||||
"app-nvue": "y"
|
"dev:alipay": "gulp dev --mp-alipay --dev",
|
||||||
},
|
"dev:toutiao": "gulp dev --mp-toutiao --dev",
|
||||||
"H5-mobile": {
|
"dev:uni-app": "gulp dev --uni-app --dev",
|
||||||
"Safari": "y",
|
"test": "gulp dev --mp-weixin --dev && npx jest",
|
||||||
"Android Browser": "y",
|
"coverage": "gulp dev --mp-weixin --dev && npx jest --coverage",
|
||||||
"微信浏览器(Android)": "y",
|
"coveralls": "npx coveralls < coverage/lcov.info",
|
||||||
"QQ浏览器(Android)": "y"
|
"clean": "gulp clean --all",
|
||||||
},
|
"clean:dev": "gulp clean --all --dev"
|
||||||
"H5-pc": {
|
},
|
||||||
"Chrome": "y",
|
"devDependencies": {
|
||||||
"IE": "u",
|
"@babel/preset-env": "^7.12.1",
|
||||||
"Edge": "y",
|
"coveralls": "^3.1.0",
|
||||||
"Firefox": "y",
|
"gulp": "^4.0.0",
|
||||||
"Safari": "y"
|
"gulp-babel": "^8.0.0",
|
||||||
},
|
"gulp-clean": "^0.4.0",
|
||||||
"小程序": {
|
"gulp-clean-css": "^4.3.0",
|
||||||
"微信": "y",
|
"gulp-htmlmin": "^5.0.1",
|
||||||
"阿里": "y",
|
"gulp-if": "^3.0.0",
|
||||||
"百度": "y",
|
"gulp-plumber": "^1.2.1",
|
||||||
"字节跳动": "y",
|
"gulp-size": "^3.0.0",
|
||||||
"QQ": "y"
|
"gulp-uglify": "^2.1.2",
|
||||||
},
|
"jest": "^26.6.1",
|
||||||
"快应用": {
|
"miniprogram-simulate": "^1.2.7",
|
||||||
"华为": "y",
|
"standard": "^16.0.3",
|
||||||
"联盟": "y"
|
"stylelint": "^13.7.2",
|
||||||
},
|
"stylelint-config-recess-order": "^2.3.0",
|
||||||
"Vue": {
|
"stylelint-config-standard": "^20.0.0",
|
||||||
"vue2": "y",
|
"through2": "^4.0.2",
|
||||||
"vue3": "y"
|
"uglify-js": "^2.8.29"
|
||||||
}
|
},
|
||||||
}
|
"dependencies": {}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1 +1,254 @@
|
|||||||
"use strict";function t(t){for(var e=Object.create(null),n=t.attributes.length;n--;)e[t.attributes[n].name]=t.attributes[n].value;return e}function e(){a[1]&&(this.src=a[1],this.onerror=null),this.onclick=null,this.ontouchstart=null,uni.postMessage({data:{action:"onError",source:"img",attrs:t(this)}})}function n(){window.unloadimgs-=1,0===window.unloadimgs&&uni.postMessage({data:{action:"onReady"}})}function o(r,s,c){for(var d=0;d<r.length;d++)!function(d){var u=r[d],l=void 0;if(u.type&&"node"!==u.type)l=document.createTextNode(u.text.replace(/&/g,"&"));else{var g=u.name;"svg"===g&&(c="http://www.w3.org/2000/svg"),"html"!==g&&"body"!==g||(g="div"),l=c?document.createElementNS(c,g):document.createElement(g);for(var p in u.attrs)l.setAttribute(p,u.attrs[p]);if(u.children&&o(u.children,l,c),"img"===g){if(window.unloadimgs+=1,l.onload=n,l.onerror=n,!l.src&&l.getAttribute("data-src")&&(l.src=l.getAttribute("data-src")),u.attrs.ignore||(l.onclick=function(e){e.stopPropagation(),uni.postMessage({data:{action:"onImgTap",attrs:t(this)}})}),a[2]){var h=new Image;h.src=l.src,l.src=a[2],h.onload=function(){l.src=this.src},h.onerror=function(){l.onerror()}}l.onerror=e}else if("a"===g)l.addEventListener("click",function(e){e.stopPropagation(),e.preventDefault();var n,o=this.getAttribute("href");o&&"#"===o[0]&&(n=(document.getElementById(o.substr(1))||{}).offsetTop),uni.postMessage({data:{action:"onLinkTap",attrs:t(this),offset:n}})},!0);else if("video"===g||"audio"===g)i.push(l),u.attrs.autoplay||u.attrs.controls||l.setAttribute("controls","true"),l.onplay=function(){if(uni.postMessage({data:{action:"onPlay"}}),a[3])for(var t=0;t<i.length;t++)i[t]!==this&&i[t].pause()},l.onerror=function(){uni.postMessage({data:{action:"onError",source:g,attrs:t(this)}})};else if("table"===g&&a[4]&&!l.style.cssText.includes("inline")){var f=document.createElement("div");f.style.overflow="auto",f.appendChild(l),l=f}else"svg"===g&&(c=void 0)}s.appendChild(l)}(d)}document.addEventListener("UniAppJSBridgeReady",function(){document.body.onclick=function(){return uni.postMessage({data:{action:"onClick"}})},uni.postMessage({data:{action:"onJSBridgeReady"}})});var a,i=[];window.setContent=function(t,e,n){var r=document.getElementById("content");e[0]&&(document.body.style.cssText=e[0]),e[5]||(r.style.userSelect="none"),n||(r.innerHTML="",i=[]),a=e,window.unloadimgs=0;var s=document.createDocumentFragment();o(t,s),r.appendChild(s);var c=r.scrollHeight;uni.postMessage({data:{action:"onLoad",height:c}}),window.unloadimgs||uni.postMessage({data:{action:"onReady",height:c}}),clearInterval(window.timer),window.timer=setInterval(function(){r.scrollHeight!==c&&(c=r.scrollHeight,uni.postMessage({data:{action:"onHeightChange",height:c}}))},350)},window.onunload=function(){clearInterval(window.timer)};
|
// 等待初始化完毕
|
||||||
|
document.addEventListener('UniAppJSBridgeReady', () => {
|
||||||
|
document.body.onclick = () =>
|
||||||
|
uni.postMessage({
|
||||||
|
data: {
|
||||||
|
action: 'onClick'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
uni.postMessage({
|
||||||
|
data: {
|
||||||
|
action: 'onJSBridgeReady'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
let options
|
||||||
|
let medias = []
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 获取标签的所有属性
|
||||||
|
* @param {Element} ele
|
||||||
|
*/
|
||||||
|
function getAttrs (ele) {
|
||||||
|
const attrs = Object.create(null)
|
||||||
|
for (let i = ele.attributes.length; i--;) {
|
||||||
|
attrs[ele.attributes[i].name] = ele.attributes[i].value
|
||||||
|
}
|
||||||
|
return attrs
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 图片加载出错
|
||||||
|
*/
|
||||||
|
function onImgError () {
|
||||||
|
if (options[1]) {
|
||||||
|
this.src = options[1]
|
||||||
|
this.onerror = null
|
||||||
|
}
|
||||||
|
// 取消监听点击
|
||||||
|
this.onclick = null
|
||||||
|
this.ontouchstart = null
|
||||||
|
uni.postMessage({
|
||||||
|
data: {
|
||||||
|
action: 'onError',
|
||||||
|
source: 'img',
|
||||||
|
attrs: getAttrs(this)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 检查是否所有图片加载完毕
|
||||||
|
*/
|
||||||
|
function checkReady () {
|
||||||
|
window.unloadimgs -= 1
|
||||||
|
if (window.unloadimgs === 0) {
|
||||||
|
// 所有图片加载完毕
|
||||||
|
uni.postMessage({
|
||||||
|
data: {
|
||||||
|
action: 'onReady'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 创建 dom 结构
|
||||||
|
* @param {object[]} nodes 节点数组
|
||||||
|
* @param {Element} parent 父节点
|
||||||
|
* @param {string} namespace 命名空间
|
||||||
|
*/
|
||||||
|
function createDom (nodes, parent, namespace) {
|
||||||
|
for (let i = 0; i < nodes.length; i++) {
|
||||||
|
const node = nodes[i]
|
||||||
|
let ele
|
||||||
|
if (!node.type || node.type === 'node') {
|
||||||
|
let name = node.name
|
||||||
|
// svg 需要设置 namespace
|
||||||
|
if (name === 'svg') {
|
||||||
|
namespace = 'http://www.w3.org/2000/svg'
|
||||||
|
}
|
||||||
|
if (name === 'html' || name === 'body') {
|
||||||
|
name = 'div'
|
||||||
|
}
|
||||||
|
// 创建标签
|
||||||
|
if (!namespace) {
|
||||||
|
ele = document.createElement(name)
|
||||||
|
} else {
|
||||||
|
ele = document.createElementNS(namespace, name)
|
||||||
|
}
|
||||||
|
// 设置属性
|
||||||
|
for (const item in node.attrs) {
|
||||||
|
ele.setAttribute(item, node.attrs[item])
|
||||||
|
}
|
||||||
|
// 递归创建子节点
|
||||||
|
if (node.children) {
|
||||||
|
createDom(node.children, ele, namespace)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理图片
|
||||||
|
if (name === 'img') {
|
||||||
|
window.unloadimgs += 1
|
||||||
|
ele.onload = checkReady
|
||||||
|
ele.onerror = checkReady
|
||||||
|
if (!ele.src && ele.getAttribute('data-src')) {
|
||||||
|
ele.src = ele.getAttribute('data-src')
|
||||||
|
}
|
||||||
|
if (!node.attrs.ignore) {
|
||||||
|
// 监听图片点击事件
|
||||||
|
ele.onclick = function (e) {
|
||||||
|
e.stopPropagation()
|
||||||
|
uni.postMessage({
|
||||||
|
data: {
|
||||||
|
action: 'onImgTap',
|
||||||
|
attrs: getAttrs(this)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (options[2]) {
|
||||||
|
const image = new Image()
|
||||||
|
image.src = ele.src
|
||||||
|
ele.src = options[2]
|
||||||
|
image.onload = function () {
|
||||||
|
ele.src = this.src
|
||||||
|
}
|
||||||
|
image.onerror = function () {
|
||||||
|
ele.onerror()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ele.onerror = onImgError
|
||||||
|
} else if (name === 'a') {
|
||||||
|
// 处理链接
|
||||||
|
ele.addEventListener('click', function (e) {
|
||||||
|
e.stopPropagation()
|
||||||
|
e.preventDefault() // 阻止默认跳转
|
||||||
|
const href = this.getAttribute('href')
|
||||||
|
let offset
|
||||||
|
if (href && href[0] === '#') {
|
||||||
|
offset = (document.getElementById(href.substr(1)) || {}).offsetTop
|
||||||
|
}
|
||||||
|
uni.postMessage({
|
||||||
|
data: {
|
||||||
|
action: 'onLinkTap',
|
||||||
|
attrs: getAttrs(this),
|
||||||
|
offset
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, true)
|
||||||
|
} else if (name === 'video' || name === 'audio') {
|
||||||
|
// 处理音视频
|
||||||
|
medias.push(ele)
|
||||||
|
if (!node.attrs.autoplay && !node.attrs.controls) {
|
||||||
|
ele.setAttribute('controls', 'true')
|
||||||
|
}
|
||||||
|
ele.onplay = function () {
|
||||||
|
uni.postMessage({
|
||||||
|
data: {
|
||||||
|
action: 'onPlay'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (options[3]) {
|
||||||
|
for (let i = 0; i < medias.length; i++) {
|
||||||
|
if (medias[i] !== this) {
|
||||||
|
medias[i].pause()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ele.onerror = function () {
|
||||||
|
uni.postMessage({
|
||||||
|
data: {
|
||||||
|
action: 'onError',
|
||||||
|
source: name,
|
||||||
|
attrs: getAttrs(this)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else if (name === 'table' && options[4] && !ele.style.cssText.includes('inline')) {
|
||||||
|
// 处理表格
|
||||||
|
const div = document.createElement('div')
|
||||||
|
div.style.overflow = 'auto'
|
||||||
|
div.appendChild(ele)
|
||||||
|
ele = div
|
||||||
|
} else if (name === 'svg') {
|
||||||
|
namespace = undefined
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ele = document.createTextNode(node.text.replace(/&/g, '&'))
|
||||||
|
}
|
||||||
|
parent.appendChild(ele)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置 html 内容
|
||||||
|
window.setContent = function (nodes, opts, append) {
|
||||||
|
const ele = document.getElementById('content')
|
||||||
|
|
||||||
|
// 容器样式
|
||||||
|
if (opts[0]) {
|
||||||
|
document.body.style.cssText = opts[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 长按复制
|
||||||
|
if (!opts[5]) {
|
||||||
|
ele.style.userSelect = 'none'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!append) {
|
||||||
|
ele.innerHTML = '' // 不追加则先清空
|
||||||
|
medias = []
|
||||||
|
}
|
||||||
|
|
||||||
|
options = opts
|
||||||
|
window.unloadimgs = 0
|
||||||
|
const fragment = document.createDocumentFragment()
|
||||||
|
createDom(nodes, fragment)
|
||||||
|
ele.appendChild(fragment)
|
||||||
|
|
||||||
|
// 触发事件
|
||||||
|
let height = ele.scrollHeight
|
||||||
|
uni.postMessage({
|
||||||
|
data: {
|
||||||
|
action: 'onLoad',
|
||||||
|
height
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (!window.unloadimgs) {
|
||||||
|
uni.postMessage({
|
||||||
|
data: {
|
||||||
|
action: 'onReady',
|
||||||
|
height
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
clearInterval(window.timer)
|
||||||
|
window.timer = setInterval(() => {
|
||||||
|
if (ele.scrollHeight !== height) {
|
||||||
|
height = ele.scrollHeight
|
||||||
|
uni.postMessage({
|
||||||
|
data: {
|
||||||
|
action: 'onHeightChange',
|
||||||
|
height: height
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, 350)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 回收计时器
|
||||||
|
window.onunload = function () {
|
||||||
|
clearInterval(window.timer)
|
||||||
|
}
|
||||||
|
|||||||
@@ -1 +1,33 @@
|
|||||||
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"><style>body,html{width:100%;height:100%;overflow-x:scroll;overflow-y:hidden}body{margin:0}video{width:300px;height:225px}img{max-width:100%;-webkit-touch-callout:none}</style></head><body><div id="content" style="overflow:hidden"></div><script type="text/javascript" src="./js/uni.webview.min.js"></script><script type="text/javascript" src="./js/handler.js"></script></body>
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no">
|
||||||
|
<style>
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow-x: scroll;
|
||||||
|
overflow-y: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
video {
|
||||||
|
width: 300px;
|
||||||
|
height: 225px;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="content" style="overflow: hidden;"></div>
|
||||||
|
<script type="text/javascript" src="./js/uni.webview.min.js"></script>
|
||||||
|
<script type="text/javascript" src="./js/handler.js"></script>
|
||||||
|
</body>
|
||||||
Reference in New Issue
Block a user