zhangxinxu/quiz

DOM基础测试28

Opened this issue · 23 comments

本期小测题目如下,主要考察DOM位置比对:

题目中的HTML代码可以复制下面代码的进行测试:

<div id="container" class="container">
    <section>
        <img src="https://image.zhangxinxu.com/image/study/s/s256/mm.jpg" alt="外层图片">
        <p>
            <img src="https://image.zhangxinxu.com/image/study/s/s256/mm1.jpg" alt="示意图1">
            <img src="https://image.zhangxinxu.com/image/study/s/s256/mm2.jpg" alt="示意图2">
            <img id="compareImg" src="https://image.zhangxinxu.com/image/study/s/s256/mm3.jpg" alt="示意图3">
            <img src="https://image.zhangxinxu.com/image/study/s/s256/mm4.jpg" alt="示意图4">
            <img src="https://image.zhangxinxu.com/image/study/s/s256/mm5.jpg" alt="示意图5">
        </p>
    </section>
</div>

大家提交回答的时候,注意缩进距离,起始位置从左边缘开始;另外,github自带代码高亮,所以请使用下面示意的格式。

 ```js
// 你的JS代码写在这里
 ```
crimx commented
window.addEventListener(
  'click',
  e => {
    const { target } = e
    if (target.tagName === 'IMG' &&
        isContain(document.getElementById('container'), target)
    ) {
      e.target.style.outline = `2px solid ${
        getOutlineColor(document.getElementById('compareImg'), target)
      }`
    } else {
      for (const img of document.images) {
        img.style.outline = 'none'
      }
    }
  },
)

/**
 * @param parent {HTMLElement}
 * @param child {HTMLElement}
 * @returns boolean
 */
function isContain (parent, child) {
  if (!parent || !child) { return false }
  return parent.contains(child)
}

/**
 * @param compareImg {HTMLElement}
 * @param targetImg {HTMLElement}
 * @returns string
 */
function getOutlineColor (compareImg, targetImg) {
  if (compareImg && targetImg) {
    switch (compareImg.compareDocumentPosition(targetImg)) {
      case 0: return ''
      case Node.DOCUMENT_POSITION_PRECEDING: return 'red'
      case Node.DOCUMENT_POSITION_FOLLOWING: return 'green'
    }
  }
  return 'blue'
}
const container = document.getElementById('container')
window.addEventListener('click', e => {
  let el = e.target
  if (isValidElement(el)) {
    el.style.outline = getImgStyle(el)
  } else {
    clearImgStyle()
  }
})
const isValidElement = el => {
  return el && container.contains(el) && el.tagName === 'IMG'
}
const getImgStyle = el => {
  const baseId = 'compareImg'
  const basicStyle = '2px solid'
  if (el.id === 'compareImg') {
    return basicStyle
  } else {
    let tempElm = el
    while (tempElm) {
      if (tempElm.id === baseId) {
        return `${basicStyle} green`
      }
      tempElm = tempElm.previousElementSibling
    }
    tempElm = el
    while (tempElm) {
      if (tempElm.id === baseId) {
        return `${basicStyle} red`
      }
      tempElm = tempElm.nextElementSibling
    }
  }
  return `${basicStyle} blue`
}
const clearImgStyle = () => {
  const imgs = document.querySelectorAll('img')
  for (let i of imgs) {
    i.style.outline = 'none'
  }
}
.container{
    border:1px solid;
    background: lightblue;
    padding:100px;
    margin:100px;
}
<div
    id="container"
    class="container"
>
    <section>
        <img src="https://avatars0.githubusercontent.com/u/11225175?s=40&v=4">
        <div>
            <img src="https://avatars0.githubusercontent.com/u/11225175?s=40&v=4">
            <img src="https://avatars0.githubusercontent.com/u/11225175?s=40&v=4">
            <img id="compareimg" src="https://avatars0.githubusercontent.com/u/11225175?s=40&v=4">
            <img src="https://avatars0.githubusercontent.com/u/11225175?s=40&v=4">
            <img src="https://avatars0.githubusercontent.com/u/11225175?s=40&v=4">
        </div>
    </section>
</div>
const container = document.querySelector("#container"),
        compareimg = document.querySelector("#compareimg");
