Laravel Vue中使用TextScrambler组件报错:length未定义求助
解决Vue组件中使用TextScrambler包的"TypeError: Cannot read property 'length' of undefined"错误
嘿,我仔细看了你的代码,很快就发现了问题所在——这是几个常见的小失误导致的,让我一步步帮你解决:
问题根源
- 变量名不匹配:你在
randomChar方法里使用this.chars来获取随机字符集,但组件props里定义的字符集属性是scrambleCharacterSet,根本不存在chars这个属性!当代码尝试访问this.chars.length时,this.chars是undefined,直接抛出了你看到的错误。 - 未处理undefined边界情况:监听
text变化时,第一次触发的oldValue可能是undefined,直接拼接字符串会出问题;同时props的text没有设置默认值,初始状态也可能是undefined。 - 导入路径可能错误:你写了
import TextScrambler from 'text-scrambler',但看起来你是自己写了同名本地组件,这会导致导入冲突。
修复步骤
1. 修正字符集变量名
把randomChar方法里的this.chars全部替换成this.scrambleCharacterSet,和props定义的属性名保持一致。
2. 处理undefined的边界情况
- 在watch的
text监听回调里,把oldValue替换成oldValue || '',避免undefined参与字符串操作; - 给props的
text添加默认值,确保初始状态不会是undefined。
3. 修正组件导入路径
把导入语句改成本地组件的路径(比如./TextScrambler.vue),避免和npm包冲突。
修复后的完整代码
TextScrambler.vue
<template> <span>{{ tweenedValue }}</span> </template> <script> export default { name: 'TextScrambler', data() { return { queue: [], tweenedValue: '', frame: 0, frameRequest: null } }, watch: { text(newValue, oldValue) { // 处理oldValue可能为undefined的情况 this.setText(oldValue || '', `${newValue}`) } }, mounted() { if (this.disableInitialScramble) { this.tweenedValue = `${this.text}` } else { // 初始调用用空字符串作为旧值,逻辑更清晰 this.setText('', `${this.text}`) } }, props: { text: { type: String, default: '' // 添加默认值,避免初始undefined }, disableInitialScramble: { type: Boolean, default: false }, scrambleDuration: { type: Number, default: 20 }, scrambleCharacterSet: { type: String, default: '!<>-_\\/[]{}—=+*^?#________' } }, methods: { setText(oldText, newText) { const length = Math.max(oldText.length, newText.length) this.queue = [] for (let i = 0; i < length; i++) { const from = oldText[i] || '' const to = newText[i] || '' const start = Math.floor(Math.random() * this.scrambleDuration) const end = start + Math.floor(Math.random() * this.scrambleDuration) this.queue.push({ from, to, start, end }) } cancelAnimationFrame(this.frameRequest) this.frame = 0 this.update() }, randomChar() { // 修正为props定义的scrambleCharacterSet return this.scrambleCharacterSet[Math.floor(Math.random() * this.scrambleCharacterSet.length)] }, 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 += char } else { output += from } } this.tweenedValue = output if (complete !== this.queue.length) { this.frameRequest = requestAnimationFrame(this.update) this.frame++ } } } } </script>
调用组件的代码
<template> <TextScrambler :text="text" /> </template> <script> // 修正为本地组件的正确路径 import TextScrambler from './TextScrambler.vue' export default { layout: 'basic', components: { TextScrambler }, data() { return { text: Math.random().toString(36).substring(7) } }, } </script>
内容的提问来源于stack exchange,提问作者Alit Indrawan
相关产品推荐
相关产品推荐

