首页 > 解决方案 > Vue 不使用 axios 钩子打开 .json 文件

问题描述

迈出vue的第一步。我在导入 .json 文件时崩溃了。这份工作涉及一家小商店。本段的目标是在商店中输入 4 个产品。产品文件是使用 Axios 挂钩导入的。但 Vue 开发工具错误未定义(见图)。加载网站时,会自动加载带有 v-else 的 div。

片段 Vue 开发工具

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>

标签: node.jsvue.jstwitter-bootstrap-3vuejs2vue-component

解决方案


我在这里尝试了相同的代码,它工作正常,我确实 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>


推荐阅读