document.addEventListener("click",function(e){
    //当前点击的元素
    var target = e.target,
    //是否是后代的标志
        isPosterity,
    //是否是img的标志
        isImg;


    //判断当前点击的元素是否是#contaienr的子元素
    if(
        //判断当前点击的元素在#container中
        target.closest("#container")
        &&
        //判断当前点击的元素不是#container自身
        target!==container
    ){
        isPosterity = true;
        console.log("当前点击的是container的子元素")
    }else{
        isPosterity = false;
        console.log("当前点击的是container的子元素")
    }


    //判断当前点击的元素是否是img元素
    if(target.tagName==="IMG"){
        isImg = true;
        console.log("当前点击的元素是img");
    }else{
        isImg = false;
        console.log("当前点击的元素不是img");
    }


    //如果既是后代元素又是img,那么设置点击元素的outline样式为2px solid;
    //否则取消所有img元素的outline
    if(isPosterity&&isImg){
        target.style.outline = "2px solid";
    }else{
        [].slice.call(document.querySelectorAll("img")).forEach(function(img){
            img.style.outline = "";
        })
    }


    //如果点击的图片元素的dom在“示意图3”的前面,则设置outline-color为red
    //如果在后面,则设置outline-color为green
    //如果是自己,不专门设置outline-color
    //如果没有前后关系,则设置outline-color为blue
    if(target !== compareimg){
        if(!isBrother(target)){
            target.style.outlineColor = "blue";
        }else if(isPrev(target)){
            target.style.outlineColor = "red";
        }else if(isNext(target)){
            target.style.outlineColor = "green";
        }
    }
})


//是否是目标元素的兄弟元素
function isBrother(target){
    return compareimg.parentElement.contains(target);
}
//是否是在目标元素的前面
function isPrev(target){
    var prev = compareimg.previousElementSibling;
    while(prev&&prev!==target){
        prev = prev.previousElementSibling;
    }
    return !!prev;
}
//是否是在目标元素的后面
function isNext(target){
    var next = compareimg.nextElementSibling;
    while(next&&next!==target){
        next = next.nextElementSibling;
    }
    return !!next;
}
document.body.addEventListener('click', function(e) {	
  let container = document.querySelector('#container');
  let compareImg = document.querySelector('#compareImg');
  let imgsInContainer = container.querySelectorAll('img');
  // 第2题
  let isImgDom = e.target.tagName === 'IMG';
  let target = e.target;
  // 第1题
  let isInContainer = selector(target.parentNode);
  if (isImgDom && isInContainer) {
	let arrs = [].slice.call(imgsInContainer);
	arrs.forEach(v => {
		v.style.outline = '0'
	});
	if (target.parentNode === compareImg.parentNode) {
		let children = [].slice.call(target.parentNode.children),
			targetIndex = 0,
			compareIndex = 0;
			children.forEach((v, i) => {
				if (v.tagName === 'IMG') {
					if (v === target && target !== compareImg) {
						targetIndex = i;
					} else if (v === compareImg && target !== compareImg) {
						compareIndex = i;
					}
				}
			});
			if (targetIndex < compareIndex) {
				target.style.outline = '2px solid red'
			} else  if (targetIndex > compareIndex){
				target.style.outline = '2px solid green'
			} else {
				target.style.outline = '2px solid'
			}
	} else {
		target.style.outline = '2px solid blue'
	}
};
}, false);
function selector(node) {
	if (node.id == 'container') {
		return true
	} else {
		if (node.tagName === 'BODY') {
			return false
		} else {
			return selector(node.parentNode);
		}
	}
}

看到楼上的,有很多特性都不知道,写的代码太啰嗦了。

crimx commented

