объявление о работе
Дамы и господа, резюме можно отправлять на адрес ivanxjfan@tencent.com.
Пожалуйста, укажите имя резюме в формате: Имя-Должность-Рабочие годы-Место работы (например: Чжан Сан-Внешняя разработка-Пять лет-Чанша.pdf)
Компания:Тенсент
Место:Чанша
Позиция:разработчик веб-интерфейса
Рабочие обязанности:
Отвечает за системные исследования и разработку продуктов Tencent Cloud DNSPod, полные интерфейсные функции системы и реализацию внутреннего логического кода, а также обеспечивает качество продукта и прогресс в исследованиях и разработках.
профессиональные требования:
1. степень бакалавра или выше, майор в компьютере, связанных с компьютером, более 2 лет работы на работе;
2. Владение Javascript, html, css и другими технологиями фронтенд-разработки с прочной базой;
3. Знакомство с текущими основными интерфейсными фреймворками (react/vue и т. д.), приветствуется опыт разработки на React и Redux;
4. Знакомы с протоколами HTTP и TCP/IP, хорошо разбираетесь в вопросах безопасности и знакомы с общими стратегиями атак и защиты в сети;
5. Хорошие аналитические способности и навыки решения проблем, а также энтузиазм в обучении;
6. Приветствуется опыт разработки Node.js/PHP;
7. Предпочтение отдается разработчикам плагинов с опытом работы в WP или DZ
Примечание. Этот пост подготовлен дочерней компанией Tencent Group. сообщение"
Компания:Тенсент
Место:Штаб-квартира Tencent в Шэньчжэне
Позиция:Старший разработчик веб-интерфейса
Рабочие обязанности:
Отвечает за проектирование системной архитектуры и исследования и разработки продуктов Tencent Cloud Domain Name (DNSPod).
профессиональные требования:
1. Степень бакалавра или выше, специальность компьютерная, опыт работы не менее 5 лет;
2. Владение Javascript, html, css и другими технологиями фронтенд-разработки с прочной базой;
3. Знакомство с текущими основными интерфейсными фреймворками (react/vue и т. д.), приветствуется опыт разработки на React и Redux;
4. Знакомы с протоколами HTTP и TCP/IP, хорошо разбираетесь в вопросах безопасности и знакомы с общими стратегиями атак и защиты в области сетевой безопасности;
5. Хорошие аналитические способности и навыки решения проблем, а также энтузиазм в обучении;
6. Приветствуется опыт разработки Node.js/PHP;
предисловие
мы в предыдущей статьеАнализ исходного кода Egg.js — старт проекта, Кратко проанализирован механизм запуска Eggjs и соответствующий ему принцип реализации. Eggjs основан на ряде обычных правил. Когда проект запускается, файлы в соответствующей папке автоматически загружаются для инициализации проекта. Мы можем обратиться к данным на официальном сайтеСтруктура каталогов, чтобы стандартизировать наш проект, включая спецификацию файловой структуры, спецификацию логики кода, чтобы достичь спецификации всего проекта.
Почему существует такоеСтруктура каталогов, на самом деле, это еще для нашей прошлой статьиАнализ исходного кода Egg.js — старт проектаИз анализа при запуске проекта будет загружена следующая конфигурация.За следующим кодом следует примечание, и отмечено только имя файла, соответствующее нашему приложению (имя файла, соответствующее eggjs, не отмечено) loadConfig() {
// your-project-name/config/plugin.js
this.loadPlugin();
// your-project-name/config/config.default.js
// your-project-name/config/`config.${this.serverEnv}`.js
super.loadConfig();
}
load() {
// app > plugin > core
this.loadApplicationExtend();
this.loadRequestExtend();
this.loadResponseExtend();
this.loadContextExtend();
this.loadHelperExtend();
// your_project_name/app.js
this.loadCustomApp();
// your_project_name/app/service/**.js
this.loadService();
this.loadMiddleware();
// your_project_name/app/controller/**.js
this.loadController();
// your_project_name/ app/router.js
this.loadRouter(); // Dependent on controllers
}
Из вышеизложенного мы можем узнать общую структуру нашего приложения.Давайте создадим проект с нуля один за другим и глубоко поймем, как используется Eggjs (спецификация)
Инициализировать проект
Сначала мы используем форму egg-init от egg-init, чтобы инициализировать проект, мы можем запустить следующие команды (я не был связан с разработкой приложений, поэтому я недавно хотел изучить реакцию, поэтому я создал реактивную нативную -обучающий серверный проект):
$ npm i egg-init -g
$ egg-init react-native-learning-server --type=simple
$ cd react-native-learning-server
$ npm i
$ npm run dev
Браузер открывает порт по умолчанию:http://localhost:7001, страница будет отображатьсяhi, egg
, что означает, что наш проект успешно создан.
установить маршрут
Теперь предположим, что мы хотим сделать приложение, похожее на Nuggets, у нас может быть четыре больших меню.Mine , Find , Message, Home
Мы просто разрабатываем несколько API:
Mine:
API | Method | описывать |
---|---|---|
/users | GET | получить всех пользователей |
/user/:id | GET | Получить указанную информацию о пользователе |
/user | POST | Добавить пользователя |
/user/:id | PUT | изменить пользователя |
/user/:id | DELETE | удалить пользователей |
Message:
API | Method | описывать |
---|---|---|
/messages/:userId | GET | Получить всю информацию о пользователе |
/message | POST | Отправить сообщение |
/message/:id | DELETE | удалить указанную информацию |
Find:
API | Method | описывать |
---|---|---|
/search/:keyword | GET | Поиск информации по ключевым словам |
Home:
API | Method | описывать |
---|---|---|
/hot | GET | Запросите самую горячую информацию |
/heart | GET | Горячие точки запроса |
Мы разрабатываем только несколько простых API, как указано выше (в этой статье мы просто хотим реализовать некоторые способы использования Egg через псевдобизнес, сосредоточив внимание на использовании Eggjs).
Выше мы инициализировали проект, теперь редактируемapp/router.js
Для разработки маршрутизации код выглядит следующим образом:
module.exports = app => {
const { router, controller } = app;
router.get('/', controller.home.index);
// User
router.get('/users', controller.user.findAll);
router.get('/user/:id', controller.user.findOne);
router.post('/user', controller.user.add);
router.put('/user/:id', controller.user.update);
router.del('/user/:id', controller.user.delete);
// Message
router.get('/messages/:userId', controller.message.findByUserId);
router.post('/message', controller.message.add);
router.del('/messages/:id', controller.message.delete);
// Find
router.get('/search/:keyword', controller.search.find);
// Home
router.get('/hot', controller.home.findHot);
router.get('/heart', controller.home.findHeart);
};
Давайте сначала проигнорируем реализацию Контроллера, мы уже реализовали нашу маршрутизацию выше, но мы обнаружили проблему, то есть когда проект становится все больше и больше, то этоrouter.jsОн станет больше и сложнее в обслуживании, поэтому мы можем внести следующие коррективы:
- Создайте папку под приложениемrouters, а затем создайте четыре файла, а именно:user.js, message.js, search.js, home.js,
- Затем маршруты в router.js разбиваются, а разные маршруты разбиваются на соответствующие файлы.
- в router.js для ссылки на каждый отдельный маршрут Разделение router.js выглядит следующим образом:
'use strict';
const userRouter = require('./routers/user');
const messageRouter = require('./routers/message');
const homeRouter = require('./routers/home');
const searchRouter = require('./routers/search');
module.exports = app => {
const { router, controller } = app;
router.get('/', controller.home.index);
userRouter(app);
messageRouter(app);
homeRouter(app);
searchRouter(app);
};
Его код routers/user.js выглядит следующим образом:
'use strict';
module.exports = app => {
const { router, controller } = app;
router.get('/users', controller.user.findAll);
router.get('/user/:id', controller.user.findOne);
router.post('/user', controller.user.add);
router.put('/user/:id', controller.user.update);
router.del('/user/:id', controller.user.delete);
};
После описанного выше разделения код router.js становится чистым, а соответствующие маршруты становятся проще в обслуживании.
Настройте управляющий слой (Контроллер)
Мы разработали (настроили) маршрутизатор выше, но все функции обратного вызова маршрутизатора указывают на объекты под контроллером приложения, такие как:controller.user.findAll
Мы проанализировали, откуда берется этот путь в предыдущей главе: контроллер — это объект атрибута приложения (приложения), eggjs вызовет его при запуске.this.loadController();
метод, чтобы загрузить все приложениеapp/controller
Все js-файлы в файле будут использовать имя файла в качестве имени атрибута и монтировать его в объекте app.controller, а затем присоединять все методы, соответствующие экспорту (выставленному) js-файла на объект, имя файла которого атрибут, то вы можете пройтиcontroller.user.findAll
Этот способ относится к методу ниже контроллера.
С этой идеей мы можем очень четко поддерживать наш контрольный слой.Ниже приведен пример нашего дома:
'use strict';
const Controller = require('egg').Controller;
class HomeController extends Controller {
async index() {
this.ctx.body = 'hi , egg.';
}
async findHot() {
this.ctx.body = this.ctx.request.url;
}
async findHeart() {
this.ctx.body = this.ctx.request.url;
}
}
module.exports = HomeController;
Настройка службы
Мы уже разработали маршрутизатор и контроллер, но в нашем контроллере они все статические.Для проекта нам нужно взаимодействовать с базой данных.Мы обычно размещаем контент, который взаимодействует с БД, на уровне службы, и мы разработайте его ниже наш сервис.
Сначала мы создаемserviceкаталог и создайтеuser.js, message.js, search.js, home.js,документ, Мы не подключаемся сначала к реальной базе данных, и созданный сервис выглядит следующим образом (home.js):
'use strict';
const Service = require('egg').Service;
class HomeService extends Service {
async index() {
return 'hi, egg';
}
findHot() {
const hotArticle = [
{
title: 'Title 0001',
desc: 'This is hot article 0001',
},
{
title: 'Title 0002',
desc: 'This is hot article 0002',
},
];
return hotArticle;
}
findHeart() {
const heartArticle = [
{
title: 'Title 0001',
desc: 'This is heart article 0001',
},
{
title: 'Title 0002',
desc: 'This is heart article 0002',
},
];
return heartArticle;
}
}
module.exports = HomeService;
Затем мы модифицируем файл контроллера:
'use strict';
const Controller = require('egg').Controller;
class HomeController extends Controller {
async index() {
this.ctx.body = this.service.home.index();
}
async findHot() {
this.ctx.body = this.service.home.findHot();
}
async findHeart() {
this.ctx.body = this.service.home.findHeart();
}
}
module.exports = HomeController;
Мы вызываем метод службы следующим образом:this.service.home.index();
, аналогично принципу контроллера.
На этом базовая структура нашего проекта построена, и теперь мы можем подумать о том, как подключиться к базе данных.
подключить БД
Мы решили использовать Mongodb для нашей базы данных, поэтому мы можем выбрать использоватьegg-mongoose插件,我们可以按照文档进行操作: Сначала установите плагин:
$ npm i egg-mongoose --save
Поскольку egg-mongoose — это плагин Eggjs, нам нужно настроить этот плагин, сейчас мыapp/config/plugin.js
Настройте плагин в:
'use strict';
module.exports = {
// enable plugins
mongoose: {
enable: true,
package: 'egg-mongoose',
},
};
Далее нам нужно настроить соединение MongoDB, мы модифицируемapp/config/config.default.js
:
'use strict';
module.exports = appInfo => {
const config = exports = {};
// use for cookie sign key, should change to your own and keep security
config.keys = appInfo.name + '_1541735701381_1116';
// add your config here
config.middleware = [];
config.cluster = {
listen: {
path: '',
port: 7001,
hostname: '',
},
};
config.mongoose = {
client: {
url: 'mongodb://127.0.0.1/react-native-demo',
options: {},
},
};
return config;
};
Далее нам нужно настроить модель для MongoDB, мы создаем папку модели в каталоге приложения и создаемuser.js, код показан ниже:
'use strict';
// {app_root}/app/model/user.js
module.exports = app => {
const mongoose = app.mongoose;
const Schema = mongoose.Schema;
const UserSchema = new Schema({
userName: { type: String },
password: { type: String },
});
return mongoose.model('User', UserSchema);
};
Тогда мы собираемся изменитьServiceПриходите к реальному подключению к базе данных, модифицируйтеservice/user.js
код показывает, как показано ниже:
'use strict';
const Service = require('egg').Service;
class UserService extends Service {
async findAll() {
return await this.ctx.model.User.find();
}
}
module.exports = UserService;
Настоящий процесс подключения к базе данных завершен, мы можем его открытьhttp://localhost:7001/users
, на странице будут отображаться все данные, запрошенные из базы данных MongoDB.
Суммировать
- Установите плагин:
$ npm i egg-mongoose --save
- Настройте плагин:
app/config/plugin.js
настроить плагин в - Настраиваем подключение: модифицируем
app/config/config.default.js
, добавить информацию о подключении к яйцу-мангусту - Создать модель: мы в
{app_root}/app/model/user.js
Создайте модель ниже. - Изменить службу: изменить код службы, управлять MongoDB,
await this.ctx.model.User.find();
вопрос
- в предыдущей статьеАнализ исходного кода Egg.js — старт проекта, мы не анализировали, eggjs загрузитсяmodelФайлы в папке Когда здесь загружаются файлы из каталога модели?
- существует
config.default.js
, настройте информацию о подключении мангуста и смонтируйте ее вconfig.mongoose
начальство,mongoose
Является ли имя фиксированным, его можно изменить на другое? - существует
app/config/plugin.js
, настроить информацию о плагине мангуста,mongoose
Является ли имя атрибута фиксированным и может быть изменено на что-то другое?
Отвечать
- В eggjs не реализована загрузкаmodelфункция, ноegg-mongooseЭтот плагин реализует эту функцию, и его код выглядит следующим образом:
function loadModelToApp(app) {
const dir = path.join(app.config.baseDir, 'app/model');
app.loader.loadToApp(dir, 'model', {
inject: app,
caseStyle: 'upper',
filter(model) {
return typeof model === 'function' && model.prototype instanceof app.mongoose.Model;
},
});
}
- должен быть вызван
mongoose
Это имя, потому что в плагине egg-mongoose оно будет напрямую читать приложениеapp.config.mongoose
Конфигурацияconst { client, clients, url, options, defaultDB, customPromise, loadModel } = app.config.mongoose;
, так что правилоegg-mongoose
разработан плагином. - существует
plugin.js
Имя конфигурации не является фиксированным и может быть произвольным, потому что его действительно важная конфигурация:package: 'egg-mongoose'
, указывающий, какой именно пакет используется этим пульгином.
Данные инициализации
Когда проект выходит в сеть, нам часто нужно подготовить некоторые данные для инициализации, например данные пользователя. Обычно мы создаем учетную запись суперадминистратора. Эта учетная запись не требует регистрации пользователя, поэтому мы можем использовать сценарии при инициализации проекта. мы следуем шагам ниже:
- Исправлять
app/model/user.js
Добавить кisMaster
свойства следующим образом:
'use strict';
// {app_root}/app/model/user.js
module.exports = app => {
const mongoose = app.mongoose;
const Schema = mongoose.Schema;
const UserSchema = new Schema({
userName: { type: String, required: true },
password: { type: String, required: true },
isMaster: { type: Boolean, default: false, required: true },
});
return mongoose.model('User', UserSchema);
};
- существует
{app_root}/app
каталог, создайтеdata
папку, затем создайтеuser.json
, содержание которого следующее:
[
{
"userName": "admin",
"password": "admin",
"isMaster": true
}
]
- Поскольку данные должны быть инициализированы при запуске проекта, мы
{app_root}
каталог, добавьтеapp.js
(this.loadCustomApp()), код показан ниже:
'use strict';
// app.js
module.exports = app => {
app.beforeStart(async () => {
if (app.config.initData) {
const initUsers = require('./app/data/user.json');
const ctx = app.createAnonymousContext();
ctx.model.User.create(initUsers, err => {
if (err) {
app.coreLogger.console.warn('[egg-app-beforeStart] init user data fail %s', err);
}
});
}
});
};
Мы добавилиinitData
Переключатель используется, чтобы указать, требуются ли данные инициализации, поскольку данные инициализации обычно требуются в первый раз (эта конфигурация должна быть передана в качестве параметра для запуска команды сценария, что проще в обслуживании, и вам не нужно переходите к config.default.js каждый раз, когда код)
Суммировать
В соответствии с приведенной выше операцией мы в основном завершили базовый скелет проекта, нам нужно только построить на нем блоки и понять основное использование Eggjs.исходный код