code: function bindEvents (ctx, evts, attrs, tag, appearAttached) {
    for (const key in evts) {
      const appearEvtName = appearEventsMap[key]
      if (appearEvtName) {
        attrs[`data-evt-${appearEvtName}`] = ''
        if (!appearAttached.value) {
          appearAttached.value = true
          attrs['weex-appear'] = ''
        }
      }
      else {
        attrs[`data-evt-${key}`] = ''
        if (key !== 'click') {
          // should stop propagation by default.
          // TODO: should test inBubble first.
          const handler = evts[key]
          if (isArray(evts[key])) {
            handler.unshift(ctx.$stopPropagation)
          }
          else {
            evts[key] = [ctx.$stopPropagation, handler]
          }
        }
      }
    }
    if (evts.click) {
      evts.weex$tap = evts.click
      evts.click = ctx.$stopOuterA
    }
    if (evts.scroll) {
      evts.weex$scroll = evts.scroll
      delete evts.scroll
    }
  }
docs: Tell whether a element is contained in a element who has
  a attribute 'bubble'=true.
  @param {HTMLElement} el
   function inBubble (el) { if (typeof el._inBubble === 'boolean') { return el._inBubble } const parents = [] let parent = el.parentElement let inBubble while (parent && parent !== document.body) { if (typeof parent._inBubble === 'boolean') { inBubble = parent._inBubble break } const attr = parent.getAttribute('bubble') if (attr !== '') { inBubble = attr === true || attr === 'true' break } parents.push(parent) parent = parent.parentElement } el._inBubble = inBubble for (let i = 0, l = parents.length; i < l; i++) { parents[i]._inBubble = inBubble } return inBubble }