@Molunerfinn Node.contains 学习了

	var imgs = document.getElementsByTagName('img');
	document.getElementsByTagName('body')[0].addEventListener('click',function(e){
		var boolInContainer = isChildren(e.target,'container');
		console.log(e.target.previousSibling)
		var boolImg = isImg(e.target)
		
		var outlineColor='';
		var targetImg = document.getElementById('compareImg')
		switch(relative(e.target,targetImg)){
			case 'prev':outlineColor='red';break;
			case 'next':outlineColor='green';break;
			case 'current':;break;
			default:outlineColor='blue';break;
		}

		if(boolInContainer && boolImg){
			e.target.style.outline = '2px solid '+outlineColor;
		}else{
			for(var i=0,len=imgs.length,item=imgs[0];i<len;i++,item=imgs[i]){
				item.style.outline = 'none';
			}
		}
	})

	function isChildren(elem,parentId){

		if(elem.parentNode.id == parentId){
			return true;
		}else if(elem.parentNode.nodeName == 'HTML'){
			return false;
		}else{
			return isChildren(elem.parentNode,parentId)
		}
	}
	function isImg(elem){
		if(elem.nodeName == 'IMG'){
			return true;
		}else{
			return false;
		}
	}

	// 判断与目标元素的关系
	function relative(elem,targetElem){
		if(elem == targetElem){
			return 'current';
		}else if(elem.parentNode !== targetElem.parentNode){
			return false;
		}else if(isNext(elem,targetElem)){
			return 'next';
		}else{
			return 'prev';
		}
	}
	// 判断是否为目标元素后面的兄弟元素
	function isNext(elem,targetElem){

		if(elem.previousElementSibling == null){
			return false;
		}else if(elem.previousElementSibling == targetElem){
			return true;
		}else{
			return isNext(elem.previousElementSibling,targetElem)
		}
	}
      let container = document.getElementById("container");
      let imgs = document.querySelectorAll("img");
      let basicOutline = "2px solid";
      //  点击页面,判断当前点击的元素是否是#container的子元素
      //   是否是img元素
      window.addEventListener("click", function(e) {
        let current = e.target;
        // 1,2同时满足,则当前设置当前img的outline,否则取消所有img的outline
        if (isChildElement(current)) {
          current.style.outline = getOutline(current);
        } else {
          for (let img of imgs) {
            img.style.outline = "none";
          }
        }
      });

      // 是否是子元素、img元素
      let isChildElement = el => {
        return el && container.contains(el) && el.tagName === "IMG";
      };
      
      // 根据位置获取outline样式
      let getOutline = el => {
        if (el.id === "compareImg") {
          return basicOutline;
        } else {
          let tmpEl = el.previousElementSibling;
          while (tmpEl) {
            if (tmpEl.id === "compareImg") {
              return "2px solid red";
            }
            tmpEl = tmpEl.previousElementSibling;
          }
          tmpEl = el.nextElementSibling;
          while (tmpEl) {
            if (tmpEl.id === "compareImg") {
              return "2px solid green";
            }
            tmpEl = tmpEl.nextElementSibling;
          }
        }
        return "2px solid blue";
      };

@Rsnowing 你的解法跟我的可真像啊

@Rsnowing 你的解法跟我的可真像啊
对呀,看着你的写的嘻嘻~~改了一点,比如说你的while循环里多次遍历到当前元素了

(function (doc) {
    var container = doc.getElementById('container');
    var aImg = container.getElementsByTagName('img');

    container.addEventListener('click', function (ev) {
        var ev = ev || window.event;
        var target = ev.target || ev.srcElement;
        if (target.tagName.toLowerCase() == 'img') {
            ev.stopPropagation();
            if (target.id === 'compareImg') {
                target.style.outline = "2px solid";
            } else if (isNext(target, 'compareImg')) {
                target.style.outline = "2px solid green";
            } else if (isPrev(target, 'compareImg')) {
                target.style.outline = "2px solid red";
            } else {
                target.style.outline = "2px solid blue";
            }
        }
    }, false)

    doc.addEventListener('click', function () {
        Array.prototype.slice.call(aImg).forEach(function (el) {
            el.style.outline = '';
        });
    }, false)

    //isNext
    function isNext(target, id) {
        while ((target = target.nextSibling)) {
            if (target.id === id) {
                return true
                break;
            }
        }
    }
    //isPrev
    function isPrev(target, id) {
        while ((target = target.previousSibling)) {
            if (target.id === id) {
                return true
                break;
            }
        }
    }
})(document)

在线demo

