You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过下拉列表调整数组实现Firestore帖子排序,解决const只读报错

报错原因

  • 你使用const关键字声明了constraints变量,JavaScript中const声明的为常量,仅允许首次赋值时写入,后续整体重新赋值会触发只读属性的类型错误,这是你收到报错的直接原因。
  • 逻辑设计存在核心问题:selectPosts是单次执行的异步查询方法,执行完成后就已经返回了首次查询的结果,就算你修改了constraints和queryRef变量,也不会触发页面列表数据的重新加载,根本达不到切换排序刷新列表的效果。
  • 额外缺陷:在数据层直接通过ID获取Vue组件内的DOM元素,会存在组件未渲染获取不到节点、多实例场景ID冲突、多次调用方法重复绑定监听事件等问题,不符合Vue的单向数据流规范。

修复方案

1. 修改下拉组件,通过事件传递选中的排序值

修改dropDonwList.vue,用Vue的双向绑定和事件机制传递排序参数,避免原生DOM操作:

<template>
    <div>
        <select v-model="sortType" @change="handleSortChange">
            <option value="1" selected>按最新排序</option>
            <option value="2">按点赞数排序</option>
        </select>
    </div>
</template>
<script>
export default {
    data() {
        return {
            sortType: '1'
        }
    },
    methods: {
        handleSortChange() {
            // 将选中的排序类型抛出给父组件
            this.$emit('sort-change', this.sortType)
        }
    }
}
</script>

2. 重构查询方法,将排序类型作为入参

修改firestore.dao.js中的selectPosts方法,移除内部的DOM监听逻辑,将排序类型作为参数传入,动态拼接查询条件:

async selectPosts (sortType = '1', {country, city, state, street} = {}) {
    const goodOrderByDir = 'desc'
    const dateOrderByDir = 'desc'
    const db = getFirestore()

    // 抽离公共过滤条件
    const baseConstraints = [
        where('visibility', '==', 'public'),
        where('country', '==', country), 
        where('city', '==', city),
        where('state', '==', state), 
        where('street', '==', street)
    ]
    // 根据传入的排序类型动态生成排序规则
    const orderConstraints = sortType === '1' 
        ? [orderBy('date', dateOrderByDir), orderBy('good', goodOrderByDir)]
        : [orderBy('good', goodOrderByDir), orderBy('date', dateOrderByDir)]

    const allConstraints = [...orderConstraints, ...baseConstraints]
    const queryRef = query(collection(db, 'posts'), ...allConstraints)
    const snapshot = await getDocs(queryRef)

    // 无需多余的Promise.all包裹,map直接返回结果即可
    return snapshot.docs.map(item => {
        this._lastSelectPostsDoc = item
        return { ...item.data() }
    })
}

3. 父组件监听排序变化,重新触发查询

在引入下拉组件的父组件中,监听排序变化事件,调用重构后的selectPosts方法重新拉取数据更新列表:

<template>
  <div>
    <DropDonwList @sort-change="handleSortChange" />
    <!-- 帖子列表渲染逻辑 -->
    <div v-for="post in postList" :key="post.id">{{ post.content }}</div>
  </div>
</template>
<script>
import DropDonwList from './dropDonwList.vue'
import postDao from './firestore.dao.js'

export default {
  components: { DropDonwList },
  data() {
    return {
      postList: [],
      // 你的地址查询参数,根据实际场景赋值
      queryParams: {
        country: '中国',
        city: '上海',
        state: '上海市',
        street: '某某路'
      }
    }
  },
  mounted() {
    // 初始化加载默认排序的帖子
    this.loadPosts('1')
  },
  methods: {
    async loadPosts(sortType) {
      this.postList = await postDao.selectPosts(sortType, this.queryParams)
    },
    handleSortChange(sortType) {
      // 排序切换时重新拉取数据
      this.loadPosts(sortType)
    }
  }
}
</script>

内容的提问来源于stack exchange,提问作者dkskfktldi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 21:54:08