Nodejs 下拉框的显示问题

Nodejs 下拉框的显示问题

下拉框是ul li的方式,不过li下面还有一个ul,li所以我在mongo中设计的两张表,它们通过id和fatherid相关联。 自己照着书写了一个数据库的get方法,在尝试显示外层的ul时,ok显示正常。后来尝试开始写个字的下拉框里的内容,之前显示外层ul的时候,我们是传了一个空给get方法查询所有结果,然后遍历它,这里我的想法是这样的,在遍历的for循环中,我可以得到每个外层ul的id,然后去匹配内层ul的fatherid,想法不错,这相当于是在for循环中,不停执行get方法,后来系统报错了。 不知道我说没说明白,如果谁有做过多级的下拉框的显示时,分享一下你们的心得,谢谢了


6 回复

针对你提到的“Nodejs 下拉框的显示问题”,可以理解为在处理多级下拉菜单(例如,具有嵌套结构的列表)时遇到了一些挑战。下面我将提供一个简单的示例来展示如何使用Node.js和MongoDB来获取并渲染这种嵌套结构的数据。

数据库设计

假设你有两个集合(或表):categoriessubcategories。其中,categories 包含顶级分类,而 subcategories 包含子分类,并且有一个字段 fatherId 来关联到父分类。

示例数据

// categories
[
    {
        "_id": "category1",
        "name": "Electronics"
    }
]

// subcategories
[
    {
        "_id": "subcategory1",
        "categoryId": "category1",
        "name": "Smartphones"
    },
    {
        "_id": "subcategory2",
        "categoryId": "category1",
        "name": "Laptops"
    }
]

Node.js 后端逻辑

首先,我们需要创建一个API来获取所有分类及其子分类:

const express = require('express');
const mongoose = require('mongoose');

mongoose.connect('mongodb://localhost:27017/mydatabase', { useNewUrlParser: true, useUnifiedTopology: true });

const Category = mongoose.model('Category', new mongoose.Schema({ name: String }));
const Subcategory = mongoose.model('Subcategory', new mongoose.Schema({ categoryId: String, name: String }));

const app = express();

app.get('/categories', async (req, res) => {
    const categories = await Category.find();
    const subcategories = await Subcategory.find();

    // 将子分类归类到各自的父分类
    const categorizedSubcategories = subcategories.reduce((acc, subcat) => {
        if (!acc[subcat.categoryId]) acc[subcat.categoryId] = [];
        acc[subcat.categoryId].push(subcat);
        return acc;
    }, {});

    res.json(categories.map(category => ({
        ...category._doc,
        subcategories: categorizedSubcategories[category._id] || []
    })));
});

app.listen(3000, () => console.log('Server running on port 3000'));

前端HTML与JavaScript

接下来,我们将前端HTML结构与JavaScript结合起来,以动态加载和渲染这些数据:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Dropdown Example</title>
</head>
<body>
<ul id="mainMenu"></ul>

<script>
fetch('/categories')
    .then(response => response.json())
    .then(data => {
        const mainMenu = document.getElementById('mainMenu');
        data.forEach(category => {
            const categoryItem = document.createElement('li');
            categoryItem.textContent = category.name;

            const subMenu = document.createElement('ul');
            category.subcategories.forEach(subcategory => {
                const subItem = document.createElement('li');
                subItem.textContent = subcategory.name;
                subMenu.appendChild(subItem);
            });

            categoryItem.appendChild(subMenu);
            mainMenu.appendChild(categoryItem);
        });
    });
</script>
</body>
</html>

以上就是一种基本的实现方式,你可以根据具体需求进行调整。希望这对解决你的问题有所帮助!


这种问题不上代码就是耍流氓嘛

其实问题就是for循环里不停地去请求查询mongo数据库,我的想法是这样的,但是系统报db object already connecting ,open cannot be called multiple times,看来不能多次请求,我的做法是错的

现在功能实现,但方法不好,通过mongo数据库的两次全查询,将两次的结果集返回到页面上,在页面上通过两次for,根据主外键关系匹配,完成要求的显示。(唉,真心不给力)。发问了,mongo数据库不支持循环查询么,或者说如果想循环查询mongo,该如何实现?

可以 for 循环 不过注意是否出现闭包问题就好了,我这里给一段我写得代码给你参考

	for(i = 0; i<articles_id.length; i++){
		(function(i){
			where = {_id: articles_id[i]}
			get_article_by_query_once(where, function(err, article, author, edit, tags, replies){
				if(err) return cb(err);
				article.author = author;
				article.edit = edit;
				article.create_at = Util.format_date(article.create_time);
				article.update_time = Util.format_date(article.update_at);
				article.tags = tags;
				article.reply = replies;
				if(article.last_reply_at){
					article.last_reply_time = Util.format_date(article.last_reply_at);
				}
				articles[i] = article;
				proxy.trigger('articles.ready');
			});
		})(i);
	}

根据你的描述,你想要实现一个多级下拉菜单,并且数据存储在MongoDB中,使用父子ID关联来表示层级关系。你可以通过递归的方式来获取多级下拉菜单的数据,而不是在每个父元素上都调用一次get方法。

示例代码

数据库模型

假设你有两个集合:itemssubItems

// items集合
const ItemSchema = new mongoose.Schema({
    name: String,
    fatherId: { type: mongoose.Schema.Types.ObjectId, ref: 'Item' }
});

// subItems集合
const SubItemSchema = new mongoose.Schema({
    name: String,
    itemId: { type: mongoose.Schema.Types.ObjectId, ref: 'Item' }
});

获取数据的方法

我们可以先获取顶层的项目,然后通过递归的方式来获取子项。

async function getDropdownData() {
    // 获取顶层项目
    const topItems = await Item.find({ fatherId: null });
    
    // 递归函数获取子项
    function fetchChildren(items) {
        return Promise.all(items.map(async item => {
            const subItems = await SubItem.find({ itemId: item._id }).populate('itemId');
            item.children = subItems;
            
            if (subItems.length > 0) {
                item.children = await fetchChildren(subItems);
            }
            
            return item;
        }));
    }

    const dropdownData = await fetchChildren(topItems);
    return dropdownData;
}

渲染下拉菜单

你可以使用模板引擎(如EJS)来渲染这些数据。

<ul id="dropdown">
    <% for (let item of dropdownData) { %>
        <li><%= item.name %>
            <% if (item.children && item.children.length > 0) { %>
                <ul>
                    <% for (let child of item.children) { %>
                        <li><%= child.name %></li>
                    <% } %>
                </ul>
            <% } %>
        </li>
    <% } %>
</ul>

解释

  1. 数据库模型:定义了两个集合,items 表示顶级项目,subItems 表示子项。
  2. 获取数据:首先获取顶层项目,然后通过递归函数获取子项,避免了多次调用get方法。
  3. 渲染下拉菜单:使用模板引擎将数据渲染到HTML页面上。

通过这种方式,你可以高效地获取并渲染多级下拉菜单。希望这能帮助你解决当前的问题!

回到顶部