(function (window) {
    `use strict`

    function listener(e) {
        var path = Array.from(e.path), currentNode = path[0]

        // answer 1
        var isContainerChild = path
            .findIndex(node => node.id === 'container') >= 0


        // answer 2
        var isImgEle = /^img$/i.test(currentNode.tagName)


        // answer 3
        if (isContainerChild && isImgEle) {
            currentNode.style.outline = '2px solid'
        } else {
            Array.from(document.getElementsByTagName('img'))
                .map(node => node.style.outline = '')
        }

        // answer 4
        var compareImgNode = document.getElementById('compareImg')

        var nodeRelation = find(currentNode, compareImgNode)

        if (nodeRelation === 'prev') {
            currentNode.style.outlineColor = 'red'
        } else if (nodeRelation === 'next') {
            currentNode.style.outlineColor = 'green'
        } else if (nodeRelation === 'no_relation') {
            currentNode.style.outlineColor = 'blue'
        }

        // console result
        console.table([
            ['是否是 #container 的子元素', isContainerChild],
            ['是否是 img 元素', isImgEle],
        ])
    }

    function find(currentNode, compareImgNode) {

        var sameLevelNode = currentNode.parentNode.children

        if (currentNode === compareImgNode) {
            return 'same'
        }
        else if (currentNode.parentNode !== compareImgNode.parentNode) {
            return 'no_relation'
        } else {
            var currentNodePos = Array.from(sameLevelNode)
                .findIndex(node => node === currentNode)
            var compareImgNodePos = Array.from(sameLevelNode)
                .findIndex(node => node === compareImgNode)
            return currentNodePos < compareImgNodePos ? 'prev' : 'next'
        }
    }

    document.addEventListener('click', listener)
})(window)
document.addEventListener('click', e => {
    // 第一题
    const isChild = document.querySelector('#container').contains(e.target)
    // 第二题
    const isImg = e.target.nodeName === 'IMG'
    // 第三题
    if (isChild && isImg) {
        e.target.style.outline = '2px solid'
    } else {
        Array.from(document.querySelectorAll('img')).forEach(el => el.style.outline = '')
    }
    // 第四题
    const position = document.querySelector('#compareImg').compareDocumentPosition(e.target)
    if (position === 0) {
        // 自己
    } else if (position & Node.DOCUMENT_POSITION_PRECEDING) {
        // 前
        e.target.style.outlineColor = 'red'
    } else if (position & Node.DOCUMENT_POSITION_FOLLOWING) {
        // 后
        e.target.style.outlineColor = 'green'
    } else {
        // 其它
        e.target.style.outlineColor = 'blue'
    }
})

compareDocumentPosition() 方法比较两个节点,并返回描述它们在文档中位置的整数。

请看上面的例子。返回值可能是:

0:当前节点。

1:没有关系,两个节点不属于同一个文档。

2:第一节点(P1)位于第二个节点后(P2)。

4:第一节点(P1)定位在第二节点(P2)前。

8:第一节点(P1)位于第二节点内(P2)。

16:第二节点(P2)位于第一节点内(P1)。

32:没有关系,或是两个节点是同一元素的两个属性。

注释:返回值可以是值的组合。例如,返回 20 意味着在 p2 在 p1 内部(16),并且 p1 在 p2 之前(4)。

@hollowtree 这个简直太棒了吧 ~

有个疑问,感觉两个图片元素之间应该没有除了前、后、自身之外的关系了吧?因此对题目中的 blue 有些不太理解。
还有,blue 没有排除自己,不过依上下文,应该是不包含自己的的?

@IceyTea 谢谢~

document.addEventListener('click', e => {
    // 第一题
    const isChild = document.querySelector('#container').contains(e.target)
    // 第二题
    const isImg = e.target.nodeName === 'IMG'
    // 第三题
    if (isChild && isImg) {
        e.target.style.outline = '2px solid'
    } else {
        Array.from(document.querySelectorAll('img')).forEach(el => el.style.outline = '')
    }
    // 第四题
    const position = document.querySelector('#compareImg').compareDocumentPosition(e.target)
    if (position === 0) {
        // 自己
    } else if (position & Node.DOCUMENT_POSITION_PRECEDING) {
        // 前
        e.target.style.outlineColor = 'red'
    } else if (position & Node.DOCUMENT_POSITION_FOLLOWING) {
        // 后
        e.target.style.outlineColor = 'green'
    } else {
        // 其它
        e.target.style.outlineColor = 'blue'
    }
})

666

大概想法

1、直接使用事件代理,点击的一定#container的子元素或本身;
2、使用tagName判断是否为img标签;
3、getOutLineColor函数用于获取outline的颜色:

  • 点击图片或比较的图片不在DOM树中了,则无法确定前后关系;
  • 点击和比较的图片是兄弟元素,直接比较;
  • 如果不是,一直向上查找到第一个共同的祖先下各自所属的子元素,比较前后;

