根据 select 值更新单独的组件
update seperate component based on select value
我的博客页面包含两个不同的组件 filter
和 card
<template>
<div>
<div v-if='$apollo.loading'>Fetching data...</div>
<div v-else>
<FilterComponent :categories='categories' />
<Card :blogs='blogs' />
</div>
</div>
</template>
<script>
import blogsGQL from '../graphql/blog/blog.graphql'
import categoriesGQL from '../graphql/category/category.graphql'
import Card from '~/components/Blog/Card'
import FilterComponent from '~/components/Blog/FilterComponent'
export default {
name: 'Blogs',
components: { FilterComponent, Card },
layout: 'blog',
apollo: {
blogs: {
query: blogsGQL,
prefetch: true
},
categories: {
query: categoriesGQL,
prefetch: true
}
}
}
</script>
在我的 filterComponent 中,我有一个 select 下拉列表,其中填充了来自数据库的类别,当我 select 在这些类别中触发一个 graphql 查询,它获取由 [= 过滤的新博客帖子66=]
<template>
<div class='w-full bg-gray-200 dark:bg-gray-900 py-10'>
<div class='container mx-auto px-6 flex items-start justify-center'>
<form id='filter' @submit.prevent>
<div class='mt-16 flex flex-col w-full'>
<select id='category'
v-model.number='selected'
class='dark:border-gray-700 pl-3 py-3 shadow-sm rounded text-sm focus:outline-none focus:border-indigo-700 bg-transparent placeholder-gray-500 text-gray-500 dark:text-gray-400'
>
<option value='0' selected>Choose category</option>
<option v-for='category in categories' :key='category.id' :value='category.id'>
{{ category.category }}
</option>
</select>
</div>
</form>
</div>
</div>
</template>
<script>
import blogPostByCategoryId from '~/graphql/blog/blogByCategoryId.graphql'
export default {
name: 'FilterComponent',
props: {
categories: {
type: Array,
required: true
}
},
data() {
return {
selected: 0
}
},
apollo: {
blogPostByCategoryId: {
query: blogPostByCategoryId,
variables() {
return {
category_id: this.selected
}
},
skip() {
return !this.selected
}
}
}
}
</script>
但是如何使用从过滤器组件收到的新数据更新卡片组件?是否可以通过某种方式将 blogPostByCategoryId
结果传回卡片组件?
编辑:
我设法让一些部分工作,我目前在 nuxt 的 store
目录中有一个 index.js
文件,该文件包含以下代码:
import blogsGQL from '~/graphql/blog/blog.graphql'
export const state = () => ({
blogs: []
})
export const actions = {
async nuxtServerInit({ commit }, context) {
const client = context.app.apolloProvider.defaultClient
const response = await client.query({ query: blogsGQL })
commit('setBlogs', response.data.blogs)
}
}
export const mutations = {
setBlogs(state, blogs) {
state.blogs.push(blogs)
},
filter(state, categoryId) {
state.blogs.map(blog => blog.category_id === categoryId)
}
}
我查询我的 graphql api 并将所有帖子放入我的状态,然后在我的父组件中我将数据传递到我的卡片组件,如下所示:
<Card :blogs='blogs' />
computed: {
blogs() {
return this.$store.state.blogs
}
},
现在,我不确定我是不是脑残了,但是当我尝试像这样遍历卡片组件内部的数组时:
<div v-for='blog in blogs'
我得到的都是空白space?我控制台记录了 blogs
数组,数据在其中。
编辑 2:
所以我解决了我之前的问题,不得不使用 state.blogs.push(...blogs)
让它工作。
我在阅读了一些文档后也稍微更改了我的文件我现在使用 getter 来获取 filterblogs :
export const getters = {
filterdBlogs: state => (categoryId) => {
return state.blogs.filter(blog => blog.category_id === categoryId)
}
}
我在我的 filterComponent 内的 apollo update 方法上调用了这个方法:
update(data) {
const id = data.blogByCategoryId[0].category_id
this.$store.getters.filterdBlogs(id)
}
这似乎有效,控制台记录 filterdblogs 方法 returns 正确的项目,但我的卡片组件没有更新。
编辑 3
所以我更改了卡片组件而不是通过道具传递它我现在这样做
//卡片组件
<template>
<div class='w-full bg-gray-200 dark:bg-gray-900 py-10'>
<div class='container mx-auto px-6 flex justify-center'>
<div class='w-full'>
<div v-for='blog in blogs'
:key='blog.id'
class='flex flex-row mx-auto bg-white dark:bg-gray-800 justify-center shadow rounded'>
<div class='w-full lg:w-1/3 px-12 flex flex-col items-center py-10'>
<div class='w-24 h-24 mb-3 p-2 rounded-full bg-gray-200 dark:bg-gray-700 flex items-center justify-center'>
<img class='w-full h-full overflow-hidden object-cover rounded-full'
:src='`https://tuk-cdn.s3.amazonaws.com/assets/components/grid_cards/gc_${blog.id}.png`'
alt='avatar' />
</div>
<h2 class='text-gray-800 dark:text-gray-100 text-xl tracking-normal font-medium mb-1'>{{ blog.title }}</h2>
<p class='text-gray-600 dark:text-gray-100 text-sm tracking-normal font-normal mb-8 text-center w-10/12'>
{{ blog.big_text }}</p>
<p class='text-gray-600 dark:text-gray-100 text-sm tracking-normal font-normal mb-8 text-center w-10/12'>
{{ blog.small_text }}</p>
<div class='flex items-start'>
<div class='mx-6 border-l border-r'>
<NuxtLink :to='`blog/${blog.slug}`'>
<button type='submit'
class='group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500'>
Read more
</button>
</NuxtLink>
</div>
<div class='mx-4 border-l border-r'>
<h2
class='group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white text-black'>
Posted on {{ blog.created_at | formatDate }}
</h2>
</div>
<div class='mx-4 border-l border-r'>
<h2
class='group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white text-black'>
Updated on {{ blog.updated_at | formatDate }}
</h2>
</div>
</div>
</div>
</div>
<!-- Card code block end -->
</div>
</div>
</div>
</template>
<script>
export default {
name: 'Card',
filters: {
formatDate: (dateStr) =>
Intl.DateTimeFormat('us-EN').format(new Date(dateStr))
},
computed: {
blogs() {
return this.$store.state.blogs
}
}
}
</script>
现在,当我 select 下拉菜单中的值时,状态不会更新;
// 下拉组件
<template>
<div class='w-full bg-gray-200 dark:bg-gray-900 py-10'>
<div class='container mx-auto px-6 flex items-start justify-center'>
<form id='filter' @submit.prevent>
<div class='mt-16 flex flex-col w-full'>
<select id='category'
v-model.number='selected'
class='dark:border-gray-700 pl-3 py-3 shadow-sm rounded text-sm focus:outline-none focus:border-indigo-700 bg-transparent placeholder-gray-500 text-gray-500 dark:text-gray-400'
>
<option value='0' selected>Choose category</option>
<option v-for='category in categories' :key='category.id' :value='category.id'>
{{ category.category }}
</option>
</select>
</div>
</form>
</div>
</div>
</template>
<script>
import blogPostByCategoryId from '~/graphql/blog/blogByCategoryId.graphql'
export default {
name: 'FilterComponent',
props: {
categories: {
type: Array,
required: true
}
},
data() {
return {
selected: 0
}
},
apollo: {
blogPostByCategoryId: {
query: blogPostByCategoryId,
variables() {
return {
category_id: this.selected
}
},
skip() {
return !this.selected
},
update(data) {
const id = data.blogByCategoryId[0].category_id
this.$store.commit('filter', {
categoryId: id
})
}
}
}
}
</script>
<style scoped>
</style>
我的过滤方法是这样的:
export const mutations = {
filter(state, payload) {
return state.blogs.filter(blog => blog.category_id === payload.categoryId)
}
}
你在改变 Vuex 状态时犯了错误。正确的变异格式:
export const state = () => ({
blogs: [],
search: null //if you want multiselect you must use array [] with ids
})
export const getters = {
filterBlog(state, payload) {
return state.search ? state.blogs.filter(blog => +blog.category_id === +state.search) : state.blogs
}
}
export const mutations = {
setBlogs(state, blogs) {
state.blogs.push(blogs)
},
search(state, id) {
state.search = id
}
}
卡片组件:
<div v-for='blog in blogs'>
computed: {
blogs() {
return this.$store.getters.filterBlog
}
}
下拉组件:
update(data) {
const id = data.blogByCategoryId[0].category_id
this.$store.commit('search', id)
}
在 Vuex 中,您可以直接更改当前状态,而不是像在 Redux Reducer 中那样返回一个新状态。
我的博客页面包含两个不同的组件 filter
和 card
<template>
<div>
<div v-if='$apollo.loading'>Fetching data...</div>
<div v-else>
<FilterComponent :categories='categories' />
<Card :blogs='blogs' />
</div>
</div>
</template>
<script>
import blogsGQL from '../graphql/blog/blog.graphql'
import categoriesGQL from '../graphql/category/category.graphql'
import Card from '~/components/Blog/Card'
import FilterComponent from '~/components/Blog/FilterComponent'
export default {
name: 'Blogs',
components: { FilterComponent, Card },
layout: 'blog',
apollo: {
blogs: {
query: blogsGQL,
prefetch: true
},
categories: {
query: categoriesGQL,
prefetch: true
}
}
}
</script>
在我的 filterComponent 中,我有一个 select 下拉列表,其中填充了来自数据库的类别,当我 select 在这些类别中触发一个 graphql 查询,它获取由 [= 过滤的新博客帖子66=]
<template>
<div class='w-full bg-gray-200 dark:bg-gray-900 py-10'>
<div class='container mx-auto px-6 flex items-start justify-center'>
<form id='filter' @submit.prevent>
<div class='mt-16 flex flex-col w-full'>
<select id='category'
v-model.number='selected'
class='dark:border-gray-700 pl-3 py-3 shadow-sm rounded text-sm focus:outline-none focus:border-indigo-700 bg-transparent placeholder-gray-500 text-gray-500 dark:text-gray-400'
>
<option value='0' selected>Choose category</option>
<option v-for='category in categories' :key='category.id' :value='category.id'>
{{ category.category }}
</option>
</select>
</div>
</form>
</div>
</div>
</template>
<script>
import blogPostByCategoryId from '~/graphql/blog/blogByCategoryId.graphql'
export default {
name: 'FilterComponent',
props: {
categories: {
type: Array,
required: true
}
},
data() {
return {
selected: 0
}
},
apollo: {
blogPostByCategoryId: {
query: blogPostByCategoryId,
variables() {
return {
category_id: this.selected
}
},
skip() {
return !this.selected
}
}
}
}
</script>
但是如何使用从过滤器组件收到的新数据更新卡片组件?是否可以通过某种方式将 blogPostByCategoryId
结果传回卡片组件?
编辑:
我设法让一些部分工作,我目前在 nuxt 的 store
目录中有一个 index.js
文件,该文件包含以下代码:
import blogsGQL from '~/graphql/blog/blog.graphql'
export const state = () => ({
blogs: []
})
export const actions = {
async nuxtServerInit({ commit }, context) {
const client = context.app.apolloProvider.defaultClient
const response = await client.query({ query: blogsGQL })
commit('setBlogs', response.data.blogs)
}
}
export const mutations = {
setBlogs(state, blogs) {
state.blogs.push(blogs)
},
filter(state, categoryId) {
state.blogs.map(blog => blog.category_id === categoryId)
}
}
我查询我的 graphql api 并将所有帖子放入我的状态,然后在我的父组件中我将数据传递到我的卡片组件,如下所示:
<Card :blogs='blogs' />
computed: {
blogs() {
return this.$store.state.blogs
}
},
现在,我不确定我是不是脑残了,但是当我尝试像这样遍历卡片组件内部的数组时:
<div v-for='blog in blogs'
我得到的都是空白space?我控制台记录了 blogs
数组,数据在其中。
编辑 2:
所以我解决了我之前的问题,不得不使用 state.blogs.push(...blogs)
让它工作。
我在阅读了一些文档后也稍微更改了我的文件我现在使用 getter 来获取 filterblogs :
export const getters = {
filterdBlogs: state => (categoryId) => {
return state.blogs.filter(blog => blog.category_id === categoryId)
}
}
我在我的 filterComponent 内的 apollo update 方法上调用了这个方法:
update(data) {
const id = data.blogByCategoryId[0].category_id
this.$store.getters.filterdBlogs(id)
}
这似乎有效,控制台记录 filterdblogs 方法 returns 正确的项目,但我的卡片组件没有更新。
编辑 3
所以我更改了卡片组件而不是通过道具传递它我现在这样做
//卡片组件
<template>
<div class='w-full bg-gray-200 dark:bg-gray-900 py-10'>
<div class='container mx-auto px-6 flex justify-center'>
<div class='w-full'>
<div v-for='blog in blogs'
:key='blog.id'
class='flex flex-row mx-auto bg-white dark:bg-gray-800 justify-center shadow rounded'>
<div class='w-full lg:w-1/3 px-12 flex flex-col items-center py-10'>
<div class='w-24 h-24 mb-3 p-2 rounded-full bg-gray-200 dark:bg-gray-700 flex items-center justify-center'>
<img class='w-full h-full overflow-hidden object-cover rounded-full'
:src='`https://tuk-cdn.s3.amazonaws.com/assets/components/grid_cards/gc_${blog.id}.png`'
alt='avatar' />
</div>
<h2 class='text-gray-800 dark:text-gray-100 text-xl tracking-normal font-medium mb-1'>{{ blog.title }}</h2>
<p class='text-gray-600 dark:text-gray-100 text-sm tracking-normal font-normal mb-8 text-center w-10/12'>
{{ blog.big_text }}</p>
<p class='text-gray-600 dark:text-gray-100 text-sm tracking-normal font-normal mb-8 text-center w-10/12'>
{{ blog.small_text }}</p>
<div class='flex items-start'>
<div class='mx-6 border-l border-r'>
<NuxtLink :to='`blog/${blog.slug}`'>
<button type='submit'
class='group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500'>
Read more
</button>
</NuxtLink>
</div>
<div class='mx-4 border-l border-r'>
<h2
class='group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white text-black'>
Posted on {{ blog.created_at | formatDate }}
</h2>
</div>
<div class='mx-4 border-l border-r'>
<h2
class='group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white text-black'>
Updated on {{ blog.updated_at | formatDate }}
</h2>
</div>
</div>
</div>
</div>
<!-- Card code block end -->
</div>
</div>
</div>
</template>
<script>
export default {
name: 'Card',
filters: {
formatDate: (dateStr) =>
Intl.DateTimeFormat('us-EN').format(new Date(dateStr))
},
computed: {
blogs() {
return this.$store.state.blogs
}
}
}
</script>
现在,当我 select 下拉菜单中的值时,状态不会更新;
// 下拉组件
<template>
<div class='w-full bg-gray-200 dark:bg-gray-900 py-10'>
<div class='container mx-auto px-6 flex items-start justify-center'>
<form id='filter' @submit.prevent>
<div class='mt-16 flex flex-col w-full'>
<select id='category'
v-model.number='selected'
class='dark:border-gray-700 pl-3 py-3 shadow-sm rounded text-sm focus:outline-none focus:border-indigo-700 bg-transparent placeholder-gray-500 text-gray-500 dark:text-gray-400'
>
<option value='0' selected>Choose category</option>
<option v-for='category in categories' :key='category.id' :value='category.id'>
{{ category.category }}
</option>
</select>
</div>
</form>
</div>
</div>
</template>
<script>
import blogPostByCategoryId from '~/graphql/blog/blogByCategoryId.graphql'
export default {
name: 'FilterComponent',
props: {
categories: {
type: Array,
required: true
}
},
data() {
return {
selected: 0
}
},
apollo: {
blogPostByCategoryId: {
query: blogPostByCategoryId,
variables() {
return {
category_id: this.selected
}
},
skip() {
return !this.selected
},
update(data) {
const id = data.blogByCategoryId[0].category_id
this.$store.commit('filter', {
categoryId: id
})
}
}
}
}
</script>
<style scoped>
</style>
我的过滤方法是这样的:
export const mutations = {
filter(state, payload) {
return state.blogs.filter(blog => blog.category_id === payload.categoryId)
}
}
你在改变 Vuex 状态时犯了错误。正确的变异格式:
export const state = () => ({
blogs: [],
search: null //if you want multiselect you must use array [] with ids
})
export const getters = {
filterBlog(state, payload) {
return state.search ? state.blogs.filter(blog => +blog.category_id === +state.search) : state.blogs
}
}
export const mutations = {
setBlogs(state, blogs) {
state.blogs.push(blogs)
},
search(state, id) {
state.search = id
}
}
卡片组件:
<div v-for='blog in blogs'>
computed: {
blogs() {
return this.$store.getters.filterBlog
}
}
下拉组件:
update(data) {
const id = data.blogByCategoryId[0].category_id
this.$store.commit('search', id)
}
在 Vuex 中,您可以直接更改当前状态,而不是像在 Redux Reducer 中那样返回一个新状态。