首页 > 解决方案 > 在 Vue.js mongoose 上无法渲染带有引用字段的文档

问题描述

最近,我拿起了Vue.js和Mongoose,开发了一个个人项目,主要是跟踪某款网络游戏中的配料在手数量。

应用图片

不同的菜肴需要不同的食材。Lotus Seed - Bird Egg soup, Jewelry Soup并且Jade Parcels都需要不同数量的Lotus Head成分。我通过updateOne在成分集合上使用来更新成分的数量。

不幸的是,我最初将配料嵌入食物/菜肴中,最近我意识到这是有问题的,因为实际上你只是计算你目前拥有的配料。

所以食物文件现在看起来像这样

{
    "_id" : ObjectId("5fca4ada32195d5814510242"),
    "foodName" : "Lotus Seed and Bird Egg Soup",
    "onHandQty" : 20,
    "ingredients" : [ 
        "5fca481432195d581451023f", 
        "5fca483932195d5814510240", 
        "5fca48a232195d5814510241"
    ]
}

我阅读了有关 Mongoose 的信息populate(),并测试输出一种食物/菜肴。不幸的是,Vue.js在尝试了该代码之后,前端没有任何结果。

服务器/模型/Food.js

const { Router } = require('express');
const FoodItem = require('../../models/Food');
const IngredientItem = require('../../models/Ingredient');

const router = Router()

router.get('/', async(req, res) =>{
    try {
        const food = await FoodItem.findOne({
            foodName: 'Lotus Seed and Bird Egg Soup'
        }).populate('ingredients').
        exec(function (err, food) {
          if (err) return handleError(err);
          console.log('The food is %s', food.foodName);
        });
        res.send(food);
    } catch (error) {
        res.status(500).json({
            message: error.message
        })
    }
});

module.exports = router

渲染成分的组件的一部分

客户端/src/components/Food.vue

<div class="tile is-ancestor">
                    <div class="tile">
                        <div class="tile is-parent">
                            <div class="tile is-child box">
                                <template v-if="food.ingredients">
                                    <div class="ingredients-block">
                                        <p>Ingredients List:</p>
                                        <ul class="ingredients-list">
                                            <li class="row" v-for="ingredient in food.ingredients" :key="ingredient._id">
                                                <div id="ingredient-image-container">
                                                    <img class="image is-64x64" :src="require(`../assets/images/food_inv/${ingredient.imagePath}.png`)" alt="ingredient.ingredientName" :title="ingredient._id">
                                                    {{ingredient.ingredientName}}
                                                </div>
                                                <div class="required-qty-container">
                                                    <!-- <i class="material-icons" id="required-inner-qty">food_bank</i> -->
                                                    Required:
                                                    {{ ingredient.requiredQty }}
                                                </div>
                                                <div class="on-hand-qty-container">
                                                    <p>On Hand:</p>
                                                    <input v-if="ingredient.onHandQty < ingredient.requiredQty" class="input is-danger on-hand-input" type="number" v-model="ingredient.onHandQty" min="0">
                                                    <input v-else class="input is-primary on-hand-input" type="number" v-model="ingredient.onHandQty" min="0">
                                                    <!-- <button class="button is-primary save-button" @click="test({ingredient_id: ingredient._id, onhandqty: ingredient.onHandQty})"><i class="material-icons">save</i></button> -->
                                                    <button class="button is-primary save-button" @click="$emit('update-qtys', {ingredient_id: ingredient._id, onhandqty: ingredient.onHandQty})"><i class="material-icons">save</i></button>
                                                </div>
                                            </li>
                                        </ul>
                                    </div>
                                </template>
                            </div>
                        </div>
                    </div>
                </div>

Github 上的整个项目:食品库存

标签: node.jsmongodbexpressmongoosevuejs2

解决方案


快速修复,

  • 将食物模式的成分字段从对象更改为数组,
const foodSchema = new mongoose.Schema(
    {
        foodName: String,
        imagePath: String,
        effect: String,
        onHandQty: Number,
        // correct this to array
        ingredients:  [{
            type: mongoose.Schema.Types.ObjectId,
            ref: 'Ingredient'
        }]
    }
);
  • 有两种方法可以调用 mongoose 方法,第一种是带有回调的 exec(),第二种是没有 exec() 回调的方法,
  • 带有您使用过的回调的 exec 购买需要从 exec 调用函数内部发送响应(res.send(food)或),res.json(food)
router.get('/', async(req, res) =>{
    try {
        await FoodItem.find()
            .populate('ingredients')
            .exec(function (err, food) {
                if (err) return handleError(err);
                console.log('The food is %s', food);
                // put response here
                res.json(food);
            });
    } catch (error) {
        res.status(500).json({ message: error.message })
    }
});
  • 没有回调的执行
router.get('/', async(req, res) =>{
    try {
        const food = await FoodItem.find() 
            .populate('ingredients')
            .exec();
        res.json(food);
    } catch (error) {
        res.status(500).json({ message: error.message })
    }
});

推荐阅读