4、给document绑定click时候,当点击的不是#container时,才会响应调用clearImgsOutLine。

const container = document.getElementById("container")
const compareImg = container.querySelector("#compareImg")
let hasOutLineImgs = []

function clearImgsOutLine() {
    hasOutLineImgs.forEach((img) => { img.outlineColor = img.style.outline = 'none' })
    hasOutLineImgs.splice(0)
}

function getParentsNumber (element) {
    return element.tagName.toLowerCase() === 'body' ? 0 : (getParentsNumber(element.parentElement) + 1)
}

function getParentByNum (target,parentNum,currentMun) {
    let parentElement = target
    while (currentMun-- >= parentNum) {
        parentElement = parentElement.parentElement
    }
    return parentElement
}
function getOutLineColor (target,compareImg) {
    if (!target.parentElement || !compareImg.parentElement) {
        return 'blue'
    }
    if(target.parentElement === compareImg.parentElement) {
        if (target === compareImg) {
            return ''
        }
        let childrens = Array.from(target.parentElement.children)
        return childrens.indexOf(target) < childrens.indexOf(compareImg) ? 'red' : 'green'
    }
    let targetParentsNumber = getParentsNumber(target)
    let compareImgParentsNumber = getParentsNumber(compareImg)
    let minParentsNumber = Math.min(targetParentsNumber,compareImgParentsNumber)
    let sameLayerParent = {
            target:getParentByNum(target,minParentsNumber,targetParentsNumber),
            compareImg:getParentByNum(compareImg,minParentsNumber,compareImgParentsNumber)
        }
    if (sameLayerParent.target === sameLayerParent.compareImg) {
        return getOutLineColor(getParentByNum(target,minParentsNumber,targetParentsNumber -1), getParentByNum(compareImg,minParentsNumber,compareImgParentsNumber - 1))
    } else {
        return getOutLineColor(sameLayerParent.target,sameLayerParent.compareImg)
    }
}

container.addEventListener('click',(event)=>{
    let target = event.target
    if (event.target.tagName.toLowerCase() === 'img' && compareImg !== target) {
        let outlineColor = getOutLineColor(target,compareImg)
        let oldOutlineColor = hasOutLineImgs.includes(target) && hasOutLineImgs[hasOutLineImgs.indexOf(target)].outlineColor
        if (!hasOutLineImgs.includes(target) || oldOutlineColor !== outlineColor) {   
            target.style.outline = `${outlineColor} 2px solid`
            target.outlineColor = outlineColor // 颜色保存,防止颜色未改变也修改style
            !hasOutLineImgs.includes(target) && hasOutLineImgs.push(target) // 防止多次push同一个元素
        }
    }
    event.stopPropagation() 
    return false
})
document.addEventListener('click',clearImgsOutLine)

大家的方法都很简洁,我写的好复杂,学习了

