vue.js 通过route.push在组件之间传递数据时未定义route.params

ki0zmccv  于 2022-12-14  发布在  Vue.js
关注(0)|答案(2)|浏览(110)

我想将数据从 Homepage.vue 传递到 clickthru.vue
在Homepage.vue中单击表中的记录时,我希望被路由到一个新组件(clickthru.vue)。目标是以两种不同的方式传递两种数据:

**第一个:**我想将 cve_id 作为路由传递。查询如下所示

/clickthru?cve_id=CVE-xxxx-xxxx

**第二个:**我还想传递一个对象作为参数,以便在clickthru. vue的html模板上呈现/挂载。

{ "cve": "CVE-2022-45869", "severity": "Medium", "packages": [ { "package": "kernel", "version": "5.15.80.1", "owner": "joslobo", "detection_date": "12-03-2022", "BranchStatus": { "1.0": { "sourceBranch": "NULL", "status": "NULL", "detectedOn": "NULL", "patchedOn": "NULL", "firstPatchedPackageRelease": "NULL", "fixReleaseDate": "NULL", "aid": "NULL", "qid": [ "NULL" ] }, "2.0": { "sourceBranch": "2.0", "status": "Unpatched", "detectedOn": "12-03-2022", "patchedOn": "NULL", "firstPatchedPackageRelease": "NULL", "fixReleaseDate": "NULL", "aid": "11574", "qid": [ "Not Assigned" ] } } }, { "package": "kernel", "version": "5.10.155.1", "owner": "joslobo", "detection_date": "12-03-2022", "BranchStatus": { "1.0": { "sourceBranch": "1.0", "status": "Unpatched", "detectedOn": "12-03-2022", "patchedOn": "NULL", "firstPatchedPackageRelease": "NULL", "fixReleaseDate": "NULL", "aid": "11573", "qid": [ "Not Assigned" ] }, "2.0": { "sourceBranch": "NULL", "status": "NULL", "detectedOn": "NULL", "patchedOn": "NULL", "firstPatchedPackageRelease": "NULL", "fixReleaseDate": "NULL", "aid": "NULL", "qid": [ "NULL" ] } } } ] }

在我的 homepage.vue 中,我遍历了记录/对象,并以如下所示的表格格式显示:主页.版本
第一次

点击查看

