如何使React应用中的常规JavaScript工作

时间:2019-03-30 22:59:45

标签: javascript reactjs

嗨,我正在尝试将此文本设置为scrable https://codepen.io/soulwire/pen/mErPAK/?editors=1010 在我的React应用程序中,但是我收到错误TypeError:无法读取null的属性“ innerText”。

   9 |   this.update = this.update.bind(this)
  10 | }
  11 | setText(newText) {
> 12 |   const oldText = this.el.innerText
  13 |   const length = Math.max(oldText.length, newText.length)
  14 |   const promise = new Promise(resolve => (this.resolve = resolve))
  15 |   this.queue = []

到目前为止,这是我所做的 https://codesandbox.io/s/oxm38v7x9y

  1. 创建了新组件scrable.js
  2. 从代码笔中移出了代码
  3. 导入到index.js

您无需修复codeandbox,仅需一点提示即可:)

import React, { Component } from "react"

export default class Scrable extends Component {
  render() {
    const phrases = [
      "Neo,",
      "sooner or later",
      "you're going to realize",
      "just as I did",
      "that there's a difference",
      "between knowing the path",
      "and walking the path",
    ]
    const el = document.querySelector(".text")
    const fx = new TextScramble(el)
    console.log(el)
    let counter = 0
    const next = () => {
      fx.setText(phrases[counter]).then(() => {
        setTimeout(next, 800)
      })
      counter = (counter + 1) % phrases.length
    }
    next()
    return (
      <TextScramble>
        <div className="text" />
      </TextScramble>
    )
  }
}

export class TextScramble extends Component {
  constructor(el) {
    super()
    this.el = el
    this.chars = "!<>-_\\/[]{}—=+*^?#________"
    this.update = this.update.bind(this)
  }
  setText(newText) {
    const oldText = this.el.innerText
    const length = Math.max(oldText.length, newText.length)
    const promise = new Promise(resolve => (this.resolve = resolve))
    this.queue = []
    for (let i = 0; i < length; i++) {
      const from = oldText[i] || ""
      const to = newText[i] || ""
      const start = Math.floor(Math.random() * 40)
      const end = start + Math.floor(Math.random() * 40)
      this.queue.push({ from, to, start, end })
    }
    cancelAnimationFrame(this.frameRequest)
    this.frame = 0
    this.update()
    return promise
  }
  update() {
    let output = ""
    let complete = 0
    for (let i = 0, n = this.queue.length; i < n; i++) {
      let { from, to, start, end, char } = this.queue[i]
      if (this.frame >= end) {
        complete++
        output += to
      } else if (this.frame >= start) {
        if (!char || Math.random() < 0.28) {
          char = this.randomChar()
          this.queue[i].char = char
        }
        output += `<span class="dud">${char}</span>`
      } else {
        output += from
      }
    }
    this.el.innerHTML = output
    if (complete === this.queue.length) {
      this.resolve()
    } else {
      this.frameRequest = requestAnimationFrame(this.update)
      this.frame++
    }
  }
  randomChar() {
    return this.chars[Math.floor(Math.random() * this.chars.length)]
  }
  render() {
    return <div />
  }
}

1 个答案:

答案 0 :(得分:0)

大家好,谢谢您的评论

我能够使它工作。这是我的下面的代码。欢迎任何建议

我不完全确定这是正确的方法,但是它能起作用

import React, { Component } from 'react'

export default class Scrable extends Component {
  constructor(el) {
    super(el)
    this.el = el
    this.chars = "!<>-_\\/[]{}—=+*^?#________"
    // this.update = this.update.bind(this)
  }
  componentDidMount(){
    const phrases = [
      'Neo,',
      'sooner or later',
      'you\'re going to realize',
      'just as I did',
      'that there\'s a difference',
      'between knowing the path',
      'and walking the path'
    ]

    const el = document.querySelector('.text')
    const fx = new TextScramble(el)

    let counter = 0
    const next = () => {
      fx.setText(phrases[counter]).then(() => {
        setTimeout(next, 800)
      })
      counter = (counter + 1) % phrases.length
    }

    next()
    console.log(el)
  }
  render() {
    const phrases = [
      "Neo,",
      "sooner or later",
      "you're going to realize",
      "just as I did",
      "that there's a difference",
      "between knowing the path",
      "and walking the path",
    ]

    return (
      <div>
        <div className="text">text</div>
      </div>
    )
  }
}

class TextScramble {
  constructor(el) {
    this.el = el
    this.chars = '!<>-_\\/[]{}—=+*^?#________'
    this.update = this.update.bind(this)
    console.log(this)
  }
  setText(newText) {
    const oldText = this.el.innerText
    const length = Math.max(oldText.length, newText.length)
    const promise = new Promise((resolve) => this.resolve = resolve)
    this.queue = []
    for (let i = 0; i < length; i++) {
      const from = oldText[i] || ''
      const to = newText[i] || ''
      const start = Math.floor(Math.random() * 40)
      const end = start + Math.floor(Math.random() * 40)
      this.queue.push({ from, to, start, end })
    }
    cancelAnimationFrame(this.frameRequest)
    this.frame = 0
    this.update()
    return promise
  }
  update() {
    let output = ''
    let complete = 0
    for (let i = 0, n = this.queue.length; i < n; i++) {
      let { from, to, start, end, char } = this.queue[i]
      if (this.frame >= end) {
        complete++
        output += to
      } else if (this.frame >= start) {
        if (!char || Math.random() < 0.28) {
          char = this.randomChar()
          this.queue[i].char = char
        }
        output += `<span class="dud">${char}</span>`
      } else {
        output += from
      }
    }
    this.el.innerHTML = output
    if (complete === this.queue.length) {
      this.resolve()
    } else {
      this.frameRequest = requestAnimationFrame(this.update)
      this.frame++
    }
  }
  randomChar() {
    return this.chars[Math.floor(Math.random() * this.chars.length)]
  }
}