var container = document.getElementById('container')
container.addEventListener('click', function(e) {
  var event = e || window.event
  var target = event.target
  // 是否为子标签
  var isChildOfContainer = isChildOf(target, container)
  // 是否为图片标签
  var isImg = isClickImg(target)
  // 1
  if (isChildOfContainer) {
    console.log('点击的是container的子标签')
  } else {
    console.log('点击的不是container的子标签')
  }
  // 2
  if (isImg) {
    console.log('点击是图片')
  } else {
    console.log('点击的不是图片')
  }
  // 4 根据出现的位置设置outline
  var compareImg = document.getElementById('compareImg')
  var pos = target.compareDocumentPosition(compareImg)
  var outlineColor = ''
  if (pos & 0) {
    outlineColor = ''
  } else if (pos & Node.DOCUMENT_POSITION_PRECEDING) {
    outlineColor = 'red'
  } else if (pos & Node.DOCUMENT_POSITION_FOLLOWING) {
    outlineColor = 'green'
  }
  //3 既是子标签又是图片设置outline,否则清空所有img 的outline
  if (isChildOfContainer && isImg) {
    target.style.outline = '2px solid ' + outlineColor
  } else {
    var imgs = document.getElementsByTagName('img')
    Array.from(imgs).forEach((img) => {
      img.style.outline = ''
    })
  }
})
// 判断一个标签是否包含另一个标签,从里往外找一直找到body标签
function isChildOf (child, parent) {
  while (!!child && child.nodeName !== 'BODY') {
    if (child === parent) {
      return true
    } else {
      child = child.parentNode
    }
  }
  return false
}
// 判断点击的是否是img标签
function isClickImg(target){
  return target.nodeName === 'IMG'
}
document.addEventListener('click', function(event) {
            let target = event.target;
            let ElementContainer = findParentElement(target, '#container');
            let isImg = isTag(target, 'img');
            if (ElementContainer && isImg) {
                target.style.outline = '2px solid';
            } else {
                document.querySelectorAll('img').forEach(node => {
                    node.style.outline = '';
                })
            }
            let compareElement = document.querySelector('#compareImg');
            let atPlaceStr = atPlace(target, compareElement);
            if (atPlaceStr === 'next') {
                target.style.outlineColor = 'green';
            } else if(!atPlaceStr) {
                target.style.outlineColor = 'blue';
            }
        })

        function findParentElement(self, parentName) {
            let parentElement = self.parentElement;
            if (parentElement === null) return null;
            let target = resolveParent(parentName);
            let res = null;
            while(parentElement) {
                if(parentElement[target[0]] === target[1]) {
                    res = parentElement;
                    break;
                } else {
                    parentElement = parentElement.parentElement;
                }
            }
            return res;
            function resolveParent(parent) {
                if (Object.prototype.toString.call(parent) !== '[object String]') {
                    return ;
                } else {
                    let firstLetter = parent.charAt(0);
                    switch (firstLetter) {
                        case '#':
                            return ['id', parent.slice(1)]
                            break;
                        case '.':
                            return ['className', parent.slice(1)]
                            break;
                        default:
                            return ['tagName', parent.toUpperCase()]
                            break;
                    }
                }
            }
        }

        function isTag(target, tagName) {
            return target.tagName === tagName.toUpperCase();
        }

        function atPlace(targetElement, element) {
            let atNextStr = atNext(targetElement, element);
            let atPrevStr = atPrev(targetElement, element);

            return atNextStr || atPrevStr
        }

        function atNext(targetElement, element) {
            let previousElementSibling = targetElement.previousElementSibling;
            let res = null;
            while (previousElementSibling) {
                if (previousElementSibling === element) {
                    res = 'next';
                    break;
                } else {
                    previousElementSibling = previousElementSibling.previousElementSibling;
                }
            }
            return res;
        }
        function atPrev(targetElement, element) {
            let nextElementSibling = targetElement.nextElementSibling;
            let res = null;
            while (nextElementSibling) {
                if (nextElementSibling === element) {
                    res = 'prev';
                    break;
                } else {
                    nextElementSibling = nextElementSibling.nextElementSibling;
                }
            }
            return res;
        }
   window.onclick = function(e){
       let iscon = checkElement(e.target)
       let isImg = checkImg(e.target)
       let imgs = document.getElementsByTagName("img")
       let color = "blue"
       let tagindex = -1
       let targetindex = -1
       if(isImg){
         let imgEle = e.target.parentNode.children
         let imgAlt = Array.from(imgEle).map((item,index )=> {
           if(item.alt == e.target.alt){
             tagindex = index
           }
           if(item.alt == "示意图3"){
             targetindex = index
           }
           return item.alt
         })
         if(targetindex>0&&targetindex>tagindex){
           color = "red"
         }else if(targetindex>0&&targetindex<tagindex){
          color = "green"
         }else if(targetindex==tagindex){
          color = "#000"
         }
       }
       if(iscon&&isImg){
         e.target.style.outline = `2px solid ${color}`
       }else{
         Array.from(imgs).map(item=>{
          item.style.outline = ''
         })
       }
    }
    function parent(ele){
      return ele.parentNode
    }
    function checkElement(ele){
      if(ele.tgName=="BODY" || ele.tagName=="HTML"){
        alert('当前点击元素不是#container的子元素')
        return false
      }
      let element = parent(ele)
      if(element.id=="container"){
        alert('当前点击元素是#container的子元素')
        return true;
      }else if(element.tagName=="BODY"){
        alert('当前点击元素不是#container的子元素')
        return false
      }else{
        return checkElement(element)
      }
    }

    function checkImg(ele){
      if(ele.tagName == 'IMG'){
        alert('当前点击元素是img元素')
        return true
      }else{
        alert('当前点击元素不是img元素')
        return false
      }
    }

