【问题标题】:Vue Router not working properly and adds a #Vue Router 无法正常工作并添加了 #
【发布时间】:2020-09-09 18:38:48
【问题描述】:

我有一个带有搜索栏的主应用页面组件。返回的搜索结果在卡片中,我希望设置一个“单击此处查看更多详细信息”,将放置在每张卡片中。它将链接到单击的一个结果的详细信息页面。如何在 Vue 上链接这些组件以及是否可以传递 id?我希望单击按钮后,组件会在同一页面上呈现,而不是在新选项卡上呈现。

单击“单击此处”后,它会将链接更新为http://localhost:8081/#/{name:'Details',%20params:%20{id:%20result._gddid}}

我收到 [Vue 警告]:属性或方法“结果”未在实例上定义,但在渲染期间被引用。

谢谢!

app.vue

<template>
  <div id="app">
    <Header/>
    <SearchForm v-on:search="search"/>
    <SearchResults
      v-if="results.length > 0"
      v-bind:results="results"
      v-bind:reformattedSearchString="reformattedSearchString"/>
    <Details
      v-bind:results="results"
     />

    <Pagination
      v-if="results.length > 0"
      v-bind:prevPageToken="api.prevPageToken"
      v-bind:next_page="api.scrollId"
      v-on:prev-page="prevPage"
      v-on:next-page="nextPage"
    />
  </div>
</template>

<script>
import Header from './components/layout/Header';
import SearchForm from './components/SearchForm';
import SearchResults from './components/SearchResults';
import Details from './components/Details'
import Pagination from './components/Pagination';
import axios from 'axios';

export default {
  name: 'app',
  components: {
    Header,
    SearchForm,
    SearchResults,
    Details,
    Pagination
  },

   data() {
    return {
      results: [],
      reformattedSearchString: '',
      api: {
        baseUrl: 'https://test.org/api/v1/articles?',
        max: 25,
        q: '',
        prevPageToken: '',
        scrollId: ''
      }
    };
  },


   methods: {
    search(searchParams) {
      this.reformattedSearchString = searchParams.join(' ');
      this.api.q = searchParams.join('+');
      const { baseUrl, q, max} = this.api;
      const apiUrl = `${baseUrl}&term=${q}&title_like=${q}&recent&max=${max}&full_results`;
      this.getData(apiUrl);

    },

    prevPage() {
      const { baseUrl, q, max, prevPageToken } = this.api;
      const apiUrl = `${baseUrl}&term=${q}&title_like=${q}&max=${max}&pageToken=${prevPageToken}`;
      this.getData(apiUrl);
    },

    nextPage() {
      const { baseUrl, q, max,scrollId } = this.api;
      const apiUrl = `${baseUrl}&term=${q}&title_like=${q}&max=${max}&recent&full_results&scroll_id=${scrollId}`;
      this.getData(apiUrl);
    },

    getData(apiUrl) {
      axios
        .get(apiUrl)
        .then(res => {
          this.results = res.data.success.data;
          this.api.prevPageToken = res.data.success.data.prevPageToken;
          this.api.next_page = res.data.scrollId;
        })
        .catch(error => console.log(error))
    }  
  }
};
</script>

SearchResults.vue

<template>
  <div class="container mb-3">
    <div class="d-flex mb-3">
      <div class="mr-auto">
        <h3>Search Results for "{{ reformattedSearchString }}"</h3>
      </div>
      <div class="btn-group ml-auto" role="group">
        <button
          @click="changeDisplayMode('grid')"
          type="button"
          class="btn btn-outline-secondary"
          v-bind:class="{ active: displayMode === 'grid' }"
        >
          <i class="fas fa-th"></i>
        </button>
        <button
          @click="changeDisplayMode('list')"
          type="button"
          class="btn btn-outline-secondary"
          v-bind:class="{ active: displayMode === 'list' }"
        >
          <i class="fas fa-list"></i>
        </button>
      </div>
    </div>

    <div class="card-columns" v-if="displayMode === 'grid'">
      <div class="card" v-bind:key="result._gddid" v-for="result in results">
        <ArticleGridItem v-bind:result="result"/>
      </div>
    </div>
    <div v-else>
      <div class="card mb-2" v-bind:key="result._gddid" v-for="result in results">
        <ArticleListItem v-bind:result="result"/>
      </div>
    </div>
    <div class="card mb-2" v-bind:key="result._gddid" v-for="result in results">
        <Details v-bind:result="result"/>
    </div>
  </div>
