【发布时间】:2018-12-07 19:23:53
【问题描述】:
我想确保这个 Vue 应用程序的用户只在输入框中输入格式正确的货币值。为此,我添加了一个正则表达式测试,以确保用户只能输入格式正确的值。根据我在网上为 JavaScript 找到的一堆不同的 Regex 测试人员,Regex 可以正常工作。当我在开发环境中运行应用程序时,一切正常。
但是,当我使用npm run build 并使用应用程序的缩小版时,在输入框中输入非数字会导致网络浏览器崩溃。 Windows 任务管理器显示该特定选项卡的 CPU 使用率急剧上升。使用 Chrome 调试器时,看起来任何非数字字符都会导致应用程序进入无限循环。但是,在非缩小版本中不会发生这种情况。
要重现问题,请使用 Vue CLI 创建一个新的 Vue 项目。编辑 App.vue 文件,如下所示:
<template>
<div id="app">
<Reporting/>
</div>
</template>
<script>
import Reporting from './components/Reporting'
export default {
name: 'app',
components: {
Reporting
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
编辑 main.js 文件,如下所示:
import Vue from 'vue'
import Vue2Filters from 'vue2-filters'
import App from './App.vue'
Vue.config.productionTip = false
Vue.use(Vue2Filters)
new Vue({
render: h => h(App),
}).$mount('#app')
您需要安装 vue2-filters,因此请使用 npm install --save vue2-filters 进行安装。
添加这个 Reporting.vue 组件:
<template>
<div id="Reporting" style="min-height: inherit; display: flex; flex-direction: column;">
<div class="mainbody">
<div id="content">
<ErrorList v-if="error" :error="error"/>
<table>
<thead>
<tr>
<th scope="col">
State
</th>
<th scope="col">
Class
</th>
<th scope="col">
Description
</th>
<th scope="col">
Net Rate
</th>
<th scope="col">
Payroll
</th>
<th scope="col">
Premium Due
</th>
</tr>
</thead>
<tbody>
<tr v-for="(clazz, index) in classes" :key="index">
<td scope="row" data-label="State">
{{ clazz.state }}
</td>
<td data-label="Class">
{{ clazz.classCode }}
</td>
<td data-label="Description">
{{ clazz.description }}
</td>
<td data-label="Net Rate" class="alignright">
{{ clazz.netRate | currency }}
</td>
<td data-label="Payroll">
<input type="text" v-model="clazz.payroll"/>
</td>
<td data-label="Premium Due" class="alignright">
{{ premiumDue(clazz) | currency }}
</td>
</tr>
</tbody>
<tfoot>
<tr class="subtotal">
<td colspan="3" aria-hidden="true"></td>
<td colspan="2" class="alignright lighter">Premium Total:</td>
<td class="alignright">{{ premiumTotal() | currency }}</td>
</tr>
<tr class="subtotal last">
<td colspan="3" aria-hidden="true"></td>
<td colspan="2" class="alignright lighter">Tax Total:</td>
<td class="alignright">{{ taxTotal() | currency }}</td>
</tr>
<tr class="grandtotal">
<td colspan="3" aria-hidden="true"></td>
<td colspan="2" class="alignright lighter">Grand Total:</td>
<td class="alignright">{{ (taxTotal() + premiumTotal()) | currency }}</td>
</tr>
<tr class="formbuttons">
<td colspan="4" aria-hidden="true"></td>
<td><button class="button-sm purple" @click="onClear">Clear</button></td>
<td><button class="button-sm purple" @click="onSubmit">Submit</button></td>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</template>
<script>
/* eslint-disable vue/no-unused-components */
import ErrorList from './shared/ErrorList'
export default {
name: 'Reporting',
components: { ErrorList },
data() {
return {
error: null,
classes: []
}
},
methods: {
onClear() {
this.classes.forEach(clazz => {
clazz.payroll = ''
})
},
validate(lines) {
for (let line of lines) {
if (!(/^\d*(\.\d{1,2})?$/.test(line.quantity))) {
this.error = { message: 'Payroll must be in number format with no more than 2 places after decimal.' }
return false
}
}
this.error = null
return true
},
onSubmit(e) {
let lines = []
this.classes.forEach(clazz => {
lines.push({
classCode: clazz.id,
quantity: clazz.payroll,
rate: clazz.netRate,
taxRate: clazz.taxRate
})
})
this.validate(lines)
},
premiumDue(clazz){
if (!clazz.payroll) {
this.error = null
return 0
} else if (/^\d*(\.\d{1,2})?$/.test(clazz.payroll)) {
this.error = null
return (clazz.payroll / 100) * clazz.netRate
} else {
this.error = { message: 'Payroll must be in number format with no more than 2 places after decimal.' }
return 0
}
},
premiumTotal() {
return this.classes.reduce((accumulator, clazz) => {
return (clazz.payroll) ? accumulator + this.premiumDue(clazz) : accumulator + 0
}, 0)
},
taxDue(clazz){
return this.premiumDue(clazz) * clazz.taxRate
},
taxTotal() {
return this.classes.reduce((accumulator, clazz) => {
return (clazz.payroll) ? accumulator + this.taxDue(clazz) : accumulator + 0
}, 0)
},
initialize() {
this.classes.push({
classCode: "5540",
description: "Roofing",
name: "CC-00002",
netRate: 12.34,
state: "CA",
taxRate: 0.035
})
this.classes.push({
classCode: "8810",
description: "Clerical",
name: "CC-00001",
netRate: 0.68,
state: "CA",
taxRate: 0.035
})
}
},
beforeRouteUpdate(to) {
this.onClear()
this.initialize()
},
created() {
this.initialize()
}
}
</script>
<style scoped>
</style>
添加此 ErrorList.vue 文件(确保将其放在 components 文件夹下名为 shared 的子文件夹中):
<template>
<section>
<div v-if="error.message">{{ error.message }}</div>
<div v-if="error.errors && error.errors.length > 0">
<ul>
<li v-for="(err, index) in error.errors" :key="index"><h1>{{ err.message }}</h1></li>
</ul>
</div>
</section>
</template>
<script>
export default {
name: 'ErrorList',
props: ['error']
}
</script>
<style scoped>
</style>
现在运行命令npm run build。然后运行命令serve -s dist 运行缩小的代码。在应用中输入非数字字符会导致浏览器崩溃。
此代码的缩小版本是否会导致无限循环?
【问题讨论】:
-
我很难重现该问题,因为您共享的代码并不是真正独立的。 (见minimal reproducible example)。您能否测试以下内容:如果您删除 ` else if (/^\d*(\.\d{1,2})?$/g.test(clazz.payroll)) {` 条件,构建版本是否仍然有你提到的错误?如果从
premiumDue(clazz)返回的内容中删除currency过滤器,错误是否仍然存在?这里没有引起我的注意,但也许你在依赖它的函数中修改clazz,导致无限更新循环? -
我添加了一些额外的信息,可以让您重新创建错误。
标签: javascript vue.js minify