javascript - 无法在 Vue.JS 中将数据从一个组件推送到另一个组件

标签 javascript vue.js

我试图通过 Prop 将数据从父组件(主页路由)传递到子组件(播放列表路由)。在子组件中,我收到错误“TypeError:无法读取未定义的属性'length'”。这两个组件目前位于同一页面上,但我试图将子组件移动到其自己的路线,这导致了此错误。

App.vue

<template>
  <div id="app">
    <Header></Header>
    <router-view></router-view>
    <Footer></Footer>
  </div>
</template>

<script>
import Header from './components/header.vue'
import Footer from './components/footer.vue'


export default {
  name: 'app',
  components: {
    Header,
    Footer,
  }
}
</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: 0px;
}
</style>

Main.js

import Vue from 'vue';
import App from './App.vue';
import "jquery";
import "bootstrap";
import VueRouter from 'vue-router';

import "bootstrap/dist/css/bootstrap.min.css"
import { library } from '@fortawesome/fontawesome-svg-core'
import { faSearch } from '@fortawesome/free-solid-svg-icons'
import { faRedo } from '@fortawesome/free-solid-svg-icons'
import { faPlus } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
import Home from './components/home.vue'
import Next from './components/next.vue'
import List from './components/myList.vue'


library.add(faSearch)
library.add(faRedo)
library.add(faPlus)

Vue.component('font-awesome-icon', FontAwesomeIcon)
Vue.use(VueRouter);
Vue.config.productionTip = false

const router = new VueRouter({
  routes: [
    {
      path: '/home',
      component: Home
    },
    {
      path: '/next',
      component: Next
    },
    {
      path: '/playlist',
      component: List
    }
  ]
});

new Vue({
  render: h => h(App),
  router
}).$mount('#app')

父组件:

<template>
  <div class="container search">

    <div class="jumbotron" style="clear:both">
      <h1 class="display-4">{{title}}</h1>
      <p class="lead">{{intro}}</p>
      <hr class="my-4">
      <p v-if="validated" :class="errorTextClass">Enter a valid search term</p>

      <button
        type="button"
        class="btn btn-primary btn-lg mb-3"
        v-on:click="refreshPage"
        v-if="result.length > 1"
      >
        <font-awesome-icon icon="redo"/>Start again
      </button>
      <input
        class="form-control form-control-lg mb-3"
        type="search"
        placeholder="Search"
        aria-label="Search"
        v-model="search"
        required
        autocomplete="off"
        id="search"
      >

      <div v-for="(result, index) in result" :key="index">
        <div class="media mb-4">
          <img
            :src="resizeArtworkUrl(result)"
            alt="Album Cover"
            class="album-cover align-self-start mr-3"
          >
          <div class="media-body">
            <h4 class="mt-0">
              <!-- <button
                type="button"
                class="btn btn-primary btn-lg mb-3 float-right"
                v-on:click="addItem(result)"
              >
                <font-awesome-icon icon="plus"/>
              </button>-->

              <button
                type="button"
                class="btn btn-primary btn-lg mb-3 float-right"
                v-on:click="addItem(result)"
                :disabled="result.disableButton"
              >

                <font-awesome-icon icon="plus"/>
              </button>

              <b>{{result.collectionName}}</b>
            </h4>
            <h6 class="mt-0">{{result.artistName}}</h6>
            <p class="mt-0">{{result.primaryGenreName}}</p>
          </div>
        </div>
      </div>

      <div :class="loadingClass" v-if="loading"></div>

      <button
        class="btn btn-success btn-lg btn-block mb-3"
        type="submit"
        v-on:click="getData"
        v-if="result.length < 1"
      >
        <font-awesome-icon icon="search"/>Search
      </button>
    </div>
  </div>
</template>

<script>
import List from "../components/myList.vue";

