我正在尝试重新加载我的main.js
组件,但是第一次加载时它仅加载一次。
当第一次加载组件时,我的文本动画效果很好,但是当我访问不同的路线并再次访问该组件时,文本动画会停止。
class Main extends Component {
typeWriter() {
var TxtRotate = function (el, toRotate, period) {
this.toRotate = toRotate;
this.el = el;
this.loopNum = 0;
this.period = parseInt(period, 10) || 2000;
this.txt = '';
this.tick();
this.isDeleting = false;
};
TxtRotate.prototype.tick = function () {
var i = this.loopNum % this.toRotate.length;
var fullTxt = this.toRotate[i];
if (this.isDeleting) {
this.txt = fullTxt.substring(0, this.txt.length - 1);
} else {
this.txt = fullTxt.substring(0, this.txt.length + 1);
}
this.el.innerHTML = '<span class="wrap">' + this.txt + '</span>';
var that = this;
var delta = 300 - Math.random() * 100;
if (this.isDeleting) { delta /= 2; }
if (!this.isDeleting && this.txt === fullTxt) {
delta = this.period;
this.isDeleting = true;
} else if (this.isDeleting && this.txt === '') {
this.isDeleting = false;
this.loopNum++;
delta = 500;
}
setTimeout(function () {
that.tick();
}, delta);
};
window.onload = function () {
var elements = document.getElementsByClassName('txt-rotate');
for (var i = 0; i < elements.length; i++) {
var toRotate = elements[i].getAttribute('data-rotate');
var period = elements[i].getAttribute('data-period');
if (toRotate) {
new TxtRotate(elements[i], JSON.parse(toRotate), period);
}
}
// INJECT CSS
var css = document.createElement("style");
css.type = "text/css";
css.innerHTML = ".txt-rotate > .wrap { border-right: 0.08em solid #666 }";
document.body.appendChild(css);
};
}
componentDidMount() {
this.typeWriter();
}
render() {
return (
<div id="main" >
<h2 id="typeWrite" className="mt-4 mb-5">I'm a
<span className="txt-rotate" data-period="2000" data-rotate='[ " Developer.", " Programmer."]'></span>
</h2>
</div>
)
}
}
export default Main;
如何使其重新加载此组件加载?
答案 0 :(得分:2)
使用React有状态组件来呈现类型编写器效果,不要像使用typeWriter()
方法那样尝试“突破” React。我在下面使用功能组件和React钩子编写了一个功能齐全的演示:
const { useRef, useState, useReducer, useMemo, useEffect } = React;
const typeWriterInitialState = {
index: 0,
deleting: false,
length: 0
};
const typeWriterReducer = (state, action) => {
const { index, deleting, length } = state;
const { text, fullText } = action;
if (deleting && text === '') return {
index: index + 1,
deleting: false,
length: length + 1
};
if (!deleting && text === fullText) return {
index: index,
deleting: true,
length: length - 1
};
return {
index,
deleting,
length: length + (deleting ? -1 : 1)
};
};
function useTypeWriter (props) {
const ref = useRef(null);
const [period] = useState(props.period || 2000);
const [rotate] = useState(props.rotate);
const [state, update] = useReducer(
typeWriterReducer,
typeWriterInitialState
);
const { index, deleting, length } = state;
const fullText = rotate[index % rotate.length];
const text = fullText.substring(0, length);
const delta = useMemo(() => {
if (text === fullText && !deleting) return period;
if (text === '' && deleting) return 500;
return (200 * Math.random() + 100) * (deleting ? 0.5 : 1);
}, [text, fullText, deleting, period]);
useEffect(() => {
ref.current.textContent = text;
const timeout = setTimeout(update, delta, { text, fullText });
return () => {
clearTimeout(timeout);
};
}, [ref, delta, text, fullText, update]);
return ref;
}
const wrapStyle = { borderRight: '0.08em solid #666' };
function TypeWriter (props) {
const { period, rotate } = props;
const wrapEl = useTypeWriter({ period, rotate });
return (
<span ref={wrapEl} style={wrapStyle}/>
);
}
const mainRotate = ['Developer.', 'Programmer.'];
function Main () {
return (
<div>
<h2>I'm a <TypeWriter period={2000} rotate={mainRotate}/></h2>
</div>
);
}
ReactDOM.render(<Main/>, document.body);
h2 {
white-space: pre-wrap;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>