有个疑问,感觉两个图片元素之间应该没有除了前、后、自身之外的关系了吧?因此对题目中的 blue 有些不太理解。
还有,blue 没有排除自己,不过依上下文,应该是不包含自己的的?

@IceyTea 谢谢~

有其他关系,比如说iframe内其他图片

  1. 包含关系推荐使用contains方法;
  2. 判断当前元素是否是IMG,可以 :
    event.target.tagName/nodeName == 'IMG'
    /^img$/i.test(event.target.tagName)
    event.target.tagName.toLowerCase() == 'img'
    event.target instanceof Image
  3. 前后节点关系判断,Node.compareDocumentPosition()
window.addEventListener('click', e => {
     const {target} = e;
     const container = document.getElementById('container');
     const compareImg = document.getElementById('compareImg');

     if (container.contains(target) && target.localName == 'img') {
       let color = '';
       if (compareImg.parentNode.contains(target)) {
         switch (compareImg.compareDocumentPosition(target)) {
           case 0: break;
           case 2: color = 'red'; break;
           case 4: color = 'green'; break;
         }
       } else {
         color = 'blue'
       }
       target.style.outline = `2px solid ${color}`;
     } else {
       document.querySelectorAll('img').forEach(e => {
         e.style.outline = 'none';
       })
     }
   })
(function (doc) {
    var container = doc.getElementById('container');
    var aImg = container.getElementsByTagName('img');

    container.addEventListener('click', function (ev) {
        var ev = ev || window.event;
        var target = ev.target || ev.srcElement;
        if (target.tagName.toLowerCase() == 'img') {
            ev.stopPropagation();
            if (target.id === 'compareImg') {
                target.style.outline = "2px solid";
            } else if (isNext(target, 'compareImg')) {
                target.style.outline = "2px solid green";
            } else if (isPrev(target, 'compareImg')) {
                target.style.outline = "2px solid red";
            } else {
                target.style.outline = "2px solid blue";
            }
        }
    }, false)

    doc.addEventListener('click', function () {
        Array.prototype.slice.call(aImg).forEach(function (el) {
            el.style.outline = '';
        });
    }, false)

    //isNext
    function isNext(target, id) {
        while ((target = target.nextSibling)) {
            if (target.id === id) {
                return true
                break;
            }
        }
    }
    //isPrev
    function isPrev(target, id) {
        while ((target = target.previousSibling)) {
            if (target.id === id) {
                return true
                break;
            }
        }
    }
})(document)

在线demo

(function (doc) {
    var container = doc.getElementById('container');
    var aImg = container.getElementsByTagName('img');

    container.addEventListener('click', function (ev) {
        var ev = ev || window.event;
        var target = ev.target || ev.srcElement;
        if (target.tagName.toLowerCase() == 'img') {
            ev.stopPropagation();
            if (target.id === 'compareImg') {
                target.style.outline = "2px solid";
            } else if (isNext(target, 'compareImg')) {
                target.style.outline = "2px solid green";
            } else if (isPrev(target, 'compareImg')) {
                target.style.outline = "2px solid red";
            } else {
                target.style.outline = "2px solid blue";
            }
        }
    }, false)

    doc.addEventListener('click', function () {
        Array.prototype.slice.call(aImg).forEach(function (el) {
            el.style.outline = '';
        });
    }, false)

    //isNext
    function isNext(target, id) {
        while ((target = target.nextSibling)) {
            if (target.id === id) {
                return true
                break;
            }
        }
    }
    //isPrev
    function isPrev(target, id) {
        while ((target = target.previousSibling)) {
            if (target.id === id) {
                return true
                break;
            }
        }
    }
})(document)

在线demo

你这个写反了吧,应该是这样吧?

function isNext(target, compareImg) {
  do {
    if (target.id === compareImg.id) {
      return true
      break;
    }
  } while (target = target.previousSibling)
}

function isPrev(target, compareImg) {
  do {
    if (target.id === compareImg.id) {
      return true
      break;
    }
  } while (target = target.nextSibling)
  return isPrev
}