</template>

<script>
import ArticleListItem from './ArticleListItem';
import ArticleGridItem from './ArticleGridItem';
import Details from './Details';


export default {
  name: 'SearchResults',
  components: {
    ArticleListItem,
    ArticleGridItem,
    Details,
  },
  data() {
    return {
      title: 'Search Results',
      displayMode: 'grid'
    };
  },
  methods: {
    changeDisplayMode(displayMode) {
      this.displayMode = displayMode;
    }
  },
  props: ['results', 'reformattedSearchString']
};
</script>

<style scoped>
button:focus {
  box-shadow: none !important;
}
</style>

main.js

import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router';
import moment from 'moment'



Vue.config.productionTip = false

Vue.filter('formatDate', function (value) {
  if (!value) return ''
  return moment(value.toString()).format('MM/DD/YYYY hh:mm')
})

Vue.use(VueRouter)

import Details from './components/Details';

const router = new VueRouter({
  routes: [
    {
     path: '/Details/:id',
     name: 'Details',
     component: Details
   }
 ]
})


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

ArticleListItem.vue

<template>
  <div>
    <div class="card-body"> 
    <h6 class="card-text">{{ result.title }}</h6>
      <p class="card-subtitle mb-2 text-muted"
      >{{ result.publisher }} | {{ result.journal }} | {{ result.year }}</p>
      <a :href="'https://test.org/api/articles?docid=' + result._gddid" target="_blank">
        <i class="fa fa-download"  alt="Download"> </i>
      </a>
        <router-link dark to="{name:'Details', params: {id: result._gddid}}">
              Click here for more Details
        </router-link>
      <router-view></router-view>
    </div>
  </div>
</template>

<script>
export default {
  name: 'ArticleListItem',
  props: ['result'],  
}
</script>

Details.vue

 <template>
    <div class="Details">
        <div class="container">
            <div class="row">
                <div class="col-md-12" v-for="result in results" :key="result._gddid"> 
                    <div v-if="id == result._gddid">
                        <h1>{{result.title}}</h1>
                    </div>
                </div>      
            </div>
        </div> 
    </div>    
</template>
<script>
 export default {
  name: 'Details',
  props: ['result'],

};
</script>

【问题讨论】:

    标签: json api vue.js vue-router


    【解决方案1】:

    单击“单击此处”后,它会将链接更新为http://localhost:8081/#/{name:'Details',%20params:%20{id:%20result._gddid}}

    浏览一下代码,在 ArticleListItem.vue 中似乎没有绑定路由器链接的 to 属性,因此它被视为字符串。

    目前:to="{name:'Details', params: {id: result._gddid}}"

    试试::to="{name:'Details', params: {id: result._gddid}}",让它作为对象传递。


    我收到 [Vue 警告]:属性或方法“结果”未在实例上定义,但在渲染期间被引用。

    Details.vue 中,您有 props: ['result'],,但在 v-for 中它会查找未在 results 中定义的 results em>data() 也不在 props 内。


    至于出现的#,vue-router的默认模式是hash,如果你不想使用#,你可以通过以下方式将其设置为history:

    const router = new VueRouter({
      mode: 'history',
      routes: [...]
    })
    

    但请注意,您需要运行服务器来处理路由;你可以在https://router.vuejs.org/guide/essentials/history-mode.html#html5-history-mode找到更多信息

    【讨论】:

    • 非常感谢!我仍然无法弄清楚 v-for 部分。在我的 SearchResults.vue 中,我有一个 v-for,但我不应该把它放在那里吗?
    • 我引用的 v-for 在您提供的 Details.vue 文件中。它使用 v-for over results,但 Details.vue 的道具有“结果”。
    • 所以 ArticleListItem.vue 有 props: result 所以我认为这会起作用@subhaze
    • 正确,但似乎 Details.vue 需要查看 Details.vue 代码的结果,但没有给出结果,它给出了“结果”,但在这里需要“结果”&lt;div class="col-md-12" v-for="result in results" :key="result._gddid"&gt;
    • 仍然无法让点击生效。我将其更改为道具的结果,但方法“id”未在实例上定义,但在渲染期间引用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-25
    • 1970-01-01
    • 2018-07-30
    • 2018-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多