Введение
недавно узналreact
, Я давно хотел сделать проект, но у меня нет хорошей идеи. Поскольку я хочу снять дом, я подумал об этом.租房App
Эта идея, относящаяся к приложению для аренды Douban, положила начало такому простому проекту фронтенда и бэкенда😄.
👉Онлайн-демонстрация нажмите здесь
👉Исходный код проекта нажмите здесь, вы можете скачать и запустить его локально, если вам это поможет, вы можете нажатьstar
ха 😁
// 你可以使用npm或yarn
yarn install
运行你的数据库 // 必须!!!
yarn server // 运行服务器, 连接的数据库在server目录下的config.js里配置
yarn start // 运行项目
Во-вторых, передняя часть
- Стек технологий проекта
react+react-router+react-redux
,использоватьcreate-react-app
Поколение строительных лесов. Принятие пользовательского интерфейсаAnt Design Mobile
👉официальный адрес. -
css
Схема css-in-js, с использованиемstyle-jsx
👉гитхаб-адрес, вы можете обратиться к статье о Наггетс 👉кликните сюда. - Так как это мобильный терминал, это неизбежно
适配
проблема, используяvm/vh
Адаптация, вы также можете обратиться к нагрочкам для деталей.эта статья. - в сочетании2, 3В два часа, так как я хочу добавить элемент конфигурации, но не хочу добавлять его в проект
run eject
выскочил, так привыкreact-app-rewired
Переопределите конфиг, чтобы команда не всплывала. 👉гитхаб-адрес - Маршрутизация разрешений. Идея состоит в том, чтобы просмотреть таблицу конфигурации маршрутизации и выбрать авторитетный маршрут, если вам нужно разрешение, и выбрать исходный маршрут, если он вам не нужен. Подробности смотрите в проектеrouterчасть.
- Значок принимает
iconfont SVG
иметь дело с
Просмотр конкретного использованияофициальный адрес.
Возникшие проблемы:
- (Не решено) Изменение CSS в scss в среде разработки dev не будет компилироваться и обновляться в режиме реального времени.
-
(Нерешено) Пройдено под IOS
focus
Событие не может вызвать клавиатуру, оно может быть под Android. Чтобы улучшить пользовательский опыт, я登录,搜索
Когда страница откроется, пусть поле ввода автоматическиfocus
разбудить клавиатуру,IOS
Настоящая машинная практика может вызвать толькоfocus
событие, но не поднимает клавиатуру,安卓
обычный. После проверки информацииIOS
делать ограничения(IOS
Также есть ограничения, что аудио и видео не могут воспроизводиться автоматически). Клавиатура может быть вызвана только после того, как пользователь активно щелкнет поле ввода. При следующем включении клавиатура автоматически проснется, что немного жалко😒!Пока нет решения🙄 -
(решить)Когда вы нажмете детали из списка домашней страницы, вернетесь на домашнюю страницу, вы будетеповторно запросить загрузку,а такжепозиция прокрутки потеряна, пользовательский опыт очень плохой. здесь для обучения
redux
я используюredux
(так же доступноreact
новыйcontext api
) решается, поэтому он также используется в маршрутизацииreact-redux-router
, но больше не поддерживается, изменен наconnect-react-router
гитхаб нажмите здесь. Идея состоит в том, чтобы получить список в первый раз, а затем сохранить его вredux
, в следующий раз, когда вы откроете его, изredux
получено в. -
(решить)
热加载
Не может быть спасенredux
состояние в . Решение: вstore
, добавьте следующий код,Смотрите это подробно
if (module.hot) {
// Reload reducers
module.hot.accept('./reducers', () => {
store.replaceReducer(connectRouter(history)(rootReducer));
});
}
-
(решить??)использовал
react-loadble
Загрузите страницу поиска в проекте, будет поискinput
изplaceholder
Проблема неполного отображения, при первом открытии будут проблемы, при втором открытии проблем не будет, как показано ниже. существуетdev
окружающая среда не может быть воспроизведена,生产环境
Ниже будут проблемы. КомпонентAnt Design Mobile
изsearchBar
. На картинке выше мы видим, что это проблема ширины, которая обычно должна быть110px
, и только тогда, когда это неправильно80px
.Временное решение: убрать ленивую загрузку маршрута и загрузить его напрямую 😏
Оптимизация проекта:
- Маршрут ленивой загрузки, схема:react-loadable,Добавить к
loading
намекать - Ленивая загрузка изображения, схема:lazyload
- Упаковано в компонент 👉специальный код
- Здесь необходимо пояснить, что все изображения, загруженные на Douban на вашем веб-сайте,
403
, поэтому нам нужно использовать следующий веб-сайт для загрузки изображенийкликните сюда,Инструкцииhttps://images.weserv.nl/?url=+图片原来的地址
, обратитесь к ссылке в предыдущем коде для получения подробной информации
-
ajax
По делу можно добавитьloading
подскажите, добавьтеCSS3
Анимации, чтобы сделать взаимодействие более дружелюбным.
3. Бэкенд
- использовать
koa2
+koa-router
+mongodb
+jsonWebToken
. Главное - обратить вниманиеАсинхронная обработка и обработка исключенийЭта проблема. - используемая база данных
Mongoose
работать.Mongoose
находится в асинхронной среде node.jsmongodb
Инструменты объектной модели для удобного манипулирования. Более подробные инструкции можно найти в официальной документации: 👉кликните сюда
3.1 Сканирование данных группы Douban
- использовал
http
библиотекаaxios
. - библиотека запланированных задач,
node-schedule
. гитхаб: 👉кликните сюда - Библиотека рептилий
cheerio
, его использование очень просто.
const cheerio = require('cheerio')
const $ = cheerio.load('<h2 class="title">Hello world</h2>')
Здесь мы можем пройти$(selector)
,картинаjquery
Таким же образом можно получить элементы страницы. Официальная документация: 👉кликните сюда
Весь процесс сканирования:
- При инициализации определите, превышает ли она максимальную длину хранимых данных (в этом проекте база данных настроена на хранение до
5000
данные), еслиПревосходить, удалите его, иначе пропустите. - Запускать запланированное задание каждый день
0.00am
начать ползать=>
Страница со списком сканирования=>
сохранить в базу данных=>
еслипотерпеть неудачу, не будет ползать по течению - страница сведений о ,НапротивПродолжайте сканировать страницу сведений.
- Сканер использует некоторые регулярные выражения для извлечения информации, извлечения арендной платы, контактной информации, типа комнаты, местоположения и т. д. Конкретный код: 👉кликните сюда. Что относится к 👉эта статьянекоторые регулярные выражения в .
Примечание. Douban ограничивает количество посещений IP-адресов в течение периода, поэтому нам необходимо внести некоторые коррективы.
- Интервал сканирования гарантированно будет разным для каждой страницы страницы списка и каждой части данных на странице сведений.(таймер + случайное число)(Кажется бесполезным?)
// sleep
function sleep(time = 0) {
return new Promise(resolve => {
setTimeout(resolve, time);
});
}
// 更新数据库函数
async updateTopic(tid, resolve, reject) {
// 睡眠
await sleep(Math.ceil(Math.random() * 50 * 1000) + 5000);
// 开始更新
await this.fetchDetail(tid).then(houseInfo => {...});
}
- изменить заголовок запроса
user-agent
. Есть проектuser-agent
список 👉Посмотреть код, каждый запрос приносит случайный.
3.2 Хранить в базе данных
Здесь я вставляю несколько фрагментов данных одновременно, используяapi
следующим образом
db.Houses.insertMany([your array data])
3.3 Интерфейс записи (маршрутизация)
Следует отметить, что некоторые маршруты (интерфейсы, доступ к которым возможен только после входа пользователя в систему)header
нужно пройти вtoken
доступ, поэтому добавьтеПроверка промежуточного программного обеспечения маршрутизации,通过校验
После этого доступ разрешается.Ознакомьтесь с подробным кодом здесь. Код ключа следующий👇
const jwt = require('jsonwebtoken');
const token = ctx.header['x-token'];
if(token){
解析token得到用户信息
进入下一个中间件
}else {
返回错误需要传递token
}
В-четвертых, база данных mogodb, связанная с
4.1 Изменить структуру, связанную с базой данных
Приступая к оформлению базы данных, задайте поле ценыprices
Это массив, и тогда я чувствую, что можно использовать строку. Итак, на основе исходной базы измененыФормат данныха такжеимя поляprices
=>price
- Пакетное обновление поля
db.getCollection('houses').find().forEach(function(item){
db.getCollection('houses').update({_id:item._id},{$set:{prices: ''+item.prices}})
})
- изменить имя поля
// 如将字段"prices"改为"price"
db.getCollection('houses').update({},{$rename:{'prices':'price'}}, false, true)
4.2 Прикрепите немного API.
- Репликация базы данных. например, копированиеdouban-houseбазу данных вdouban-test
// db.copyDatabase(<from_dbname>, <to_dbname>, <from_hostname>)
db.copyDatabase('douban-house', 'douban-test')
- Найти в базеДлина массива больше/меньше nДанные
// 大于 exists=1 小于exists=0
db.getCollection('houses').find({'imgs.n':{'$exists':1}})
- Найти в базеполе не пустоеДанные
// $ne=> not equal
db.getCollection('houses').find({'contact':{$ne:null}})
- Найти в базенесколько полейДанные
db.getCollection('houses').find({'tid':{$in:['这里是数组','例如id1','2']}})
Также: Вставьте номера полейNumber Int
Данные о типе хранятся какDouble
тип, с десятичной точкой, например, хранилище10
, после сохранения в базе данных он станет10.0
,Можно использоватьNumberInt
илиNumberLong
хранить
db.houses.insert({"tid": NumberInt(666)})
4.3 Возникшие проблемы
Когда краулер просканирует пост, он доползет до того же поста, и нам эти повторы не нужны. Проблема здесь заключается в том, что при вставке повторяющихся значенийПосле возникновения ошибки оставшиеся данные не будут продолжать вставляться, это очень печальный момент.Вот обходной путь:
- установить первым
mongodb
Единственное значение индексаapi
const housesSchema = new mongoose.Schema({ tid: String, //我这里设置的唯一索引是每条贴子的id号 ...省略 }) housesSchema.index({ tid: 1 }, { unique: true });
- После того, как это установлено, при вставке повторяющегося tid база данных вернет ошибку и не будет вставлять часть данных. Особо нужно сказатьдакэнэто вставленный API либо
insert
ещеinsertMany
, Ихapi
следующим образом
db.collection.insert(
<document or array of documents>,
{
writeConcern: <document>,
ordered: <boolean>
}
)
这里需要注意的是`ordered`这个参数, 这是一个可选参数,官方解释如下
Optional. A boolean specifying whether the mongod instance should perform an ordered or unordered insert. Defaults to true.
大意就是指定mongod实例是否应执行有序插入。默认为```true```。
**重点是:**当有序插入的时候,如果出现了错误,程序会停下当前的插入,不执行插入剩余的数据。只有当无序插入,也就是设置了```ordered: false```,当出现错误之后,才会把剩下的继续插入。官方说明如下:
> Excluding Write Concern errors, ordered operations stop after an error, while unordered operations continue to process any remaining write operations in the queue.
官方文档链接:👉[点击这里](http://docs.mongodb.com/manual/reference/method/db.collection.insertMany)
Пять, связанные с развертыванием (междоменная обработка)
-
стадия развитияесть в проекте
package.json
добавлено вproxy
поле, здесь предполагаетсяhttp://localhost:3003
наш внутренний сервер,http://localhost:3000
Это сервер, на котором разрабатывается реакция Такие как: доступ в проектhttp://localhost:3000/api/house/125048127
будет представленhttp://localhost:3003/api/house/125048127
, междоменной проблемы нет
"proxy": {
"/api": {
"target": "http://localhost:3003"
}
}
- онлайн-средаnginx настроить прокси 👉обратитесь сюда
location /api/ {
proxy_pass http://localhost:3003;
}
Шесть, связанные с git
Иногда, если вы отправляете неправильный код и хотите откатить версию, вам нужно откатить удаленныйgit
Код репозитория, а затем повторите отправку. 👉Подробнее об использовании см. здесь
git reflog // 查看提交列表, 如我需要撤回到第二条提交记录,也就是红线下的那条
git reset --soft 3a2a12d // 这里的参数--soft表示保留本地修改记录, --hard 代表保存本地的记录,如果是--hard 则会清空本地修改记录,也就是你修改的都没有了!!切记!!!
git push -f //强制推送到远程分支