首先介绍一下什么叫做富文本
后台常常要用到一个编辑器叫做富文本编辑器,例如淘宝和电商等等的详情页面编辑等等,这个编辑器可以参考
http://ueditor.baidu.com/website/onlinedemo.html
它编辑出来的文本我们可以看到
是一个
<p>
<span>
</span>
</p>
这样的一段内容,如果在前端显示这个就太容易了
这样一行代码就搞定了,然而到 app上,就不是那么简单了
这时候有几种方案可供选择
1:如果内容没有嵌套很多的话,直接把里面所有的 文字标签换成 text 标签 img 标签全部换成 image标签就可以了
但是 weex 还有一个很麻烦的问题,text标签不呢个有子标签
呈现代码宏出错: 参数'firstline'的值无效<p>aaa<span>bbb<span>ccc</span></span></p>
,如果富文本是这样的的话,那么 替换就无能为力了。image 必须指定图片宽高,否则就不能显示,所以这种方案局限性就太大了
2:使用 vue 来定一个一个组件可以解析显示这样的富文本内容
尝试写了一个
<
template
>
<
div
class
=
"rich-text"
>
<
div
v-for
=
"(child, index) in children"
:key
=
"index"
>
<
div
v-if
=
"child.tag === 'text'"
>
<
text
class
=
"product-text"
:style
=
"child.style"
>{{child.text}}</
text
>
</
div
>
<
div
v-if
=
"child.tag === 'image'"
class
=
"image-wrapper"
>
<
image
:src
=
"child.src"
resize
=
"stretch"
class
=
"product-image"
:style
=
"{width: child.width, height: child.height}"
></
image
>
</
div
>
<
div
v-if
=
"child.tag === 'br'"
>
<
text
class
=
"br"
></
text
>
</
div
>
</
div
>
</
div
>
</
template
>
<
style
>
.rich-text {
margin-top: 30px;
}
.product-text, .image-wrapper {
padding-left: 20px;
padding-right: 20px;
}
.br {
height: 20px;
}
</
style
>
<
script
>
import { html2json } from 'html2json'
import { translateJSON } from '../utils'
export default {
props: {
content: {
type: String,
required: true
},
imgSize: {
type: Object,
required: true
}
},
computed: {
children() {
const json = html2json(this.content)
console.error('json = '+json)
console.error('json = '+json)
return translateJSON(json, this.imgSize)
}
}
}
</
script
>
|
export
function
throttle (func, wait) {
let last = 0
return
function
(...args) {
const context =
this
const time =
new
Date().getTime()
if
(time - last > wait) {
func.apply(context, args)
last = time
}
}
}
export const translateJSON = (node, imgSize) => {
const result = []
const translate = (node, styleList) => {
const styleL = node.attr && node.attr.style ? [...styleList, node.attr.style] : styleList
if
(node.tag && node.tag ===
'img'
) {
console.error(
'node.attr = '
+node.attr.src)
console.error(
'node.imgSize = '
+imgSize)
if
(
typeof
(imgSize) ===
'undefined'
||
typeof
(node) ===
'undefined'
||
typeof
(node.attr) ===
'undefined'
){
return
}
const obj = imgSize[node.attr.src] ||
'{width: 710, height: 500}'
const {width, height} = JSON.parse(obj)
result.push({
tag:
'image'
,
src: node.attr.src,
width:
'710px'
,
height: (710 * height / width) +
'px'
})
}
else
if
(node.tag && node.tag ===
'br'
) {
result.push({
tag:
'br'
})
}
else
if
(!node.tag && node.node ===
'text'
) {
const style = styleL.map(s => {
var
str =
''
try
{
str = (/font-size:/.test(s)) ? s.replace(/\d+/g, 2 * parseInt(s.split(
':'
)[1], 10)) : s
}
catch
(error) {
// 此处是负责例外处理的语句
} finally {
return
str
}
}).reduce((acc, s) => {
var
tokens =
''
var
key =
''
try
{
tokens = s.split(
':'
)
key = tokens[0].replace(/\-([a-z]{1})/, (str, $1) => $1.toUpperCase())
const value = tokens[1].split(
';'
)[0]
acc[key] = value
}
catch
(error) {
// 此处是负责例外处理的语句
}
return
acc
}, {})
result.push({
tag:
'text'
,
style,
text: node.text.replace(/&[a-z]{3,4};/g,
''
)
})
}
if
(node.child && node.child.length) {
node.child.forEach(c => translate(c, styleL))
}
}
translate(node, [])
return
result
}
|
用下来会发现需要处理的问题之复杂远远超过了想像
当然期望网上还有一些其他的第三方解决方案,不过weex的并没有,只有一个小程序的富文本解决方案,并没有什么用
https://weappdev.com/t/wxparse-version0-2-html-markdown/326
有兴趣可以看看
所以综合1-2来看,期望在 js 中把这个问题处理掉难度貌似很大
所以我想,依赖第三种解决方案
3:weex 原生组件拓展
那么就去 android 和ios 上分别实现一个这样的扩展 组件就好了
https://github.com/zzhoujay/RichText
就使用这个解决方案
首先 在 gradle 中添加依赖
compile 'com.zzhoujay.richtext:richtext:2.5.4'
然后自定义组件
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package
com.alibaba.weex.extend.component;
import
android.content.Context;
import
android.support.annotation.NonNull;
import
android.text.SpannableString;
import
android.text.Spanned;
import
android.text.method.LinkMovementMethod;
import
android.text.style.URLSpan;
import
android.view.LayoutInflater;
import
android.widget.RelativeLayout;
import
android.widget.TextView;
import
android.widget.Toast;
import
com.alibaba.weex.R;
import
com.taobao.weex.WXSDKInstance;
import
com.taobao.weex.dom.WXDomObject;
import
com.taobao.weex.ui.component.WXComponent;
import
com.taobao.weex.ui.component.WXComponentProp;
import
com.taobao.weex.ui.component.WXVContainer;
import
com.zzhoujay.richtext.RichText;
public
class
RichTextView
extends
WXComponent<RelativeLayout> {
public
RichTextView(WXSDKInstance instance, WXDomObject dom, WXVContainer parent) {
super
(instance, dom, parent);
}
@Override
protected
RelativeLayout initComponentHostView(
@NonNull
Context context) {
LayoutInflater inflater = LayoutInflater.from(context);
RelativeLayout gifview = (RelativeLayout)inflater.inflate(R.layout.ritchtext_layout,
null
);
return
gifview;
}
@WXComponentProp
(name =
"richtext"
)
public
void
setRichtextLink(String richtext){
RichText.from(richtext).autoPlay(
true
).into((TextView) getHostView().findViewById(R.id.rich_text));
}
}
|
然后在android 项目中注册组件
WXSDKEngine.registerComponent("richtext", RichTextView.class);
最后可以在weex 的 vue 文件中去使用这个组件了
这里已然会有一个非常头疼的问题,你必须给这个组件指定一个高度,然而富文本具体有多高又未知,所以这个也是一个麻烦的问题,不过至少在效果上,这个处理比较理性
所以一个不成熟的框架会有n多问题可能需要去解决
ios 自定义富文本等使用苹果电脑的时候写完更新上来