TakWolf-Deprecated / CNode-Material-Design

CNode 社区第三方 Android 客户端,原生 App,Material Design 风格,支持夜间模式。
https://cnodejs.org
Apache License 2.0
1.34k stars 347 forks source link

兼容模式中,Markdown中图片点击事件绑定相关的实现方法的改进 #36

Closed TakWolf closed 8 years ago

TakWolf commented 8 years ago

需求:Markdown渲染完成之后,要对Markdown中的img绑定单击事件,实现点击图片查看大图的功能。

目前的实现为:

视图基于Vue.js,Markdown渲染直接使用模板:参考 https://github.com/TakWolf/CNodeMD-Page-Render-Compat/blob/master/topic_light.html#L43

<div class="markdown-container">
        {{{topic.rendered_content}}}  // rendered_content是已经渲染过的html字符串
</div>

对数据源变动实现监听,在回调中借助jQuery实现事件绑定:参考 https://github.com/TakWolf/CNodeMD-Page-Render-Compat/blob/master/js/topic.js#L77

vmPage.$watch('topic', function () {
    $('.markdown-text img').unbind('click').click(function () {
        var img = $(this);
        if (img.parent('a').length <= 0) {
            window.imageBridge.openImage(img.attr('src'));
        }
    });
});

目前功能可以实现,但是不确定思路是否正确。

存在的问题:

  1. 引入了jQuery,略不爽
  2. vue.js的视图的生成和jQuery之间是否冲突不清楚?用起来貌似没问题
  3. 是否有性能问题?主要担心的是jquery的绑定会不会引起vue的重新渲染造成死循环?貌似不存在这个问题,但是实际使用过程在,webview有极小概率卡死,不清楚愿意是什么
  4. 生成reply对象添加到topic.replies时,这个过程,并没有直接改变topic,所以vuejs的监听器没有触发,这个reply中的图片就没有点击事件
alsotang commented 8 years ago

vuejs 的监听器不是可以通过 vue.$set 方式来改变吗?这时候就可以被监听到改变了

在 2016年5月15日 下午9:55,TakWolf notifications@github.com写道:

需求:Markdown渲染完成之后,要对Markdown的img绑定单击事件,已实现点击图片查看大图的功能。

目前的实现为:

视图基于Vue.js,Markdown渲染直接使用模板: https://github.com/TakWolf/CNodeMD-Page-Render-Compat/blob/master/topic_light.html#L43

{{{topic.rendered_content}}} // rendered_content是已经渲染过的html字符串

对数据源变动实现监听,在回调中借助jQuery实现事件绑定: https://github.com/TakWolf/CNodeMD-Page-Render-Compat/blob/master/js/topic.js#L77

vmPage.$watch('topic', function () { $('.markdown-text img').unbind('click').click(function () { var img = $(this); if (img.parent('a').length <= 0) { window.imageBridge.openImage(img.attr('src')); } }); });

目前功能上是实现了,但是不确定思路是否正确。

存在的问题:

1.

引入了jQuery,略不爽 2.

vue.js的视图的生成和jQuery之前是否冲突不清楚?用起来貌似没问题 3.

是否有性能问题?主要担心的是jquery的绑定会不会引起vue的重新渲染照成死循环?貌似不存在这个问题,但是实际使用过程在,webview有极小概率卡死,不清楚愿意是什么 4.

生成reply对象添加到topic.replies时,这个过程,并没有直接改变topic,所以vuejs的监听器没有触发,这个reply中的图片就没有点击事件

— You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub https://github.com/TakWolf/CNode-Material-Design/issues/36

TakWolf commented 8 years ago

@alsotang 仔细看了一下文档,问题4确实有解决方案

文档地址:http://vuejs.org.cn/guide/list.html#问题

因为 JavaScript 的限制,Vue.js 不能检测到下面数组变化:

直接用索引设置元素,如 vm.items[0] = {};
修改数据的长度,如 vm.items.length = 0。
为了解决问题 (1),Vue.js 扩展了观察数组,为它添加了一个 $set() 方法:

// 与 `example1.items[0] = ...` 相同,但是能触发视图更新
example1.items.$set(0, { childMsg: 'Changed!'})
至于问题 (2),只需用一个空数组替换 items。

除了 $set(), Vue.js 也为观察数组添加了 $remove() 方法,用于从目标数组中查找并删除元素,在内部它调用 splice() 。因此,不必这样:

var index = this.items.indexOf(item)
if (index !== -1) {
  this.items.splice(index, 1)
}
只用这样:

this.items.$remove(item)
alsotang commented 8 years ago

https://github.com/vuejs/vue/issues/2586#issuecomment-203038630

这是我两个月帮你【创造】的文档。。你刚好都复制了

alsotang commented 8 years ago

噢噢,不对,我上面 issue 对应的是这里:http://vuejs.org.cn/api/#u6570_u7EC4_u6269_u5C55_u65B9_u6CD5

TakWolf commented 8 years ago

@alsotang 数组更新的问题现在搞定了

动态事件绑定,现在的思路是对的吗?

alsotang commented 8 years ago

用了 .$set 就对了啊。

原来上说,vue hack 一些常见的用法,来达到数据动态监听的效果。但是更深层的,由于 js 的反射机制没有那么灵活,就只能借用类似 .$set.$remove 这类来做了。

2016-05-16 20:50 GMT+08:00 TakWolf notifications@github.com:

@alsotang https://github.com/alsotang 数组更新的问题现在搞定了

动态事件绑定,现在的思路是对的吗?

— You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub https://github.com/TakWolf/CNode-Material-Design/issues/36#issuecomment-219417067

TakWolf commented 8 years ago

@alsotang 这个已经搞懂了,动态绑定指的是动态绑定html中的img这个问题

TakWolf commented 8 years ago

跟踪:

https://cnodejs.org/topic/57389ad640b2969853981358#573ae28bb507f69e1dd89f8a

https://segmentfault.com/q/1010000005143113

alsotang commented 8 years ago

jquery 的 delegate 用法,把事件绑在触发事件元素的祖先上。

2016-05-17 17:27 GMT+08:00 TakWolf notifications@github.com:

跟踪:

https://cnodejs.org/topic/57389ad640b2969853981358#573ae28bb507f69e1dd89f8a

https://segmentfault.com/q/1010000005143113

— You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub https://github.com/TakWolf/CNode-Material-Design/issues/36#issuecomment-219665537

TakWolf commented 8 years ago

根据各种意见,最终通过代理事件的方式来实现。 参考: https://github.com/TakWolf/CNodeMD-Page-Render-Compat/blob/master/topic_light.html#L91 https://github.com/TakWolf/CNodeMD-Page-Render-Compat/blob/master/js/topic.js#L74

<div class="markdown-container" v-on:click="openImageProxy($event)">
    {{{reply.rendered_content}}}
</div>

openImageProxy: function (event) {
    if (event.target.nodeName === 'IMG') {
        if (event.target.parentNode.nodeName !== 'A') {
            window.imageBridge.openImage(event.target.src);
        }
    }
}

fix by https://github.com/TakWolf/CNode-Material-Design/commit/3bfb22ad7a8fc50c73fa57c2d3d359c20c9c75b7