export default {
  name: "Hero",
  components: {
    List
  },
  data: function() {
    return {
      title: "Simple Search",
      isActive: true,
      intro: "This is a simple hero unit, a simple jumbotron-style.",
      subintro:
        "It uses utility classes for typography and spacing to space content out.",
      result: [],
      errors: [],
      List: [],
      search: "",
      loading: "",
      message: false,
      isValidationAllowed: false,
      loadingClass: "loading",
      errorTextClass: "error-text",
      disableButton: false
    };
  },

  watch: {
    search: function(val) {
      if (!val) {
        this.result = [];
      }
    }
  },

  computed: {
    validated() {
      return this.isValidationAllowed && !this.search;
    },
    isDisabled: function() {
      return !this.terms;
    }
  },

  methods: {
    getData: function() {
      this.isValidationAllowed = true;
      this.loading = true;
      fetch(`https://thisapi.com/api`)
        .then(response => response.json())
        .then(data => {
          this.result = data.results;
          this.loading = false;
          /* eslint-disable no-console */
          console.log(data);
          /* eslint-disable no-console */
        });
    },

    toggleClass: function() {
      // Check value
      if (this.isActive) {
        this.isActive = false;
      } else {
        this.isActive = true;
      }
    },

    refreshPage: function() {
      this.search = "";
    },
    addItem: function(result) {
      result.disableButton = true; // Or result['disableButton'] = true;
      this.List.push(result);
      /* eslint-disable no-console */
      console.log(result);
      /* eslint-disable no-console */
    },

    resizeArtworkUrl(result) {
      return result.artworkUrl100.replace("100x100", "160x160");
    }
  }
};
</script>

<style>
.loading {
  background-image: url("../assets/Rolling-1s-42px.gif");
  background-repeat: no-repeat;
  height: 50px;
  width: 50px;
  margin: 15px;
  margin-left: auto;
  margin-right: auto;
}

.error-text {
  color: red;
}

.media {
  text-align: left;
}

.album-cover {
  width: 80px;
  height: auto;
}

.red {
  background: red;
}

.blue {
  background: blue;
}

.div {
  width: 100px;
  height: 100px;
  display: inline-block;
  border: 1px solid black;
}
</style>

子组件或/list(路由)

<template>
  <div class="mb-5 container">
    <button type="button" class="btn btn-primary mt-2 mb-2 btn-block">
      My List
      <span class="badge badge-light">{{List.length}}</span>
    </button>

    <div class="col-md-4 float-left p-2 mb-3 " v-for="(result, index) in List" :key="index">
      <img
          :src="resizeArtworkUrl(result)"
          alt="Album Cover"
          class="album-cover align-self-start mr-3 card-img-top"
        >
      <div class="card-body">
        <h5 class="card-title">{{result.collectionName}}</h5>
        <h6 class="mt-0 mb-2">{{result.artistName}}</h6>
        <p class="mt-0 mb-2">{{result.primaryGenreName}}</p>

        <button class="btn btn-danger" v-on:click="removeElement(result)">Remove</button>
      </div>
    </div>
  </div>
</template>

<script>
export default {
   name: 'List',
   props: 
   ["List"],

  methods: {
    removeElement: function(index) {
      this.List.splice(index, 1);
    },

    resizeArtworkUrl(result) {
      return result.artworkUrl100.replace("100x100", "160x160");
    }
  }
};
</script>

<style scoped>

.album-cover {
    width: 100%;
    height: auto;
    background-color: aqua;
}

</style>

最佳答案

如果您想从当前父组件重定向到播放列表组件,您可以这样做:

this.$router.push({
    path: '/playlist',
    params: {List: this.List}
});

然后在你的路由器中添加 props 属性:

{
    path: '/playlist',
    component: List,
    props: true,
}

关于javascript - 无法在 Vue.JS 中将数据从一个组件推送到另一个组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56728522/

相关文章:

javascript - 如何在捕获时获取 axios 错误发布/请求有效负载

javascript - q.defer deferred.resolve 已弃用

javascript - Firefox 开发人员控制台中的 XML 解析错误

javascript - VueJS 路由/导航问题

javascript - 带有ajax的Vuex Action 未在计算中更新

javascript - Vuejs 警告 : infinite update loop in a component render function

javascript - 如何访问组件中的 vuejs webpack 配置变量?

Javascript:仅在其自己的函数内直接修改数组

javascript - 单击内部 anchor 时如何防止切换效果?

html - 在 col 12 div 下的 Bootstrap 表格网格上添加滚动条