如何使用vue路由到不同的页面并显示它们的标题和文字?
How to use vue to route to different pages and display their title and text?
我正在用 vue 制作一个 post 网站。
这是我的问题:
有 2 个页面,一个用于所有博客,另一个用于查看博客。
我正在使用 vuex。
当我点击其中一个博客时,我被转到查看博客页面,我看到了正确博客的标题,所以没问题。
我想做的事情,看似简单。
我想要一个包含两个项目的 viewblog 页面: 标题和文本 。这两个应该来自store(vuex).
这是目前的查看博客页面:
<template>
<div class="post">
<h1>{{ $route.params.title }}</h1>
// here I want my text from the store.
</div>
</template>
<script>
export default {
}
</script>
<style>
</style>
这是图书馆:
<template>
<div class="card-wrapper">
<Card :post="post" v-for="(post, index) in cards" :key="index" />
</div>
</template>
<script>
import Card from "../components/Card.vue";
export default {
components: {
Card,
},
computed: {
cards() {
return this.$store.state.cards;
},
},
};
</script>
<style>
// ...
</style>
去图书馆,有一张卡片:
<template>
<div class="card">
<router-link
:post="post"
:to="{ name: 'Post', params: { id: post.index, title: post.title } }"
>
<div class="image"></div>
<div class="title">{{ post.title }}</div>
</router-link>
</div>
</template>
<script>
export default {
name: "Card",
props: ["post"],
};
</script>
<style>
// ...
</style>
这是我的 vue-router:
import { createRouter, createWebHashHistory } from 'vue-router'
import Home from '../views/Home.vue'
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
component: () => import('../views/About.vue')
},
{
path: '/post/:id',
name: 'Post',
component: () => import('../views/Post.vue')
}
]
const router = createRouter({
history: createWebHashHistory(),
routes
})
router.beforeEach((to, from, next) => {
console.log(to)
let documentTitle = `${ process.env.VUE_APP_TITLE } - ${to.name}`
if (to.params.title) {
documentTitle += ` - ${ to.params.title }`
}
document.title = documentTitle
next()
})
export default router
最后,商店(vuex):
import { createStore } from "vuex";
export default createStore({
state: {
cards: [{
title: "Blog 1",
text: "This is blog 1",
index: 1,
},
{
title: "Blog 2",
text: "This is blog 2",
index: 2,
},
{
title: "Blog 3",
text: "This is blog 3",
index: 3,
},
{
title: "Blog 4",
text: "This is blog 4",
index: 4,
},
{
title: "Blog 5",
text: "This is blog 5",
index: 5,
},
{
title: "Blog 6",
text: "This is blog 6",
index: 6,
},
{
title: "Blog 7",
text: "This is blog 7",
index: 7,
},
],
},
mutations: {},
actions: {},
modules: {},
});
这是库中的结果:
这是我点击博客 1 时查看博客页面的结果:
对于清晰度:在标题下方,会有来自商店的文字。所以在这个例子中,文本将是 This is blog 1
谢谢你的帮助!
方法一:通过路由参数传递
您可以定义一个 getter 函数来 select 给定的 Blogtext。
将 blog-route
的 :id
作为 param
传递,以便您可以将其用作 getter
中的过滤器。
然后在 getter 中定义一个简单的过滤器逻辑。我用 forEach
做到了,但是还有其他选项可以过滤数组,选择一个适合您需要的选项。
在 component
中,您可以映射 getter,并在计算的 属性 中使用通过路由传递的 id 调用它,瞧,它应该 return 该特定博客的文本 post.
VueX 商店
import { createStore } from 'vuex';
export default createStore({
state: {
cards: [{
title: "Blog 1",
text: "This is blog 1",
index: 1,
},
{
title: "Blog 2",
text: "This is blog 2",
index: 2,
},
{
title: "Blog 3",
text: "This is blog 3",
index: 3,
},
{
title: "Blog 4",
text: "This is blog 4",
index: 4,
},
{
title: "Blog 5",
text: "This is blog 5",
index: 5,
},
{
title: "Blog 6",
text: "This is blog 6",
index: 6,
},
{
title: "Blog 7",
text: "This is blog 7",
index: 7,
},
],
},
getters: {
blogTextById: (state) => (index) => {
let foundText;
state.cards.forEach((card) => {
// cast both indexes to Number, so that we won't run into
//unexpected type-mismatch. Since index might be coming
// from an URL, it's likely that it is stored as a splitted
// string, holding only a number.
// e.g.: index = "2" instead of index = 2
if (Number(card.index) === Number(index)) foundText = card.text;
});
return foundText;
},
},
});
ViewBlogComponent
<template>
<div class="post">
<h1>{{ $route.params.title }}</h1>
<p>{{ blogText }}</p>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
export default {
computed: {
...mapGetters({
blogTextGetter: 'blogTextById',
}),
blogText() {
return this.blogTextGetter(this.$route.params.id);
},
},
}
</script>
方法二:通过id作为prop,获取整张卡片
此方法需要进行更多更改,其中一些更改会改变您使用路由参数的一般方法。
我们将为您的 viewBlogPage
引入一个新属性,它仅代表要查看的博客的 id || index
。然后我们使用该 ID 获取整个卡片项目并显示我们想要显示的所有数据。
在您的 LibraryCardComponent
中,您使用 title
参数重载了路由调用,这在本质上并不是不好的做法,但如果不了解此特定行为,则很难遵循。它还在组件和 $route
对象之间引入了紧密耦合。但是既然你在你的 beforeEach
钩子中使用它,我会让它留在那里。
那我们怎么办?
我们更改 Post
的路由定义以启用 Passing Props to Route Components
路由定义
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
component: () => import('../views/About.vue')
},
{
path: '/post/:id',
name: 'Post',
// Here we enable the passing of props.
// The boolean mode passes all params defined as props with the same name as the param
// So :id will be available as prop 'id' in the Component.
props: true,
component: () => import('../views/Post.vue')
}
]
现在我们必须将 prop 引入到我们的组件中以备后用。
查看博客页面
<template>
<div class="post">
<h1>{{ blogPost.title }}</h1>
<p>{{ blogPost.text }}</p>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
export default {
props: {
id: {
required: true,
}
},
computed: {
...mapGetters({
blogById: 'blogById',
}),
blogPost() {
return this.blogById(this.id);
},
},
}
</script>
方法一中的 getter 可以写成 getBlog Getter 而不是 getBlogText Getter
VueX Getters
import { createStore } from 'vuex';
export default createStore({
state: {
cards: [{
title: "Blog 1",
text: "This is blog 1",
index: 1,
},
{
title: "Blog 2",
text: "This is blog 2",
index: 2,
},
{
title: "Blog 3",
text: "This is blog 3",
index: 3,
},
{
title: "Blog 4",
text: "This is blog 4",
index: 4,
},
{
title: "Blog 5",
text: "This is blog 5",
index: 5,
},
{
title: "Blog 6",
text: "This is blog 6",
index: 6,
},
{
title: "Blog 7",
text: "This is blog 7",
index: 7,
},
],
},
getters: {
blogById: (state) => (index) => {
// cast both to Number() to prevent unexpected type-mismatch
return state.cards.find(c => Number(c.index) === Number(index));
},
},
});
通过这种方法,您的 title
和 text
显示不再与路由参数紧密耦合,而是与 vueX 的状态反应耦合。
我希望其中一种方法能满足您的需求。
我正在用 vue 制作一个 post 网站。 这是我的问题:
有 2 个页面,一个用于所有博客,另一个用于查看博客。 我正在使用 vuex。 当我点击其中一个博客时,我被转到查看博客页面,我看到了正确博客的标题,所以没问题。
我想做的事情,看似简单。 我想要一个包含两个项目的 viewblog 页面: 标题和文本 。这两个应该来自store(vuex).
这是目前的查看博客页面:
<template>
<div class="post">
<h1>{{ $route.params.title }}</h1>
// here I want my text from the store.
</div>
</template>
<script>
export default {
}
</script>
<style>
</style>
这是图书馆:
<template>
<div class="card-wrapper">
<Card :post="post" v-for="(post, index) in cards" :key="index" />
</div>
</template>
<script>
import Card from "../components/Card.vue";
export default {
components: {
Card,
},
computed: {
cards() {
return this.$store.state.cards;
},
},
};
</script>
<style>
// ...
</style>
去图书馆,有一张卡片:
<template>
<div class="card">
<router-link
:post="post"
:to="{ name: 'Post', params: { id: post.index, title: post.title } }"
>
<div class="image"></div>
<div class="title">{{ post.title }}</div>
</router-link>
</div>
</template>
<script>
export default {
name: "Card",
props: ["post"],
};
</script>
<style>
// ...
</style>
这是我的 vue-router:
import { createRouter, createWebHashHistory } from 'vue-router'
import Home from '../views/Home.vue'
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
component: () => import('../views/About.vue')
},
{
path: '/post/:id',
name: 'Post',
component: () => import('../views/Post.vue')
}
]
const router = createRouter({
history: createWebHashHistory(),
routes
})
router.beforeEach((to, from, next) => {
console.log(to)
let documentTitle = `${ process.env.VUE_APP_TITLE } - ${to.name}`
if (to.params.title) {
documentTitle += ` - ${ to.params.title }`
}
document.title = documentTitle
next()
})
export default router
最后,商店(vuex):
import { createStore } from "vuex";
export default createStore({
state: {
cards: [{
title: "Blog 1",
text: "This is blog 1",
index: 1,
},
{
title: "Blog 2",
text: "This is blog 2",
index: 2,
},
{
title: "Blog 3",
text: "This is blog 3",
index: 3,
},
{
title: "Blog 4",
text: "This is blog 4",
index: 4,
},
{
title: "Blog 5",
text: "This is blog 5",
index: 5,
},
{
title: "Blog 6",
text: "This is blog 6",
index: 6,
},
{
title: "Blog 7",
text: "This is blog 7",
index: 7,
},
],
},
mutations: {},
actions: {},
modules: {},
});
这是库中的结果:
This is blog 1
谢谢你的帮助!
方法一:通过路由参数传递
您可以定义一个 getter 函数来 select 给定的 Blogtext。
将 blog-route
的 :id
作为 param
传递,以便您可以将其用作 getter
中的过滤器。
然后在 getter 中定义一个简单的过滤器逻辑。我用 forEach
做到了,但是还有其他选项可以过滤数组,选择一个适合您需要的选项。
在 component
中,您可以映射 getter,并在计算的 属性 中使用通过路由传递的 id 调用它,瞧,它应该 return 该特定博客的文本 post.
VueX 商店
import { createStore } from 'vuex';
export default createStore({
state: {
cards: [{
title: "Blog 1",
text: "This is blog 1",
index: 1,
},
{
title: "Blog 2",
text: "This is blog 2",
index: 2,
},
{
title: "Blog 3",
text: "This is blog 3",
index: 3,
},
{
title: "Blog 4",
text: "This is blog 4",
index: 4,
},
{
title: "Blog 5",
text: "This is blog 5",
index: 5,
},
{
title: "Blog 6",
text: "This is blog 6",
index: 6,
},
{
title: "Blog 7",
text: "This is blog 7",
index: 7,
},
],
},
getters: {
blogTextById: (state) => (index) => {
let foundText;
state.cards.forEach((card) => {
// cast both indexes to Number, so that we won't run into
//unexpected type-mismatch. Since index might be coming
// from an URL, it's likely that it is stored as a splitted
// string, holding only a number.
// e.g.: index = "2" instead of index = 2
if (Number(card.index) === Number(index)) foundText = card.text;
});
return foundText;
},
},
});
ViewBlogComponent
<template>
<div class="post">
<h1>{{ $route.params.title }}</h1>
<p>{{ blogText }}</p>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
export default {
computed: {
...mapGetters({
blogTextGetter: 'blogTextById',
}),
blogText() {
return this.blogTextGetter(this.$route.params.id);
},
},
}
</script>
方法二:通过id作为prop,获取整张卡片
此方法需要进行更多更改,其中一些更改会改变您使用路由参数的一般方法。
我们将为您的 viewBlogPage
引入一个新属性,它仅代表要查看的博客的 id || index
。然后我们使用该 ID 获取整个卡片项目并显示我们想要显示的所有数据。
在您的 LibraryCardComponent
中,您使用 title
参数重载了路由调用,这在本质上并不是不好的做法,但如果不了解此特定行为,则很难遵循。它还在组件和 $route
对象之间引入了紧密耦合。但是既然你在你的 beforeEach
钩子中使用它,我会让它留在那里。
那我们怎么办?
我们更改 Post
的路由定义以启用 Passing Props to Route Components
路由定义
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
component: () => import('../views/About.vue')
},
{
path: '/post/:id',
name: 'Post',
// Here we enable the passing of props.
// The boolean mode passes all params defined as props with the same name as the param
// So :id will be available as prop 'id' in the Component.
props: true,
component: () => import('../views/Post.vue')
}
]
现在我们必须将 prop 引入到我们的组件中以备后用。
查看博客页面
<template>
<div class="post">
<h1>{{ blogPost.title }}</h1>
<p>{{ blogPost.text }}</p>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
export default {
props: {
id: {
required: true,
}
},
computed: {
...mapGetters({
blogById: 'blogById',
}),
blogPost() {
return this.blogById(this.id);
},
},
}
</script>
方法一中的 getter 可以写成 getBlog Getter 而不是 getBlogText Getter
VueX Getters
import { createStore } from 'vuex';
export default createStore({
state: {
cards: [{
title: "Blog 1",
text: "This is blog 1",
index: 1,
},
{
title: "Blog 2",
text: "This is blog 2",
index: 2,
},
{
title: "Blog 3",
text: "This is blog 3",
index: 3,
},
{
title: "Blog 4",
text: "This is blog 4",
index: 4,
},
{
title: "Blog 5",
text: "This is blog 5",
index: 5,
},
{
title: "Blog 6",
text: "This is blog 6",
index: 6,
},
{
title: "Blog 7",
text: "This is blog 7",
index: 7,
},
],
},
getters: {
blogById: (state) => (index) => {
// cast both to Number() to prevent unexpected type-mismatch
return state.cards.find(c => Number(c.index) === Number(index));
},
},
});
通过这种方法,您的 title
和 text
显示不再与路由参数紧密耦合,而是与 vueX 的状态反应耦合。
我希望其中一种方法能满足您的需求。