我正在创建一个使用 mongodb、node.js、express 和 pug 来记笔记的 Web 应用程序。当我加载主页时,笔记按创建日期的顺序排列。当我单击按钮按字母顺序排列笔记时,笔记会在后端正确排序,但仍按创建日期的顺序显示。我的问题是如何让笔记按字母顺序显示。
我的笔记架构:
const noteSchema = new mongoose.Schema(
{
title: {
type: String,
required: [true, 'You must enter a title.'],
trim: true,
unique: [true, 'A note title must be unique.'],
},
noteText: {
type: String,
trim: true,
},
itemsArr: [
{
type: mongoose.Schema.ObjectId,
ref: 'Item',
},
],
slug: String,
createdAt: {
type: Date,
default: Date.now(),
select: false,
},
user: {
type: mongoose.Schema.ObjectId,
ref: 'User',
required: [true, 'A note must belong to a user.'],
},
doneList: [
{
type: mongoose.Schema.ObjectId,
ref: 'Item',
},
],
},
{
toJSON: { virtuals: true },
toObject: { virtuals: true },
},
)
我的后端代码(按字母顺序返回数据)
我的笔记路线 'router.route('/?sort=title').get(noteController.getAllNotes);'
我的API功能
class APIFeatures {
constructor(query, queryString) {
this.query = query;
this.queryString = queryString;
}
filter() {
const queryObj = { ...this.queryString };
const excludeFields = ['page', 'limit', 'sort', 'fields'];
excludeFields.forEach((el) => delete queryObj[el]);
let queryStr = JSON.stringify(queryObj);
queryStr = queryStr.replace(/\b(gt|gte|lt|lte)\b/g, (match) => `$${match}`);
this.query = this.query.find(JSON.parse(queryStr));
return this;
}
sort() {
if (this.queryString.sort) {
const sortBy = this.queryString.sort.split(',').join(' ');
this.query = this.query.sort(sortBy);
} else {
this.query = this.query.sort('createdAt _id');
}
return this;
}
limitFields() {
if (this.queryString.fields) {
const fields = this.queryString.fields.split(',').join(' ');
this.query = this.query.select(fields);
} else {
this.query = this.query.select('-__v');
}
return this;
}
paginate() {
const page = this.queryString.page * 1 || 1;
const limit = this.queryString.limit * 1 || 100;
const skip = (page - 1) * limit;
this.query = this.query.skip(skip).limit(limit);
return this;
}
}
我的笔记控制器
exports.getAllNotes = catchAsync(async (req, res, next) => {
const features = new APIFeatures(
Note.findOne({ user: req.user.id }),
req.query,
)
.filter()
.paginate()
.sort()
.limitFields();
const notes = await features.query;
if (notes.length === 0) {
return next(new AppError('No notes for this user were found.', 404));
}
res.status(200).json({
status: 'success',
results: notes.length,
notes,
});
});
当我尝试从网页访问此数据时,它会按创建日期的顺序返回数据。
我的前端代码
我的查看路线 'router.get('/sortByTitle', authController.protect, viewController.getHome);'
我的视图控制器
exports.getHome = catchAsync(async (req, res, next) => {
try {
res.status(200).render('home', {
title: 'Home',
date,
today,
});
} catch (error) {
console.log(error);
}
});
我的哈巴狗 html
extends base
block content
main.main
if user
//- - console.log(user.notes)
.container
h1.title-welcome= `Welcome ${user.name.split(' ')[0]}`
h3.date #{today}
p.display-text Display options:
.display-container
.display
p.text Date Created
p.text Alphabetically
label.switch
input#alpha(type='checkbox')
span.slider.round
button.btn.alpha Alpha
a.btn.add-btn(href='/addNote') Add Note
i.fa-solid.fa-plus
form#search-form
.form-group#search-form-group
label.form-label(for='search-title') Search:
#search-input
input.form-input#search-title(type='text' placeholder='Enter note title...')
button.btn.btn-search(title='Search notes')
i.fa-solid.fa-magnifying-glass
- const noNotes = user.notes.length === 0 ? true : false
if noNotes
.notes-container-example
a.btn#btn-exmaple(href='/exampleNote') Example Note
else
.notes-container
each note in user.notes
a.btn.show-note(id=`${note.id}` )= note.title
else
.container
h1.main-title Note It
i.fa-solid.fa-pen-nib
p.main-text One app for keeping all your notes and lists.
.home-btn-container
a.btn(href='/signup' ) Sign Up
a.btn(href='/login' ) Login
我尝试向类名为 alpha 的按钮添加事件侦听器,并调用名为 sortFunction 的函数。这确实检索了我想要的订购数据,但仍然没有将其显示在网页上。
const alphaBtn = document.querySelector('.alpha');
if (alphaBtn) {
alphaBtn.addEventListener('click', (e) => {
e.preventDefault();
sortfunction();
});
}
export const sortfunction = async () => {
try {
const res = await axios('http://127.0.0.1:8080/api/v1/notes/?sort=title');
console.log(res.data);
if (res.data.status === 'success') {
location.assign('/sortByTitle');
}
} catch (error) {
console.log(error);
showAlert(
'error',
'There was an error sorting your notes. Please try again later.',
);
}
};
上面的console.log显示数据正在按照我想要的顺序返回,但我不明白为什么它不能在页面上正确显示。我觉得我的代码中的某个地方可能有冲突。请,任何帮助将不胜感激。
谢谢
这是因为您需要重新加载页面/使用新排序的笔记重新渲染视图。 使用 pug 时使用 Ajax 调用是没有意义的,因此您需要再次渲染视图,但是使用排序的笔记,即 getAllNotes 不应该渲染 json,而是返回排序的笔记 json 到视图渲染/控制器。
要触发此操作,在视图中,您可以添加包含排序查询字符串的链接而不是按钮:
而不是复选框和按钮:
input#alpha(type='checkbox')
添加指向端点的链接,该端点将获取排序的数据,然后重新渲染视图:
a.btn(href='/notes') Sort by date
a.btn(href='/notes?sort=title') Sort by date
因此,您应该创建一个服务于相同视图的单一路由,然后从 getAllNotes 获取笔记,这不会将 json 发送到客户端,而是将排序后的数据返回到控制器以传递到视图。
router.get('/notes', authController.protect, viewController.getHome);
并更改路由处理程序:
// get notes, pass req object to read query, user etc.
const notes = await getAllNotes(req);
// send notes
res.status(200).render('home', {
title: 'Home',
date,
today,
notes
});
您可以对搜索表单等进行同样的操作。