new Vue({
el: '#app',
data: {
infinity: Infinity,
value: 3,
debt: -6,
cash: 9,
moneyInBank: 15,
},
computed: {
computedPropRemainingCashFundsIfPaid: function() {
console.log('computedPropRemainingCashFundsIfPaid');
return this.debt + this.cash;
},
computedPropRemainingTotalFunds: function() {
console.log('computedPropRemainingTotalFunds');
return this.cash + this.moneyInBank + this.debt;
}
},
methods: {
depositFunds: function(from, to, value, limit = false) {
if (limit && (this[to] + value) >= 0) { // if you try to return greater value than you owe
this[from] += this[to];
this[to] = 0;
} else if (this[from] > value && this[from] - value >= 0) { // usual deposit
this[to] += value;
this[from] -= value;
} else { // attempt to depost more than you have
this[to] += this[from];
this[from] = 0;
}
},
repayADebt: function() {
this.value = Math.abs(this.value);
if (this.debt < 0) {
this.depositFunds('cash', 'debt', this.value, true);
}
console.log('Attempt to repayADebt', this.value);
},
lendAmount: function() {
this.depositFunds('infinity', 'debt', -Math.abs(this.value));
console.log('Attempt to lendAmount', this.value);
},
withdraw: function() {
if (this.moneyInBank) {
this.depositFunds('moneyInBank', 'cash', this.value);
}
console.log('Attempt to withdraw', this.value);
}
}
});
* {
box-sizing: border-box;
padding: 0;
margin: 0;
overflow-wrap: break-word;
}
html {
font-family: "Segoe UI", Tahoma, Geneva, Verdana;
font-size: 62.5%;
}
body {
margin: 0;
font-size: 1.6rem;
}
#app {
margin: 3rem auto;
max-width: 50vw;
padding: 1rem;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.26);
}
label,
input {
margin-bottom: 0.5rem;
display: block;
width: 100%;
}
label {
font-weight: bold;
}
ul {
list-style: none;
margin: 1rem 0;
padding: 0;
}
li {
margin: 1rem 0;
padding: 1rem;
border: 1px solid #ccc;
}
.grid {
display: grid;
grid: 1fr / 1fr min-content 1fr min-content;
gap: 1rem;
align-items: center;
margin-bottom: 1rem;
}
.grid> :is(button, input) {
height: 3rem;
margin: 0;
}
.computed-property-desc {
padding: 1rem;
background-color: rgba(0, 0, 0, 0.3);
text-align: justify;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>A First App</title>
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<div id="app">
<h1>Computed Properties Guide</h1>
<p style="background-color: bisque;">
Let's assume that you have <span v-once>{{ cash }}</span>$; And you need to pay a debt=<span v-once>{{ debt }}</span>
</p>
<p>Your bank account: {{ moneyInBank }}$ <button v-on:click="withdraw(value)">Withdrow {{ value }}$ from
bank</button></p>
<p>Your cash: {{ cash }}$</p>
<p>Your debt: {{ debt }}$ <button v-on:click="lendAmount(value)">Lend {{ value }}$ from Infinity</button></p>
<div class="grid">
<button v-on:click="repayADebt(value)">Repay a debt</button>
<span>in amout of</span>
<input type="text" v-model.number="value">
<span>$</span>
</div>
<p>computedPropRemainingCashFundsIfPaid/<br><mark>Available funds in case of debt repayment</mark> = {{ computedPropRemainingCashFundsIfPaid }}$</p>
<p>computedPropRemainingTotalFunds = {{ computedPropRemainingTotalFunds }}$</p>
<p class="computed-property-desc">when you need to change data, you will use methods. And When you need to change the presentation of existing data, you will use computed properties. As you practice both concepts, it will become easier which one should you use. Very important notes:
1. it must always return a value; 2. computed properties are only used for transforming data and not for chaning it for our presentation layer | they should not alter or change the existing data</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>
</body>
</html>