weex 实现富文本

首先介绍一下什么叫做富文本

后台常常要用到一个编辑器叫做富文本编辑器,例如淘宝和电商等等的详情页面编辑等等,这个编辑器可以参考

http://ueditor.baidu.com/website/onlinedemo.html

它编辑出来的文本我们可以看到

是一个

<p>

<span>

</span>

</p>

这样的一段内容,如果在前端显示这个就太容易了

< div  v-html=" ritchtextstyle= "font-size:32px;"  v-if="! platform></ div >

这样一行代码就搞定了,然而到 app上,就不是那么简单了

这时候有几种方案可供选择

1:如果内容没有嵌套很多的话,直接把里面所有的 文字标签换成 text 标签  img 标签全部换成 image标签就可以了

但是 weex 还有一个很麻烦的问题,text标签不呢个有子标签

呈现代码宏出错: 参数'firstline'的值无效
<p>aaa<span>bbb<span>ccc</span></span></p>

,如果富文本是这样的的话,那么 替换就无能为力了。image 必须指定图片宽高,否则就不能显示,所以这种方案局限性就太大了

2:使用 vue 来定一个一个组件可以解析显示这样的富文本内容

尝试写了一个

richtext
< 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 文件中去使用这个组件了

        < richtext   :richtext=" ritchtext"   style= "width:750px;height:25000px"  ></ richtext >

这里已然会有一个非常头疼的问题,你必须给这个组件指定一个高度,然而富文本具体有多高又未知,所以这个也是一个麻烦的问题,不过至少在效果上,这个处理比较理性

所以一个不成熟的框架会有n多问题可能需要去解决


ios 自定义富文本等使用苹果电脑的时候写完更新上来

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值