2

假设我有一条消息说“你好!” 我将每个单独的角色(不包括空格)包装在一个跨度中,我必须这样做,因为我正在使用animeJS并且想要为角色设置动画。问题是消息的动画效果很好,但是由于每个角色都在自己的范围内,因此在奇怪的部分中断/换行。例如,它看起来像“Hello t /n here!”,所以它在 t 和 h 之间中断。我只希望它在有空格而不是跨度的情况下中断。

排除所有样式类的 html 代码如下所示:

<div>
<span>H</span>
<span>e</span>
<span>l</span>
<span>l</span>
<span>o</span>
<div> </div>
<span>T</span>
<span>h</span>
<span>e</span>
<span>r</span>
<span>e</span>
<span>!</span>
</div>

上面的代码是我创建的以下函数的结果:

const addSpan = (note: any, styles: any) => {
  let note1 = note.replace(/./g, `<span class='letter' style=${styles}>$&</span>`);
  let note2 = note1.replace(/<span class='letter' style=display:inline-block;> <\/span>/g, `<div> </div>`);
  return DOMPurify.sanitize(
    note2
  );
};

我试图在空格之间添加一个 div,但它会导致我不想要的换行符。我只希望消息只在空格处而不是跨度处中断。我应该对空格包装器进行哪些更改?

我不确定我所要求的是否可能,有什么帮助吗?

编辑:到目前为止所有的答案都不理解我的要求。我只希望我的信息在空白处中断,而不是在跨度之间。尽管所有字母都在单独的跨度中,但我希望我的“你好”和“那里”保持在一起。

4

1 回答 1

1

字母应该是跨度,单词应该是内嵌块。

我什至增加了对段落的支持。

const text = `
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
`

const main = () => {
  render(text, '.target')
}

const render = (text, target) => {
  if (typeof target === 'string') {
    target = document.querySelector(target)
  }
  removeChildren(target)
  text.trim().split(/\n/g).forEach((paragraph, pIndex, pArr) => {
    let paragraphEl = document.createElement('div')
    paragraphEl.classList.add('paragraph')
    paragraph.split(/\s+/g).forEach((word, wIndex, wArr) => {
      let wordEl = document.createElement('div')
      wordEl.classList.add('word')
      word.split('').forEach((letter, lIndex, lArr) => {
        let letterEl = document.createElement('span')
        letterEl.classList.add('letter')
        letterEl.textContent = letter
        wordEl.appendChild(letterEl)
      })
      paragraphEl.appendChild(wordEl)
      if (wIndex < wArr.length) {
        let spaceEl = document.createElement('span')
        spaceEl.classList.add('space')
        spaceEl.innerHTML = '&nbsp;'
        paragraphEl.appendChild(spaceEl)
      }
    })
    target.appendChild(paragraphEl)
  })
}

const removeChildren = (el) => {
  while (el.firstChild) {
    el.firstChild.remove()
  }
}

main()
.target {
  width: 20em;
  overflow: hidden;
  border: thin solid grey;
}

.paragraph {
  margin: 0.33em 0.5em;
}

.word {
  display: inline-block;
}

.word:hover {
  background: #FFA;
}
<div class="target"></div>


简化的 DOM 树示例

这只是演示创建元素流程的一种有趣方式。

const text = `
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
`

const main = () => {
  render(text, '.page')
}

const render = (text, target) => {
  appendChildren(target, text.trim().split(/\n/g).map(
    (paragraph, pIndex, pArr) => {
    return {
      tag: 'div',
      options: {
        class: 'paragraph',
        data: { paragraphIndex : pIndex },
        children: paragraph.split(/\s+/g).reduce(
            (children, word, wIndex, wArr) => {
          children.push({
            tag: 'div',
            options: {
              class: 'word',
              children: word.split('').map((letter) => {
                return {
                  tag: 'span',
                  options: {
                    class: 'letter',
                    text: letter
                  }
                }
              })
            }
          })
          if (wIndex < wArr.length) {
            children.push({
              tag: 'span',
              options: {
                classes: [ 'letter', 'space' ],
                html: '&nbsp;'
              }
            })
          }
          return children
        }, [])
      }
    }
  }), {
    empty: true
  })
}

const createEl = (tag, options) => {
  if (typeof tag !== 'string') {
    options = tag.options
    tag = tag.tag
  }
  let opts = {
    id: null,
    class: null,
    classes: [],
    props: {},
    attrs: {},
    data: {},
    text: null,
    html: null,
    parent: null,
    children: [],
    ...options
  }
  let el = document.createElement(tag)
  if (opts.id) el.id = opts.id
  if (opts.class) el.className = opts.class
  if (opts.classes) el.classList.add(...opts.classes)
  Object.keys(opts.props).forEach(prop => el[prop] = opts.props[prop])
  Object.entries(opts.attrs).forEach(attr => el.setAttribute.call(el, attr))
  Object.assign(el.dataset, opts.data)
  if (opts.text) el.textContent = opts.text
  if (opts.html) el.innerHTML = opts.html
  if (opts.parent) query(opts.parent).appendChild(el)
  if (opts.children) appendChildren(el, opts.children)
  return el
}

const appendChildren = (el, children, options) => {
  let opts = {
    empty: false,
    ...options
  }
  el = el == null ? document.body : query(el)
  if (opts.empty) emptyEl(el)
  children.forEach(child => {
    if (isDomEntity(child)) {
      el.appendChild(child)
    } else {
      let childEl = createEl(child.tag, child.options)
      if (child.options.parent == null) {
        el.appendChild(childEl)
      }
    }
  })
}

const query = (selector) => {
  return typeof selector === 'string' ?
    document.querySelector(selector) : selector
}

const emptyEl = el => {
  while (el.firstChild) {
    el.firstChild.remove()
  }
  return el
}

const isDomEntity = entity => {
  return typeof entity === 'object' && entity.nodeType !== undefined
}

main()
.page {
  width: 20em;
  overflow: hidden;
  border: thin solid grey;
}

.paragraph {
  margin: 0.33em 0.5em;
}

.word {
  display: inline-block;
}

.word:hover {
  background: #FFA;
}
<div class="page">Loading...</div>

于 2020-07-09T20:43:34.967 回答