React操作DOM —— 添加查看原图按钮的图片点击事件

17 篇文章 0 订阅
3 篇文章 0 订阅

时刻提醒自己React的生命周期,镇楼图:
react生命周期

需求一
点击页面中的图片获取到全部图片的src以及当前图片的index。

麻烦点
页面是react编写;
页面显示的数据均是由后端以拼接html形式传过来的,img也在html拼接结果中。

踩坑过程
首先,不能在componentDidMount中获取到imglist,因为componentDidMount最后才异步获取后端接口数据,
所以想在componentDidUpdate中获取。(被领导告知不要这样)
由于img是拼接在html中的,不能使用Touchable处理点击事件,所以想到在页面中添加

最后——React操作DOM可行方法
在componentDidMount中添加document的事件监听方法,代码如下:

document.body.addEventListener('click', function(e){
    // 判断是否点击的图片
    if(e.path[0].nodeName === 'IMG'){
        let params = {};
        params.param = {};
        // 获取imglist
        var oPics = document.getElementsByTagName("img");
        params.param.imageArray = [];
        for(let i=0; i<oPics.length; i++){
            params.param.imageArray.push({url:oPics[i].src});
        }
        for(let i=0; i<oPics.length; i++){
            // 判断点击图片的index
            if(e.path[0].src === params.param.imageArray[i].url){
                params.param.index = i;
            }
        }
        console.log(params);
    }
});

⚠️此处注意:浏览器测试时,可能对touchstart/touchend/click的响应与移动端不同,例如上面将图片响应事件放在click中,在click上面有touchstart和touchend事件的处理,在移动端图片点击没有反应(找原因的时候一直忽略了事件没有响应,以为是链接问题,所以在找原因时注意每一个步骤“冒泡”的去找原因)

解决办法是将上述click事件的逻辑放到已有的touchend中。

需求二
图片上显示“查看原图”的按钮,在整个图片和按钮上点击都可以实现需求一。

踩坑过程
想法No1: img添加伪元素:after,但是img不能添加伪元素,原因是:

W3C 标准中寻觅一下,在标准中,before, after 伪类的定义如:
As their names indicate, the :before and :after pseudo-elements specify the location of content before and after an element’s document tree content.
来自 https://www.w3.org/TR/CSS21/generate.html#before-after-content
我们应该注意到所谓 document tree content,对于 img 这种自闭和标签,似乎不存在 content (内容或后代元素)在标签中,所以选择器没有生效。但这样的解释还不够清晰,实际上标准中还有一行注释:
Note. This specification does not fully define the interaction of :before and :after with replaced elements (such as IMG in HTML). This will be defined in more detail in a future specification.
嗯,这回清楚了,对于可替换元素(如 img、input、select 等),标准并没有清晰定义,这也导致了浏览器实现的差异性。
解释见:http://ask.dcloud.net.cn/article/13475

想法No2:给img的父元素p添加:after,但是CSS选择器不支持子元素获取父元素,原因是:

如果CSS支持了父选择器,那就必须要页面所有子元素加载完毕才能渲染HTML文档,因为所谓“父选择器”,就是后代元素影响祖先元素,如果后代元素还没加载处理,如何影响祖先元素的样式?于是,网页渲染呈现速度就会大大减慢,浏览器会出现长时间的白板。加载多少HTML就可以渲染多少HTML,在网速不是很快的时候,就显得尤为的必要。比方说你现在看的这篇文章,只要文章内容加载出来就可以了,就算后面的广告脚本阻塞了后续HTML文档的加载,我们也是可以阅读和体验。但是,如果支持父选择器,则整个文档不能有阻塞,页面的可访问性则要大大降低。

有人可能会说,要不采取加载到哪里就渲染到哪里的策略?这样子问题更大,因为会出现加载到子元素的时候,父元素本来渲染的样式突然变成了另外一个样式的情况,体验非常不好。
“相邻选择器只能选择后面的元素”也是一样的道理,不可能说后面的HTML加载好了,还会影响前面HTML的样式。
所以,从这一点来讲,CSS支持“父选择器”或者“前兄弟选择器”的可能性要比其他炫酷的CSS特性要低,倒不是技术层面,而是CSS和HTML本身的渲染机制决定的。当然,以后的事情谁都说不准,说不定以后网速都是每秒几个G的,网页加载速度完全就忽略不计,说不定就会支持了。
张大大解释:https://www.zhangxinxu.com/wordpress/2016/08/css-parent-selector/

最后——图片上添加查看原图按钮方案
从图片获取到父元素,通过父元素添加<div><input /></div>到图片后面,加

包裹是为了实现按钮居中text-align:center的效果(思考:可以不用
包裹吗?),将按钮和图片的点击事件同时捕获,此处注意两点:

一、在写实例程序时遇到冒泡,阻止冒泡代码:

var oImg = document.getElementsByTagName("img")[0];
oImg.onclick = function(e){
    e.stopPropagation();
    alert('img');
};
var p = document.getElementsByTagName("p")[0];
p.onclick = function(){
    alert('p');
};

(发生在子和父都存在点击事件时,点击子元素执行完子元素的点击事件会继续执行父元素的点击事件)

二、属性值的获取,也就是说e的内容的读取,在dom新建input时将图片src注入到input标签中:

⚠️注意:e中可以通过e.target.dataset.src获取到用户自定义的属性data-src,但是网上有人反映有识别不出来的情况是因为-后的命名使用了驼峰命名法,如果全部是小写字母就可以被e识别了(这里提醒一下自己)。

防触设计
在浏览器测试没有问题,在移动端当手指按到屏幕上滑动时(页面滚动前)页面就跳转了,这与我们的期望不同,我们期望滑动的时候不进行跳转。
解决办法也较为简单:

// 防止误触
move = 0; // move可以设置为class属性
document.body.addEventListener('touchstart',function(e){
    this.move = 0;
});
document.body.addEventListener('touchmove', function(e){
    this.move = 1
});
document.body.addEventListener('touchend',function(e) {
    if(this.move === 0){ /* 处理响应事件逻辑 */ }
});

参考:https://segmentfault.com/q/1010000010930325?sort=created

附赠添加兄弟节点代码:

// 添加兄弟元素
function insertAfter(newElement, targetElement){
    var parent = targetElement.parentNode;
    if (parent.lastChild == targetElement) {
        parent.appendChild(newElement);
    } else {
        parent.insertBefore(newElement, targetElement.nextSibling);
    }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值