这是我第一次尝试使用Vue.js,因此完全有可能我遗漏了一些非常明显的东西。
基本上,我有一个组件,可以计算一定数量的打印件所需的盒子数量(我从事印刷行业)。
如果需要的话,如果印刷件有多个部分,我有一个按钮可以创建一个附加组件。
我想以一种反应性的方式来更新所有零件所需的总盒数,但是我似乎无法达到目标。
以下是代码指向我的Gitlab存储库的链接:https://gitlab.com/dsross/printutils
任何帮助将不胜感激。
我还使用Browserify编写index.html中引用的build.js和build.css文件。
这是我的文件,以防万一没有人想要查看回购的情况:
App.vue
<template>
<div id="app">
<div>
</div>
<div>
<calculator v-for="(part, index) in parts" :key="index"></calculator>
<br />
<br />
<div class="card shadow-sm">
<div class="card-body">
<button type="button" class="btn" @click="addPart()">Add Part</button>
<button type="button" class="btn" @click="totalBoxes">Total Boxes</button>
<span>Box Total (all parts): </span><span id="grandtotal"></span>
</div>
</div>
</div>
</div>
</template>
<script>
// import Hello from './components/Hello.vue'
import Calculator from './components/Calculator.vue'
export default {
name: 'app',
components: {
Calculator
},
methods: {
addPart: function () {
console.log("Adding part");
this.parts.push(Calculator);
},
totalBoxes: function () {
console.log("totalBoxes called");
let totalBoxes = 0;
let partTotals = document.querySelectorAll("#partBoxTotal");
for (var i = 0; i < partTotals.length; i++) {
totalBoxes += parseInt(partTotals[i].innerHTML);
}
this.totalBoxCount = totalBoxes;
document.getElementById("grandtotal").innerHTML = totalBoxes;
}
},
data: function () {
return {
parts: [Calculator],
totalBoxCount: 0
}
},
}
</script>
Calculator.vue
<template>
<div class="card shadow-sm" id="boxCalculator">
<div class="card-body">
<form>
<div class="form-group">
<p>Paper:
<select class="custom-select" v-model="paperWeight">
<option v-for="(mweight, paper) in mweights" :key="mweight" v-bind:value="paper">{{paper}}</option>
</select>
</p>
<br />
<br />
<p>Final Width:
<input class="form-control" type="text" v-model="finalWidth" id="finalWidth" value="">
</p>
<p>Final Height:
<input type="text" class="form-control" v-model="finalHeight" id="finalHeight" value="">
</p>
<p>Sheets Per Unit:
<input type="text" class="form-control" v-model="numberOfSheets" id="numberOfSheets" name="numberOfSheets"
value="">
</p>
<p>Quantity:
<input type="text" class="form-control" v-model="quantity" id="quantity" name='quantity'>
</p>
<p>Stitched:
<input type="checkbox" v-model="stitched" name="stitched" id="stitched" value="">
</p>
</div>
</form>
<div class="card">
<div class="card-body">
<div id='results'>
<p id="partWeightTotal">Part Total Weight: {{ totalWeight }}</p>
<p><span>Part Box Total: </span><span id="partBoxTotal">{{ boxQuantity }}</span></p>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import {
mWeights,
stitchedMultiplier,
maxArea
} from "../constants.js"
module.exports = {
data: function () {
return {
paperWeight: this.selected,
paperType: "",
finalWidth: "",
finalHeight: "",
numberOfSheets: "",
quantity: "",
stitched: "",
boxes: "",
mweights: mWeights
}
},
computed: {
squareInches: function () {
return this.finalHeight * this.finalWidth;
},
squareInchWeight: function () {
let mWeight = mWeights[`${this.paperWeight}`];
return (mWeight / 1000) / maxArea;
},
totalWeight: function () {
return ((this.squareInches * this.squareInchWeight) * this.numberOfSheets) * this.quantity;
},
boxQuantity: function () {
let boxes = this.totalWeight / 35;
if (this.stitched) {
this.boxes = Math.ceil(boxes * stitchedMultiplier);
// this.$root.$emit('box-change', this.boxes);
return this.boxes
} else {
this.boxes = Math.ceil(boxes);
// this.$root.$emit('box-change', this.boxes);
return Math.ceil(this.boxes);
};
},
},
}
</script>
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>boxcalculator2</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<link rel="icon" href="../favicon.png">
<title>Box Calculator</title>
<!-- Bootstrap core CSS -->
<link href="dist/css/bootstrap.min.css" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="dist/sticky-footer.css" rel="stylesheet">
<link rel="stylesheet" href="dist/build.css">
</head>
<body>
<div class="container">
<div class='row'>
<div class='col'>
<div id="app"></div>
</div>
</div>
</div>
<script src="dist/build.js"></script>
</body>
</html>
答案 0 :(得分:1)
如果我的理解正确,那么您希望App
的总盒数可以在每个Calculator
各自确定其盒数时自动更新。一种方法是从Calculator
到emit an event,当其盒数更改时,可以用watcher进行监视。
我们将在下面解决几个问题:
Calculator
(单个文件组件定义)存储在this.parts[]
中是没有意义的(并且效率很低)。相反,它可以存储有意义的数据点,例如Calculator
的输出。在App
中,我们必须使用this.parts[]
来跟踪每个part
的计算结果(我们将在下面捕获)。我们将每个数组元素(即“部分”)定义为:
{
boxes: 0 // box count for this part
}
此定义允许基于computed
的{{1}}属性(稍后将定义)是反应性的。
因此,在.boxes
和addPart()
选项中:
data
// App.vue
export default {
// ...
methods: {
addPart() {
this.parts.push({ boxes: 0 });
}
},
data() {
return {
parts: [{ boxes: 0 }]
}
}
}
的输出通知App
通常情况下,父母通过data to children via props
,孩子交流data to parents with events。其他选择包括使用状态管理库,例如Vuex,但为简单起见,我们将在此处使用事件。
在Calculator
中,我们希望将Calculator
值的更改通知给父(App
),因此我们将添加一个{{3} }(例如,称为boxes
),只要boxes-changed
发生更改:
boxes
在// Calculator.vue
export default {
//...
watch: {
boxes(value) {
this.$emit('boxes-changed', value);
}
}
}
中,我们将watcher,并将事件详细信息的值复制到当前App
的{{1}}变量中,其中part
是正在迭代boxes
的当前数组元素。
part
parts[]
的崩溃:
// App.vue
<calculator v-for="(part, index) in parts" @boxes-changed="part.boxes = $event" :key="index"></calculator>
-监听@boxes-changed="part.boxes = $event"
发出的@boxes-changed="..."
事件boxes-changed
-将<calculator>
设置为事件详细信息的值part.boxes = $event
处于反应状态通过上述更改,我们有了使part.boxes
的{{1}}具有反应性所需的工具:
将totalBoxCount
更改为emits an event,将App
的{{1}}字段加起来。每当totalBoxCount
的数组元素更改时,将自动计算此属性。
totalBoxCount
在.boxes
的模板中,使用listen to the boxes-changed
event显示this.parts[]
:
this.parts[]
我们还可以从模板中删除 Total Boxes 按钮(以前用于手动触发计算):
// App.vue
export default {
computed: {
totalBoxCount() {
// Note: Alternatively, use a simple for-loop to sum .boxes
return this.parts
.filter(p => p.boxes && !Number.isNaN(p.boxes) // get only parts that have a positive `.boxes` value
.map(p => p.boxes) // map object array into an integer array of `.boxes` values
.reduce((p,c) => p + c, 0); // sum all array elements
},
},
data() {
return {
parts: [],
// totalBoxCount: 0 // CHANGED INTO COMPTUED PROP ABOVE
}
}
}
及其关联的App
处理程序:
totalBoxCount