H5上前端能利用vue 富文本编辑器器做到以下效果吗

1246人阅读
技术需求:扩展 富文本编辑器 &功能
目标:本着不重复造轮子,集中精力解决业务逻辑。其实主要是没技术实力....
方向:寻找开源的富文本编辑器; 发现 各个开源的都差不多(技术菜,看不出区别),传统的编辑器太庞大,适合移动端的较少
结果:公司最近在搞tower,发现他们公司有个开源的simditor,就拿过来试了试,发现还不错呢
现状:too young too simple , 自行搜索‘富文本编辑器都是坑’
官方demo下载,一切ok
我的需求:调用某个方法可以插入自定义图片; 秉着钻(拼)研(死)精(一)神(搏),改写插入横线模块源码,果然可以插入图片,有戏
mand = function() {
var $hr, $newBlock, $nextBlock, $rootB
$rootBlock = this.editor.selection.rootNodes().first();
$nextBlock = $rootBlock.next();
if ($nextBlock.length & 0) {
this.editor.selection.save();
$newBlock = $('&p/&').append(this.editor.util.phBr);
$hr = $('&img src = &xxx.jpg& alt = && /&').insertAfter($rootBlock);//原来的代码:$hr = $('&hr/&').insertAfter($rootBlock);
照葫芦画瓢
扩展:&在Simditor对象原型里边增加一个function & ,如
&span style=&white-space:pre&& &/span&Simditor.prototype.insertJQNode($node)//参数为一个jquery 封装的dom对象
这样我就可以在js中随意调用 new&Simditor().insertJQNode($(&&img src= ''/&&))来插入图片了。
下边就是具体扩展方式,按照Simditor的规范去定义prototype
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define([ &jquery&, &simple-module&, &simditor& ], function($,
SimpleModule) {
return (root.returnExportsGlobal = factory($, SimpleModule));
} else if (typeof exports === 'object') {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like enviroments that support module.exports,
// like Node.
module.exports = factory(require(&jquery&), require(&simple-module&),
require(&simditor&));
root['Simditor'] = factory(jQuery, SimpleModule);
}(this, function($, SimpleModule) {
Simditor.prototype.insertJQNode = function($node) {
//主要代码在这..........................
现在框架搭起来了,就差insertJQNode 方法的实现:
Simditor.prototype.insertJQNode = function($node) {
if (!$node) {
console.error(&$node is null&);
if (!this) {
console.error(&Simditor instance
is null&);
this.focus();// 获取焦点
var $newNode, $newBlock, $nextBlock, $rootB
// console.log(this['selection'].rootNodes())
$rootBlock = this['selection'].rootNodes().first();//选中节点中的第一个节点
$nextBlock = $rootBlock.next();//
if ($nextBlock.length & 0) {//若选中多个节点,则在第一个节点后插入
$newNode = $node.insertAfter($rootBlock);
this['selection'].save();
this['selection'].restore();
} else if ($rootBlock[0].outerHTML == '&p&&br&&/p&') {//若是空行
$newNode = $node.insertBefore($rootBlock);
this['selection'].setRangeAtStartOf($rootBlock);
} else {//某行的末尾
$newNode = $node.insertAfter($rootBlock);
$newBlock = $('&p/&').append(this.util.phBr);
$newBlock.insertAfter($newNode);
this['selection'].setRangeAtStartOf($newBlock);
return this.trigger('valuechanged');
小优化:屏蔽simditor默认对 &img的处理
Simditor.Toolbar.buttons.image = function() {
var editor = new Simditor({
textarea: $('#txt-content'),
placeholder: '这里输入文字...',
toolbar: toolbar,
pasteImage: true,
defaultImage: 'assets/images/image.png',
upload: location.search === '?upload' ? {
url: '/upload'
var $img = $(&&p&&img alt='loading' src='http://3o890.jpg' width='100%'&&/p&&);
editor.insertJQNode($img);
这算是个v1.0版本吧,里边很多细节都很粗糙,欢迎大家批评指正
下次把代码模块化,继续完善&
----------------------------------------
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:78671次
积分:1099
积分:1099
排名:千里之外
原创:26篇
转载:16篇
评论:21条
(1)(1)(1)(1)(1)(2)(1)(2)(1)(2)(6)(1)(7)(6)(1)(3)(5)问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
因为我做的富文本编辑器最终是输出html的 当我插入图片后 后端的PHP就不能使用htmlspecialchars进行转义 但是又要防止在前端有人输入恶意的script 这个有什么思路吗
这个问题已被关闭,原因:
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
楼上的处理方法只适合在小应用中,并且处理范围非常有限,简单一点就是过滤/转义,在这我就不多说了,其实方法是非常多。我今天主要讲关于架构方面的知识:你google一下,了解下 WAF(Web应用防火墙),主要有两方面的:
软件角度的(推荐):基于nginx的Web应用防火墙/百度的加速了/创新工厂的安全宝......
硬件角度的(不推荐):NGAF
WAF可处理常见的Web安全有:XSS/SQL注入/跨站脚本/shell注入/会话劫持.....
在软件角度,git上面有不少这方面的开源项目,比如:
还有一些付费的云服务:安全宝/加速了......,可以了解下,确实很有意思,并不是简单的过滤转义。
个人认为:这本身属于网站架构方面的内容,是个全局的控制==输入/输出过滤,这要后台和前台保持一致就可以了。
这个问题已经被关闭无法回答
分享到微博?
Hi,欢迎来到 SegmentFault 技术社区!⊙▽⊙ 在这里,你可以提出编程相关的疑惑,关注感兴趣的问题,对认可的回答投赞同票;大家会帮你解决编程的问题,和你探讨技术更新,为你的回答投上赞同票。
明天提醒我
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:手把手实现富文本编辑器 - WEB前端 - 伯乐在线
& 手把手实现富文本编辑器
最近尝试去写一个富文本编辑器,觉得应该也不难,但没想到还是花了不少时间去写前期的主要逻辑,其间太多的边角逻辑是没有考虑到的。原因是前期走了 很多弯路,单纯的一点一点的去实现功能,有分支功能出现就一点一点的修补,到最后发现代码量很多,逻辑很复杂。最后痛下决心,静下心来分析了一下,思考用 理论逻辑去铺垫根基,才算是构建了一个还算满意的基础逻辑。真心觉得,理论才是一切事情的开始点,缜密的理论逻辑才能建造基乎无bug的代码。
前面的都是些废话,由于该文本编器实现了execCommaond的部分方法,下面的内容相对比较复杂,对实现不感兴趣的可以忽略,如果是妹子可以直接联系笔者交流交流
富文本编辑器实现如下的功能
实现fake原生execCommand的能力
修改style的能力
其实很多能力,原生的execCommand已经帮我们做好了,但我们的编辑器要有与execCommand相同的能力,以备原生无法实现的时候,我们的编辑器还是可以实现。
标签插入与删除
便签的修改能力
比如一段代码
&div&abcd&/div&
&div&abcd&/div&
如果abc被选中之后,执行execCommand之后的代码是在abc外包裹一个strong标签
&div&&strong&abc&/strong&d&/div&
&div&&strong&abc&/strong&d&/div&
如果b再次选中执行execCommand(‘bold’)命令后,会变成
&div&&strong&a&/strong&b&strong&c&/strong&&/div&
&div&&strong&a&/strong&b&strong&c&/strong&&/div&
可以看到原来的strong被分离了,变成单独的两个,还有一些更复杂的情况,如下
&div&&strong&ab&u&&strong&cd&u&b&span&&strong&pp&/strong&&/span&&/u&&strong&&/u&&/strong&&/div&
&div&&strong&ab&u&&strong&cd&u&b&span&&strong&pp&/strong&&/span&&/u&&strong&&/u&&/strong&&/div&
像这个串,如果没有良好的理论基础与抽象建模,靠手动的代码去处理基乎是不可能的。
串的正则化
如上那个复杂的串,其树结构如下
最上面的是根结点,叶子结点都是文本节点(textNode)
我们可以看到规律
叶子结点向上回溯的过程中,通过的结点会给我们赋予不同的功能,但我们要操作的节点,如果像strong、underline一定程度是与样式有关的,我们把它们称为样式结点
如果我们直接删掉叶子结点最近的祖先中的样式结点,很有可能会影响到其他的叶子结点,这时候我们就要把样式结点的影响最小化,就要先进行正则处理
正则化的过程就是要把样式结点转化到叶子结点的上面,每个样式结点只控制一个我们想要直接操作的叶子结点
如下的转化过程
正则化的过程的同时,我们还要修剪一些无用的结点,比如空的span结点,比如空的textNode,转化完了之后的树,我们处理起来变得很简单
正则化的实现也很简单,从ROOT结点进行中序遍历的算法,即先访问根结点,再从左向右依次访问子结点,然后一直到叶子结点,找出叶子结点的样式结点次续,并删除经过的样式结点,然后把它们插入到每个叶子结点的上面
JavaScript
var scan = function(node, inhrintStyles){
// 已经是叶子节点了
if(node.nodeType === node.TEXT_NODE){
if(inhrintStyles.length){
leafNodes.push({
inhrintStyles: inhrintStyles.concat([]),
node: node
// 非叶子节点
// 如果是style节点
// 标记这是要删除的style节点,
if(styleTagNames.indexOf(node.tagName.toLowerCase()) & -1){
// inhrintStyles存在此style 不重复增加
var exists = 0;
for(var i = 0; i & inhrintStyles. i ++){
if(inhrintStyles[i].tagName === node.tagName){
exists = 1;
if(! exists){
inhrintStyles = inhrintStyles.concat(node);
styleNodes.push(node);
for(var i = 0; i & node.childNodes. i ++){
scan(node.childNodes[i], inhrintStyles);
scan(tree, []);
12345678910111213141516171819202122232425262728293031323334353637
&& var scan = function(node, inhrintStyles){&&&&&&&&// 已经是叶子节点了&&&&&&&&if(node.nodeType === node.TEXT_NODE){&&&&&&&&&&&&&if(inhrintStyles.length){&&&&&&&&&&&&&&&&&&&&leafNodes.push({&&&&&&&&&&&&&&&&&&&&&&&& inhrintStyles: inhrintStyles.concat([]),&&&&&&&&&&&&&&&&&&&&&&&& node: node&&&&&&&&&&&&&&&&&&&&});&&&&&&&&&&&&&&&&}&&&&&&&&&&&& // 非叶子节点&&&&&&&&&& }else{&&&&&&&&&&&&&&&&// 如果是style节点&&&&&&&&&&&&&&&&// 标记这是要删除的style节点,&&&&&&&&&&&&&&&&if(styleTagNames.indexOf(node.tagName.toLowerCase()) & -1){&&&&&&&&&&&&&&&&&&&&// inhrintStyles存在此style 不重复增加&&&&&&&&&&&&&&&&&&&&var exists = 0;&&&&&&&&&&&&&&&&&&&&for(var i = 0; i & inhrintStyles.length; i ++){&&&&&&&&&&&&&&&&&&&&&&&&if(inhrintStyles[i].tagName === node.tagName){&&&&&&&&&&&&&&&&&&&&&&&&&&&&exists = 1;&&&&&&&&&&&&&&&&&&&&&&&&&&&&break;&&&&&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&if(! exists){&&&&&&&&&&&&&&&&&&&&inhrintStyles = inhrintStyles.concat(node);&&&&&&&&&&&&&&&& }&&&&&&&&&&&&&&&&&&styleNodes.push(node);&&&&&&&&&&&&&&&&}&&&&&&&&&&&for(var i = 0; i & node.childNodes.length; i ++){&&&&&&&&&&&&&&&& scan(node.childNodes[i], inhrintStyles);&&&&&&&&&&&&&&}&&&&&&&&&&&}&&&&&&};&&&scan(tree, []);
如下代码实现删除样式结点的过程
JavaScript
// 删除样式节点
for(var i = 0; i & styleNodes. i ++){
var styleNode = styleNodes[i];
var childNodes = styleNode.childN
var fragment = document.createDocumentFragment();
while(child = childNodes[0]){
fragment.appendChild(child);
styleNode.parentNode.replaceChild(fragment, styleNode);
1234567891011121314
&&// 删除样式节点&&&&&&&&&&&&for(var i = 0; i & styleNodes.length; i ++){&&&&&&&&&&&&&&&&var styleNode = styleNodes[i];&&&&&&&&&&&&&&&&&var childNodes = styleNode.childNodes;&&&&&&&&&&&&&&&&&var fragment = document.createDocumentFragment();&&&&&&&&&&&&&&&&var child;&&&&&&&&&&&&&&&&while(child = childNodes[0]){&&&&&&&&&&&&&&&&&&&&fragment.appendChild(child);&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&styleNode.parentNode.replaceChild(fragment, styleNode);&&&&&&&&&&&&}
经过这样处理后的树,没有了任何样式结点,这也是去除样式的一个方法
下面的代码展示将样式结点最小化到textNode之上的代码
JavaScript
// 对叶子结点进行样式插入
for(var i = 0; i & leafNodes. i ++){
var leafNode = leafNodes[i];
if(leafNode.node.nodeValue === ""){
leafNode.node.parentNode.removeChild(leafNode.node);
var styleN
var frag = document.createDocumentFragment();
var currParent =
while(styleNode = leafNode.inhrintStyles.shift()){
// 去除无用atribute属性
if(! donotTrimSpan && styleAttrTagNames.indexOf(styleNode.tagName.toLowerCase()) & - 1 && ! styleNode.attributes.length){
el = styleNode.cloneNode();
currParent.appendChild(el);
currParent =
var leafNodeParent = leafNode.node.parentN
var tempNode = document.createElement("span");
leafNodeParent.replaceChild(tempNode, leafNode.node);
currParent.appendChild(leafNode.node);
leafNodeParent.replaceChild(frag, tempNode);
123456789101112131415161718192021222324252627282930313233
// 对叶子结点进行样式插入&&&&&&&&&&&&for(var i = 0; i & leafNodes.length; i ++){&&&&&&&&&&&&&&&&var leafNode = leafNodes[i];&&&&&&&&&&&&&&&&&if(leafNode.node.nodeValue === ""){&&&&&&&&&&&&&&&&&&&&leafNode.node.parentNode.removeChild(leafNode.node);&&&&&&&&&&&&&&&&&&&&continue;&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&var node;&&&&&&&&&&&&&&&&var styleNode;&&&&&&&&&&&&&&&&var frag = document.createDocumentFragment();&&&&&&&&&&&&&&&&var currParent = frag;&&&&&&&&&&&&&&&&while(styleNode = leafNode.inhrintStyles.shift()){&&&&&&&&&&&&&&&&&&&&// 去除无用atribute属性&&&&&&&&&&&&&&&&&&&&if(! donotTrimSpan && styleAttrTagNames.indexOf(styleNode.tagName.toLowerCase()) & - 1 && ! styleNode.attributes.length){&&&&&&&&&&&&&&&&&&&&}else{&&&&&&&&&&&&&&&&&&&&&&&&el = styleNode.cloneNode();&&&&&&&&&&&&&&&&&&&&&&&&&currParent.appendChild(el);&&&&&&&&&&&&&&&&&&&&&&&&&currParent = el;&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&var leafNodeParent = leafNode.node.parentNode;&&&&&&&&&&&&&&&&var tempNode = document.createElement("span");&&&&&&&&&&&&&&&&leafNodeParent.replaceChild(tempNode, leafNode.node);&&&&&&&&&&&&&&&&&currParent.appendChild(leafNode.node);&&&&&&&&&&&&&&&&&leafNodeParent.replaceChild(frag, tempNode);&&&&&&&&&&&&}
经过了这一轮的正则化处理之后, 我们主要做了以下三件事情
最小化样式结点到文本结点上
去除无用的结点
去除重复的结点
其实这一轮正则化之后理应要再进行更多的优化,比如
正则化完成之后使我们修减样式结点变得容易很多了,为了实现execCommand的功能,我们要实现树的如下两个方法
叶子结点某个样式结点的删除
叶子结点某个样式结点的增加
增加的实现
先向上检查是否有该样式结点存在,如果有了就不进行添加了,如果没有,要进行添加
添加的实现了很简单
JavaScript
setNodesUnderLabel: function(selectedNodes, labelName){
selectedNodes.map(function(item){
var p = item.parentN
var hasLabel = 0;
if(p.childNodes.length & 1){
if(p.tagName.toLowerCase() === labelName){
hasLabel = 1;
}while(p = p.parentNode);
if(hasLabel){
var label = document.createElement(labelName);
item.parentNode.replaceChild(label, item);
label.appendChild(item);
1234567891011121314151617181920212223242526
&&&&&& setNodesUnderLabel: function(selectedNodes, labelName){&&&&&&&&&&&&selectedNodes.map(function(item){&&&&&&&&&&&&&&&&var p = item.parentNode;&&&&&&&&&&&&&&&&&var hasLabel = 0;&&&&&&&&&&&&&&&&do{&&&&&&&&&&&&&&&&&&&&if(p.childNodes.length & 1){&&&&&&&&&&&&&&&&&&&&&&&&break;&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&&&&if(p.tagName.toLowerCase() === labelName){&&&&&&&&&&&&&&&&&&&&&&&&hasLabel = 1;&&&&&&&&&&&&&&&&&&&&&&&&break;&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&}while(p = p.parentNode);&&&&&&&&&&&&&&&&&if(hasLabel){&&&&&&&&&&&&&&&&}else{&&&&&&&&&&&&&&&&&&&&var label = document.createElement(labelName);&&&&&&&&&&&&&&&&&&&&&item.parentNode.replaceChild(label, item);&&&&&&&&&&&&&&&&&&&&&label.appendChild(item);&&&&&&&&&&&&&&&&}&&&&&&&&&&&&});&&&&&&&&},
删除的实现也是如此,先向上检查是否有label存在,有的话才删除
树的抽象功能已经建成,但后面提取最选中的叶子结点也并非一件容易的事情,主要是浏览器提供的API坑点太多,太不好用
Selection & Range对象
使用这两个父子对象,能帮我们获取被选中的区域
就是蓝色被选中的可视区域
就是逻辑里面的一块区域,与可视化无关
从一个蓝色选中的区域中获取到Range对象,用如下的方法
JavaScript
var selection = window.getSelection();
if(selection.rangeCount){
range = selection.getRangeAt(0);
var selection = window.getSelection();var range;if(selection.rangeCount){&&&&range = selection.getRangeAt(0);}
拿到Range,我们还要分析被选中的叶子节点,这里有很多坑点
首先Range对象,我们常用的五个属性
startContainer 开始选中的元素
startOffset 开始选中的偏移
endContainer
commonAncestorContainer 共同的最近的祖先结点
startContainer有两种情况,一种是元素,但这时被选中的是其子结点, 这时候startOffset代表的是被选中的子结点的index,子结点可能是叶子结点,也可能是element结点,另外一种可能是叶子结点 (textNode),startOffset代表的是text的偏移位置,比较坑的是,有可能偏移位置是不存在的str,什么意思呢,就是比如
startContainer对应叶子结点abcd
startOffset如果是1,那就被选中的开始就是从第1个字符开始(下标从0算)即bcd
但startOffset还可能是4,这时就坑了,开始什么都没有
同样endContainer也是如此
我们的任务是要找出被选中的叶子结点,然后进行增删样式处理,当前,前提是保证已经正则化过了
找出被选中的叶子结点并非一件容易的事情
文章比较长,请待后续更新
可能感兴趣的话题
大神啊!求抱大腿,我想和您讨论讨论这个富文本编辑器的问题。我想做编辑整个网页的富文本编辑器。求您的qq和微信
关于伯乐前端
伯乐前端分享Web前端开发,包括JavaScript,CSS和HTML5开发技术,前端相关的行业动态。
新浪微博:
推荐微信号
(加好友请注明来意)
– 好的话题、有启发的回复、值得信赖的圈子
– 分享和发现有价值的内容与观点
– 为IT单身男女服务的征婚传播平台
– 优秀的工具资源导航
– 翻译传播优秀的外文文章
– 国内外的精选文章
– UI,网页,交互和用户体验
– 专注iOS技术分享
– 专注Android技术分享
– JavaScript, HTML5, CSS
– 专注Java技术分享
– 专注Python技术分享
& 2017 伯乐在线artEditor增加h5拍照上传图片
来源:博客园
摘要: artEditor富文本 编辑器增加了图片拍照功能,点击图片按钮你可以从手机相册选择图片,也可以通过相机拍照上传。 项目地址: /baixuexiyang/artEditor 演示地址: http://baixuexiyang.github.io/artEditor/
免责声明:本站部分内容、图片、文字、视频等来自于互联网,仅供大家学习与交流。相关内容如涉嫌侵犯您的知识产权或其他合法权益,请向本站发送有效通知,我们会及时处理。反馈邮箱&&&&。
学生服务号
在线咨询,奖学金返现,名师点评,等你来互动| 时间排序
&p&如何取得呢??&/p&
如何取得呢??
&p&人家不懂技术,完全不明白。。&/p&
人家不懂技术,完全不明白。。
&p&该如何解决呢?&/p&
该如何解决呢?
&p&最近2天新浪长微博这个地方:&a href=&///?target=http%3A//control..cn/admin/article/changWeiBo.php& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&长微博_长微博工具_长微博生成器:新浪长微博官方网站&i class=&icon-external&&&/i&&/a& 好像发布不了长微博了&/p&
最近2天新浪长微博这个地方: 好像发布不了长微博了
&p&iframe 的性能问题问题是一个原因,还有一个原因是浏览器迟迟不支持 seamless 属性,导致适应宽度与高度很困难。&/p&
iframe 的性能问题问题是一个原因,还有一个原因是浏览器迟迟不支持 seamless 属性,导致适应宽度与高度很困难。
&p&首先看你数据是怎样的,两种方式&/p&&p&1.文字 +图片 + 文字,这种需要排版,github有封装好的富文本&/p&&p&2.类似百度贴吧评论 文字 + 文字 ,另起行 +图片,这种应该是主流吧,很多评论里面都这样操作.还可以实现图片放大等功能,比较容易操作,不容易乱.\&/p&&p&---------------------------分割线------------------------&/p&&p&回答你的评论&/p&&p&你说的稍微具体一点,比如什么样的数据.&/p&&br&&img src=&/v2-363aa9b217c7c86f80b1cded_b.png& data-rawwidth=&756& data-rawheight=&1246& class=&origin_image zh-lightbox-thumb& width=&756& data-original=&/v2-363aa9b217c7c86f80b1cded_r.png&&&br&&img src=&/v2-f55cb21f952_b.png& data-rawwidth=&732& data-rawheight=&1188& class=&origin_image zh-lightbox-thumb& width=&732& data-original=&/v2-f55cb21f952_r.png&&&p&上面两个都是我说的第二种&/p&&p&图片和文字分离&/p&&p&第一个是微博的&/p&&p&第二个是百度贴吧的&/p&&p&你可以参照一下.&/p&
首先看你数据是怎样的,两种方式1.文字 +图片 + 文字,这种需要排版,github有封装好的富文本2.类似百度贴吧评论 文字 + 文字 ,另起行 +图片,这种应该是主流吧,很多评论里面都这样操作.还可以实现图片放大等功能,比较容易操作,不容易乱.\---------------------…
&p&$$\alpha _i := \alpha _i$$&/p&&p&你试一下,加个空格.&/p&
$$\alpha _i := \alpha _i$$你试一下,加个空格.
两种思路:&br&1.本地导入图片后,将数据上传服务器返回url,src=url插入图片&br&2.本地导入图片后,将数据转化为base64的url
两种思路: 1.本地导入图片后,将数据上传服务器返回url,src=url插入图片 2.本地导入图片后,将数据转化为base64的url
H5 页面啥时候内置了富文本编辑框,可以给个截图吗?
H5 页面啥时候内置了富文本编辑框,可以给个截图吗?
做到这个效果是比较容易的,只是图片和文字的混排。直接使用webview内嵌可编辑的网页,实现原生和网页中javascript的命令交互和回调即可达到目的。
做到这个效果是比较容易的,只是图片和文字的混排。直接使用webview内嵌可编辑的网页,实现原生和网页中javascript的命令交互和回调即可达到目的。
##两种思路 &br&- 当HTML 来解析;&br&- CoreText,不愿意自己写,就去看 YY 大神的 &strong&&a class=& wrap external& href=&///?target=https%3A///ibireme/YYText& target=&_blank& rel=&nofollow noreferrer&&YYText&i class=&icon-external&&&/i&&/a&&/strong&
应该满足了市面上对富文本的绝大部分徐需求
##两种思路 - 当HTML 来解析; - CoreText,不愿意自己写,就去看 YY 大神的
应该满足了市面上对富文本的绝大部分徐需求
已有帐号?
无法登录?
社交帐号登录

我要回帖

更多关于 富文本web编辑器 的文章

 

随机推荐