f2e-journey / xueqianban

学前班 - 学前端
http://f2e-journey.github.io/xueqianban/
MIT License
320 stars 56 forks source link

Sails.js 起航 - 后端框架选秀 #49

Open ufologist opened 7 years ago

ufologist commented 7 years ago

Sails.js 请先做个自我介绍吧

Sails is a lightweight framework that sits on top of Express.

对比下 ThinkJS, 可以看到 Sails 的功能更为强大, 当然也就会更加地复杂...

新建一个项目跑起来

具体文档请参考官方的 Getting Started, 新建项目成功后访问 http://localhost:1337/ 来查看效果, 以下示例基于 sails@0.12.11 版本

npm install sails -g

sails new test-sails
cd test-sails
sails lift

由于 Sails 没有自带 autorealod 功能, 开发阶段你修改代码后必须每次重启 sails lift, 这样实在是太麻烦了, 因此推荐开发阶段推荐使用 nodemon 执行 nodemon app.js 来自动重启, 另外 sails console 是一个非常实用的命令行工具.

官方提供的文档只是做了分类, 没有向导似的文档, 让你可以一步接一步从入门到进阶, 因此文档看起来会让人觉得混乱费劲, 建议先从 Controllers 看起.

Controllers

Controllers (the C in MVC) are the principal objects in your Sails application that are responsible for responding to requests from a web browser, mobile application or any other system capable of communicating with a server. They often act as a middleman between your models and views. For many applications, the controllers will contain the bulk of your project’s business logic.

Controllers are comprised of a set of methods called actions. Actions are bound to routes in your application, so that when a client requests the route, the action is executed to perform some business logic and send a response.

完整的 controller 示例

列举了一般开发中所需要的功能

// api/controllers/HelloController.js
// sails generate controller hello index foo bar
//
// blueprint action route 机制会自动创建路由来连接 controller 的方法
// http://sailsjs.com/documentation/concepts/controllers/routing-to-controllers
// http://sailsjs.org/documentation/reference/blueprint-api
//
// 因此对应的路由规则为 /:controllerIdentity/:nameOfAction
// 这里 hello 即为 controller 的 Identity, nameOfAction 即各个方法名
module.exports = {
    // 默认的 action
    // http://sailsjs.com/documentation/reference/configuration/sails-config-blueprints
    // actions: true
    // Whether routes are automatically generated for every action
    // in your controllers (also maps index to /:controller) '/:controller',
    // '/:controller/index', and '/:controller/:action'
    //
    // http://localhost:1337/hello
    index: function(req, res) {
        // 获取 URL
        console.log('url', req.method, req.host, req.url, sails.getBaseUrl());

        // 获取请求参数
        // pathparam 必须在 config/routes.js 中配置 URL Slugs 路由
        // http://sailsjs.com/documentation/concepts/routes/url-slugs
        console.log('pathparam-a', req.params['a']);
        console.log('pathparam-b', req.params['b']);
        console.log('urlparam-c', req.query['c']);
        console.log('GET param', req.query);
        console.log('POST param', req.body);
        console.log('param', req.allParams());

        // 更多的 req res 方法
        // http://sailsjs.com/documentation/reference/request-req
        // http://sailsjs.com/documentation/reference/response-res
        return res.send('index');
    },
    // http://localhost:1337/hello/file
    file: function(req, res) {
        console.log('POST param', req.body);
        // http://sailsjs.com/documentation/concepts/file-uploads
        req.file('fileField').upload(function(err, uploadedFiles) {
            return res.send({
                body: req.body, // 包含 form 表单中除开 file 类型的其他字段的值
                files: uploadedFiles
            });
        });
    },
    // http://localhost:1337/hello/foo
    foo: function(req, res) {
        // 对应 api/responses 中的文件名
        return res.ok({foo: 'bar'});
        // 返回 JSON/JSONP
        // return res.json({a: 1});
        // return res.jsonp({a: 1}); // http://localhost:1337/hello/foo?callback=abc
        // 跳转页面
        // return res.redirect('http://sailsjs.com');
    },
    // http://localhost:1337/hello/global
    global: function(req, res) {
        // [Globals](http://sailsjs.com/documentation/concepts/globals)
        console.log('Globals: The App Object (sails)', sails.config.environment);
        sails.log.info('Globals: Models', Hello.find);
        sails.log.info('Globals: Services', Baz.find);
        return res.send(sails.config.environment);
    },
    // http://localhost:1337/hello/model
    model: function(req, res) {
        // 首先需要配置 api/models/Hello.js 的 attributes 属性来映射数据库字段
        // 否则只会查询出一个 id 字段(必须数据库表也有这个字段)
        // module.exports = {
        //     tableName: 'hello1', // 自定义表名
        //     attributes: {
        //         name: {},
        //         abc: {
        //             columnName: 'name1'
        //         },
        //         name2: {}
        //     }
        // };
        // 通过 Globals 方式来使用 Model
        Hello.find({
            // id: 1
        }).then(function(data) {
            res.ok(data);
        });

        // 指定 SQL 语句执行查询
        Hello.query('select * from hello where id = ?', [2], function(err, rawResult) {
            console.log('sql', rawResult);
        });
    },
    // http://localhost:1337/hello/view
    view: function(req, res) {
        // 变量赋值和模版渲染
        // 默认渲染 views/hello/view.ejs
        return res.view({
            title: '我们一起来学习 Sails',
            author: 'Sun'
        });
    }
};

重点内容

听听吐槽

其他选择

px0078 commented 7 years ago

现在express的教程比较多... koa的 function *(){} 和yield都不熟悉

ufologist commented 7 years ago

@px0078 Express 确实是最流行的, 生态资源相当丰富, 如果是第一次接触后端开发, 可以试一试. Koa 的话算是另一种尝试了, 功能比较单一, 虽然是 Express 团队做出来的, 但生态圈还是差了一大截, 总体来说还不如直接上 ThinkJS

px0078 commented 7 years ago

为了前后端分离和SEO,在尝试前端同构,尤雨溪的示例就是express的,所以打算照着他的改 https://github.com/vuejs/vue-hackernews-2.0