<script>
    export default {

        props: ['cve_id', 'cve_obj'],

    data() {
        return {
            cve_id: this.$route.query.cve_id,
            cve_obj: this.$route.params.cve_obj, // cve_obj is undefined 
        };
    },

主文件.js

const routes = [
   {
        path: '/clickthru',
        name: 'clickthru',
        component: clickthru,
        props: true
    }
]

如下所示,当记录 $route 时,查询被成功识别,但参数为空。

{ "fullPath": "/clickthru?cve_id=CVE-2022-45869", "hash": "", "query": { "cve_id": "CVE-2022-45869" }, "name": "clickthru", "path": "/clickthru", "params": {}, "matched": [ { "path": "/clickthru", "name": "clickthru", "meta": {}, "props": { "default": false }, "children": [], "instances": { "default": null }, "leaveGuards": { "Set(0)": [] }, "updateGuards": { "Set(0)": [] }, "enterCallbacks": {}, "components": { "default": { "props": [ "cve_id", "cve_obj" ], "__hmrId": "91ec59e3", "__file": "E:/ASTROLABE_FE/CBL-Mariner-CVE-Website/src/components/clickthru.vue" } } } ], "meta": {}, "href": "/clickthru?cve_id=CVE-2022-45869" }

我希望能够传递cve_obj,而不将其作为url/path的一部分。关于如何通过params、 meta或任何其他方式实现这一点的任何提示都非常感谢

ljo96ir5

ljo96ir51#

正如我在注解中提到的,将对象作为查询参数传递并不是一种受欢迎的方式,因此有两种方法可以做到这一点--

方法1-

只将cve_id传递给新路由,当新路由的页面被挂载时,使用查询参数cve_id从后端获取cve_object。这种方法很有用,也是推荐的,因为你总是会从后端获得更新的数据。
如果您遵循此方法,则需要进行一些更改-
1.在Homepage.vue中,只需将cve_id传递到您的新路线-

methods: {
    onAboutClick(cve_id) {
        this.$router.push({
            name: "clickthru",
            query: { cve_id: cve_id },
        });
    },
},

1.在clickthru.vue挂载的挂钩上,初始化API调用以获取该id的cve_data-

mounted() {
 // Make an API call to fetch the respected id's data
}

方法2-

当你在你的HomePage.vue中接收到记录(你正在循环的)时,把这个数据保存到你的Vuex状态。现在,和方法一一样,只把cve_id传递给你的新路由,当新路由的页面被挂载时,从Vuex状态中获取相关的数据,而不是从额外的API调用中获取。
如果你按照这个方法,那么过程将是这样的-
1.当您在HomePage.vue中获得后端响应时,将其转储为状态,如下所示-

const store = new Vuex.Store({
  state: {
    records: []
  },
  mutations: {
    SET_RECORDS (state, backend_response) {
      // mutate state
      state.records = backend_response;
    }
  }
})

1.与方法1相同,您的route查询中有cve_id,因此使用它从状态中获取相应的cve_object

<script>
export default {
    data() {
        return {
            cve_object: null,
        };
    },
    mounted() {
        this.cve_object = this.$store.state.records.find(
            (item) => item.id == this.$route.query.cve_id,
        );
    },
};
</script>

通过这种方式,您将拥有状态中的记录,因此您可以在任何页面上使用查询cve_id查找任何单个记录。

注-

我只给予了从状态中获取和设置数据的想法。如果你想遵循第二种方法,只需阅读关于Vuex的内容并按照文档进行操作。你也可以在这里查看关于how to set up Vuex in the Vue application的完整指南。

bvn4nwqk

bvn4nwqk2#

因为您的目标是在route.push的帮助下将数据路由到新页面后发送数据,所以我忽略了您代码的某些部分(例如使用您在Homepage.vue中使用的table或v-for)。以下是我认为可以帮助您的代码:
Homepage.vue:

<template>
  <div @click="onAboutClick(cveData.cve, cveData.packages)">
    some text
  </div>
</template>

<script>
export default {
  data() {
    return {
    cveData: { "cve": "CVE-2022-45869", "severity": "Medium", "packages": [ { "package": "kernel", "version": "5.15.80.1", "owner": "joslobo", "detection_date": "12-03-2022", "BranchStatus": { "1.0": { "sourceBranch": "NULL", "status": "NULL", "detectedOn": "NULL", "patchedOn": "NULL", "firstPatchedPackageRelease": "NULL", "fixReleaseDate": "NULL", "aid": "NULL", "qid": [ "NULL" ] }, "2.0": { "sourceBranch": "2.0", "status": "Unpatched", "detectedOn": "12-03-2022", "patchedOn": "NULL", "firstPatchedPackageRelease": "NULL", "fixReleaseDate": "NULL", "aid": "11574", "qid": [ "Not Assigned" ] } } }, { "package": "kernel", "version": "5.10.155.1", "owner": "joslobo", "detection_date": "12-03-2022", "BranchStatus": { "1.0": { "sourceBranch": "1.0", "status": "Unpatched", "detectedOn": "12-03-2022", "patchedOn": "NULL", "firstPatchedPackageRelease": "NULL", "fixReleaseDate": "NULL", "aid": "11573", "qid": [ "Not Assigned" ] }, "2.0": { "sourceBranch": "NULL", "status": "NULL", "detectedOn": "NULL", "patchedOn": "NULL", "firstPatchedPackageRelease": "NULL", "fixReleaseDate": "NULL", "aid": "NULL", "qid": [ "NULL" ] } } } ] }
    }
  },
  methods: {
    onAboutClick: function (cve_id, cve_obj) {
      console.log('----> cve_id = ', cve_id)
      console.log('----> cve_obj = ', cve_obj) // cve_obj is successfully printed at this point
      let objData = JSON.stringify(cve_obj);
      this.$router.push(
          {
            name: 'clickthru',
            query: {'cve_id': cve_id},
            params: {'cve_obj': objData}
          }
      )
    } // end of function
  }
}
</script>

clickthru.vue:

<template>
  <div>
    this is "clickthru" compo
  </div>
  <section>
    {{ cve_id }}
  </section>
  <section v-for="item in cve_obj">
    <div v-for="subItem in item">
      {{ subItem }}
    </div>
  </section>
</template>

<script>
export default {
  name: "clickthru",

  beforeRouteEnter (to, from, next) {
    next(vm => {
      console.log(from);
      if (from.name == "about") {
        /* you must enter the name of your home component instead of "about", I used about page so I entered "about". You can find necessary info by seeing "console.log(from)" in your console. */
        vm.cve_obj = JSON.parse(vm.$route.params.cve_obj);
        /* We set the data to "localStorage" to retrieve it when the page refreshed on mounted hook. */
        localStorage.setItem("cveDataStore" , vm.$route.params.cve_obj);
      }
    })
  },

  data() {
    return {
      cve_id: this.$route.query.cve_id,
      cve_obj: JSON.parse('[{"message": "wrong info"}]')
    };
  },

  mounted() {
    if (this.cve_obj !== JSON.parse('[{"message": "wrong info"}]')) {
      if (localStorage.getItem("cveDataStore")) {
        this.cve_obj = JSON.parse(localStorage.getItem("cveDataStore"));
      }
    }
  }
}
</script>

我在clickthru.vue组件中使用了“beforeRouteEnter”挂钩,因为根据此GitHub页面,直接传递参数可能会在页面重新加载时导致一些错误或警告。因此,我们可以将数据存储在localStorage中,以便在重新加载页面后向用户显示。

根据vue-router文档:
指定参数时,请确保提供字符串或数字(或可重复参数的数组)。任何其他类型(如undefined、false等)将自动字符串化
因为您的cve_obj数据是“object”类型,为了确保不会发生问题,我在Homepage.vue中使用了JSON.stringify,将其转换为string。然后在clickthru.vue组件中,我借助computed propertiesJSON.parse方法将其转换回一个对象。
如果您使用这段代码,就不需要在main.js中使用props: true,因为您根本不使用props

相关问题