node.js - Vue 不使用 axios 钩子打开 .json 文件
问题描述
迈出vue的第一步。我在导入 .json 文件时崩溃了。这份工作涉及一家小商店。本段的目标是在商店中输入 4 个产品。产品文件是使用 Axios 挂钩导入的。但 Vue 开发工具错误未定义(见图)。加载网站时,会自动加载带有 v-else 的 div。
products.json 文件嵌套在与 index.html 相同的文件夹中。http://localhost:8000/products.json向我展示了 .json 文件。
在这里您可以找到这家小商店的所有代码。即使复制/粘贴此代码我也无法正常工作。我还使用相关代码使其更小:
<!DOCTYPE html>
<html>
<head>
<title>Vue.js Pet Depot</title>
<script src="https://unpkg.com/vue"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="assets/css/app.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.16.2/axios.js"></script>
<meta charset="UTF-8">
</head>
<body>
<div class="container">
<div id="app">
<header>
<div class="navbar navbar-default">
<div class="navbar-header">
<h1>{{ sitename }}</h1>
</div>
<div class="nav navbar-nav navbar-right cart">
<button type="button" class="btn btn-default btn-lg" v-on:click="showCheckout">
<span class="glyphicon glyphicon-shopping-cart">{{ cartItemCount}}</span> Checkout
</button>
</div>
</div>
</header>
<main>
<div v-if="showProduct"> <!--not working-->
<div v-for="product in sortedProducts">
<div class="row">
<div class="col-md-5 col-md-offset-0">
<figure>
<img class="product" v-bind:src="product.image">
</figure>
</div>
<div class="col-md-6 col-md-offset-0 description">
<h1 v-text="product.title"></h1>
<p v-html="product.description"></p>
<p class="price">
{{product.price | formatPrice}}
</p>
<button class=" btn btn-primary btn-lg" v-on:click="addToCart(product)" v-if="canAddToCart(product)">Add to cart</button>
<button disabled="true" class=" btn btn-primary btn-lg" v-else>Add to cart</button>
<span class="inventory-message" v-if="product.availableInventory - cartCount(product.id) === 0">
All Out!
</span>
<span class="inventory-message" v-else-if="product.availableInventory - cartCount(product.id) < 5">
Only {{product.availableInventory - cartCount(product.id)}} left!
</span>
<span class="inventory-message" v-else>
Buy Now!
</span>
<div class="rating">
<span v-bind:class="{'rating-active' :checkRating(n, product)}" v-for="n in 5">
☆
</span>
</div>
</div>
<!-- end of col-md-6-->
</div>
<!-- end of row-->
<hr />
</div>
<!-- end of v-for-->
</div>
<!-- end of showProduct-->
<div v-else>
<!--skipped this part-->
</div>
</main>
</div>
<!-- end of app-->
</div>
<script type="text/javascript">
var APP_LOG_LIFECYCLE_EVENTS = true;
var webstore = new Vue({
el: '#app',
data: {
sitename: "Vue.js Pet Depot",
showProduct: true,
a: false,
states: []
},
order: []
},
products: [],
cart: []
},
methods: {
checkRating(n, myProduct) {
return myProduct.rating - n >= 0;
},
addToCart(aProduct) {
this.cart.push(aProduct.id);
},
showCheckout() {
this.showProduct = this.showProduct ? false : true;
},
submitForm() {
alert('Submitted');
},
canAddToCart(aProduct) {
//return this.product.availableInventory > this.cartItemCount;
return aProduct.availableInventory > this.cartCount(aProduct.id);
},
cartCount(id) {
let count = 0;
for (var i = 0; i < this.cart.length; i++) {
if (this.cart[i] === id) {
count++;
}
}
return count;
}
},
computed: {
cartItemCount() {
return this.cart.length || '';
},
sortedProducts() {
if (this.products.length > 0) {
let productsArray = this.products.slice(0);
console.log(productsArray);
console.log(this.products);
function compare(a, b) {
if (a.title.toLowerCase() < b.title.toLowerCase())
return -1;
if (a.title.toLowerCase() > b.title.toLowerCase())
return 1;
return 0;
}
return productsArray.sort(compare);
}
}
},
filters: {
formatPrice(price) { //#B
..
}
},
beforeCreate: function () { //#B
if (APP_LOG_LIFECYCLE_EVENTS) { //#B
..
},
created: function () {
axios.get('./products.json')
.then((response) => {
this.products = response.data.products;
console.log(this.products);
});
},
beforeMount: function () {
..
},
mounted: function () {
..
},
beforeUpdate: function () {
..
},
updated: function () {
..
},
beforeDestroyed: function () {
..
},
destroyed: function () {
..
}
});
</script>
</body>
</html>
解决方案
我在这里尝试了相同的代码,它工作正常,我确实 axios
调用了这个 json 文件:
https://raw.githubusercontent.com/ErikCH/VuejsInActionCode/master/chapter-05/products.json
<!DOCTYPE html>
<html>
<head>
<title>Vue.js Pet Depot</title>
<script src="https://unpkg.com/vue"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="assets/css/app.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.16.2/axios.js"></script>
<meta charset="UTF-8">
</head>
<body>
<div class="container">
<div id="app">
<header>
<div class="navbar navbar-default">
<div class="navbar-header">
<h1>{{ sitename }}</h1>
</div>
<div class="nav navbar-nav navbar-right cart">
<button type="button" class="btn btn-default btn-lg" v-on:click="showCheckout">
<span class="glyphicon glyphicon-shopping-cart">{{ cartItemCount}}</span> Checkout
</button>
</div>
</div>
</header>
<main>
<div v-if="showProduct">
<div v-for="product in sortedProducts">
<div class="row">
<div class="col-md-5 col-md-offset-0">
<figure>
<img class="product" v-bind:src="product.image">
</figure>
</div>
<div class="col-md-6 col-md-offset-0 description">
<h1 v-text="product.title"></h1>
<p v-html="product.description"></p>
<p class="price">
{{product.price | formatPrice}}
</p>
<button class=" btn btn-primary btn-lg" v-on:click="addToCart(product)" v-if="canAddToCart(product)">Add to cart</button>
<button disabled="true" class=" btn btn-primary btn-lg" v-else>Add to cart</button>
<span class="inventory-message" v-if="product.availableInventory - cartCount(product.id) === 0">All Out!
</span>
<span class="inventory-message" v-else-if="product.availableInventory - cartCount(product.id) < 5">
Only {{product.availableInventory - cartCount(product.id)}} left!
</span>
<span class="inventory-message" v-else>Buy Now!
</span>
<div class="rating">
<span v-bind:class="{'rating-active' :checkRating(n, product)}" v-for="n in 5">☆
</span>
</div>
</div>
<!-- end of col-md-6-->
</div>
<!-- end of row-->
<hr />
</div>
<!-- end of v-for-->
</div>
<!-- end of showProduct-->
<div v-else>
<div class="row">
<div class="col-md-10 col-md-offset-1">
<div class="panel panel-info">
<div class="panel-heading">Pet Depot Checkout</div>
<div class="panel-body">
<div class="form-group">
<div class="col-md-12">
<h4>
<strong>Enter Your Information</strong>
</h4>
</div>
</div>
<div class="form-group">
<div class="col-md-6">
<strong>First Name:</strong>
<input v-model.trim="order.firstName" class="form-control" />
</div>
<div class="col-md-6">
<strong>Last Name:</strong>
<input v-model.trim="order.lastName" class="form-control" />
</div>
</div>
<div class="form-group">
<div class="col-md-12">
<strong>Address:</strong>
</div>
<div class="col-md-12">
<input v-model.trim="order.address" class="form-control" />
</div>
</div>
<div class="form-group">
<div class="col-md-12">
<strong>City:</strong>
</div>
<div class="col-md-12">
<input v-model.trim="order.city" class="form-control" />
</div>
</div>
<div class="form-group">
<div class="col-md-2">
<strong>State:</strong>
<select v-model="order.state" class="form-control">
<option disabled value="">State</option>
<option v-for="(state, key) in states" v-bind:value="state">
{{key}}
</option>
</select>
</div>
</div>
<div class="form-group">
<div class="col-md-6 col-md-offset-4">
<strong>Zip / Postal Code:</strong>
<input v-model.number="order.zip" class="form-control" type="number" />
</div>
</div>
<div class="form-group">
<div class="col-md-6 boxes">
<input type="checkbox" id="gift" value="true" v-bind:true-value="order.sendGift" v-bind:false-value="order.dontSendGift" v-model="order.gift">
<label for="gift">Ship As Gift?</label>
</div>
</div>
<!-- end of form-group -->
<div class="form-group">
<div class="col-md-6 boxes">
<input type="radio" id="home" v-bind:value="order.home" v-model="order.method">
<label for="home">Home</label>
<input type="radio" id="business" v-bind:value="order.business" v-model="order.method">
<label for="business">Business</label>
</div>
</div>
<!-- end of form-group-->
<div class="form-group">
<div class="col-md-6">
<button type="submit" class="btn btn-primary submit" v-on:click="submitForm">Place Order</button>
</div>
<!-- end of col-md-6-->
</div>
<!-- end of form-group-->
<div class="col-md-12 verify">
<pre>
First Name: {{order.firstName}}
Last Name: {{order.lastName}}
Address: {{order.address}}
City: {{order.city}}
Zip: {{order.zip}}
State: {{order.state}}
Method: {{order.method}}
Gift: {{order.gift}}
</pre>
</div>
<!-- end of col-md-12 verify-->
</div>
<!--end of panel-body-->
</div>
<!--end of panel panel-info-->
</div>
<!--end of col-md-10 col-md-offset-1-->
</div>
<!--end of row-->
</div>
</main>
</div>
<!-- end of app-->
</div>
<script type="text/javascript">
var APP_LOG_LIFECYCLE_EVENTS = true;
var webstore = new Vue({
el: '#app',
data: {
sitename: "Vue.js Pet Depot",
showProduct: true,
a: false,
states: {
AL: 'Alabama',
AK: 'Alaska',
AR: 'Arizona',
CA: 'California',
NV: 'Nevada'
},
order: {
firstName: '',
lastName: '',
address: '',
city: '',
zip: '',
state: '',
method: 'Home Address',
business: 'Business Address',
home: 'Home Address',
gift: '',
sendGift: 'Send As A Gift',
dontSendGift: 'Do Not Send As A Gift'
},
products: {},
cart: []
},
methods: {
checkRating(n, myProduct) {
return myProduct.rating - n >= 0;
},
addToCart(aProduct) {
this.cart.push(aProduct.id);
},
showCheckout() {
this.showProduct = this.showProduct ? false : true;
},
submitForm() {
alert('Submitted');
},
canAddToCart(aProduct) {
//return this.product.availableInventory > this.cartItemCount;
return aProduct.availableInventory > this.cartCount(aProduct.id);
},
cartCount(id) {
let count = 0;
for (var i = 0; i < this.cart.length; i++) {
if (this.cart[i] === id) {
count++;
}
}
return count;
}
},
computed: {
cartItemCount() {
return this.cart.length || '';
},
sortedProducts() {
if (this.products.length > 0) {
let productsArray = this.products.slice(0);
function compare(a, b) {
if (a.title.toLowerCase() < b.title.toLowerCase())
return -1;
if (a.title.toLowerCase() > b.title.toLowerCase())
return 1;
return 0;
}
return productsArray.sort(compare);
}
}
},
filters: {
formatPrice(price) { //#B
if (!parseInt(price)) {
return "";
} //#C
if (price > 99999) { //#D
var priceString = (price / 100).toFixed(2); //#E
var priceArray = priceString.split("").reverse(); //#F
var index = 3; //#F
while (priceArray.length > index + 3) { //#F
priceArray.splice(index + 3, 0, ","); //#F
index += 4; //#F
} //#F
return "$" + priceArray.reverse().join(""); //#G
} else {
return "$" + (price / 100).toFixed(2); //#H
}
}
},
created: function() { //#C
axios.get('https://raw.githubusercontent.com/ErikCH/VuejsInActionCode/master/chapter-05/products.json')
.then((response) => {
this.products = response.data.products;
// console.log(this.products);
});
}
});
</script>
</body>
</html>