2018年11月26日 星期一

Sails(v1) + Vue.js 完整攻略


Sails(v1) + Vue.js 完整攻略

一、Sails 架構簡易說明

新增sails  : 一句指令搞定
npm install sails -g

開啟新的專案
sails new test-project  開啟新的

依指示進行(選擇1:web App) , sails v1 改版 vue.js 列為為前端工具

啟動專案
sails lift

當然~ 他的網頁架構非常的複雜,一時之間也很難說明,依主架構分如下

1.         Controller : 邏輯層:  依頁面名稱來放置位置

範例1: Page頁面的controller

module.exports = {
  exits: {
    success: {
      viewTemplatePath: 'pages/dispatch/add-cases',
    },

    redirect: {
      description: 'The requesting user is already logged in.',
      responseType: 'redirect'
    }
  },
  fn: async function (inputs, exits) {
    return exits.success();
  }
};

ViewTemplatePath: 使用Pages 頁面,如果沒設定頁面時,通常是用來呼叫資料或存取資料用,例如WEB API

範例2: 傳入資料,並寫入資料
module.exports = {

  inputs: {
    title:{
      required: true,
      type: 'string',
      description:"請說明任務名稱"
     },
     content:{
      required: false,
      type: 'string',
      description:"請說明任務內容"
     },
     caseType:{
      required: true,
      type: 'number',
      description:"任務選項"
     },
     dispatchTime:{
      required: true,
      type: 'string',
      description:"任務日期"
     }
  },

  exits: {
    success: {
      description: 'The message was sent successfully.'
    }

  },
  fn: async function(inputs, exits) {
    console.log(inputs);
    await Cases.create(
      {
        title:inputs.title,
        content:inputs.content,
        caseType:inputs.caseType,
        dispatchTime:inputs.dispatchTime
      }
     );
     console.log(this.req);
    return exits.success();
  }
};

Fn: 函式用inputs 接收頁面傳回的資料,Inputs的值型別,要事先宣告
物件型別,之後透過前端頁面傳入inputs欄位值,並將值存入資料表

直接新增/修改/刪除資料,參考以下官方文件: https://sailsjs.com/documentation/reference/waterline-orm/models
有更多關於資料的methods使用說明

2.         Model : 建立資料層 (建立資料表的欄位)

module.exports = {
  attributes: {
    title: {
      type: 'string'
    },
    content: {
      type: 'string'
    },
    caseType: {
      type: 'number'
    },
    startDate: {
      type: 'string'
    },
    endDate: {
      type: 'string'
    },
    startLocation: {
      type: 'string'
    },
    endLocation: {
      type: 'string'
    }
  },
};

如同資料表,訂好資料模組存取的型態和名稱

3.         Vue.js
引用vue.JS , 讓原本的sails的頁面EJS (HTMLJavaScript) 分離

Assets/JS/pages/ dispatch/list-cases.js :
//sails 中的寫法, parasails.registePage 宣告對應頁面名稱
parasails.registerPage("list-cases",{
    data:{
        lists:[],
    },
    beforeMount: function() {
        // Attach raw data exposed by the server.
        _.extend(this, window.SAILS_LOCALS);//讀取controller傳入參數
      },
      methods: {
        edit(){
            alert("你確定要修改嗎?");
        },
      }
});

如果有從controller端傳回資料到View中,需要事先在beforeMount window.SAILS_LOCALS 加到this 物件中

Views/pages/dispatch/list-cases.ejs (畫面)
//id的值,呼應parasails.registePage,所以id名稱不能重複
<div id="list-cases" v-cloak> 
    <table class="table table-striped">
        <thead>
            <tr>
                <th scope="col">#</th>
                <th scope="col">標題</th>
                <th scope="col">內文</th>
                <th scope="col">日期</th>
                <th>功能</th>
            </tr>
        </thead>
        <tbody>
//list並未喧告在Vue.js, 資料是直接從sailscontroller的值
            <tr v-for="(item, index) in lists">
                <th scope="row">
                    <div class="checkbox">
                        <label><input type="checkbox" value=""></label>
                    </div>
                </th>
                <td>{{item.title}}</td>
                <td>{{item.content}}</td>
                <td>{{item.dispatchTime}}</td>
                <td>
                    <a href=# @click="edit"> <span style="font-size: 18px; color:coral;">
                            <i class="far fa-edit"></i>
                        </span>
                    </a>
                    &nbsp;
                    <a href=#>
                        <span style="font-size: 18px; color: Dodgerblue;">
                            <i class="fas fa-trash"></i>
                        </span>
                    </a>
                </td>
            </tr>
        </tbody>
    </table>
</div>
<%- /* Expose locals as `window.SAILS_LOCALS` :: */ exposeLocalsToBrowser() %>
//在畫面最下面,一定要加這一行
VUE.js要讀取到window.SAILS_LOCALS物件,而這是唯一從sailscontroller讀取傳回參數的方法之一,官方說法,這樣才會安全性,如果有興趣的朋友可以再深入研究相關的話題。

Controller: 
module.exports = {
    exits: {
      success: {
        responseType: 'view',
        viewTemplatePath: 'pages/dispatch/list-cases',
      },
 
      redirect: {
        description: 'The requesting user is already logged in.',
        responseType: 'redirect'
      }
    },
   
    fn: async function (inputs, exits) {
      var lists = await Cases.find();//讀取所有Cases的所有資料列
      return exits.success({lists: lists}); //傳回參數
    }
  };



設定mongoDB

Config /datastores.js

module.exports.datastores = {
  default: {
   adapter: 'sails-mongo',
   url: 'mongodb://root@localhost/foo'
  },
};

如果是本機端有mongoServer : mongodb://root@localhost/dbname  , 如果是遠端mongoDB Server 就要設遠端的連線。

Config/ Model.js
module.exports.models = {
  schema: true,
  migrate: 'alter',
  attributes: {
    createdAt: { type: 'number', autoCreatedAt: true, },
    updatedAt: { type: 'number', autoUpdatedAt: true, },
    id: {  type: 'string', columnName: '_id' },
    //---------------------------------------
    //  /\   Using MongoDB?
    //  ||   Replace `id` above with this instead:
    //
    // ```
    // id: { type: 'string', columnName: '_id' },
    // ```
    //
    // Plus, don't forget to configure MongoDB as your default datastore:
    // https://sailsjs.com/docs/tutorials/using-mongo-db
    //--------------------------------------------------
  },

mongoDB_id取代原本的id項目

設定routing
module.exports.routes = {
 
  'GET /dispatch/addCases': { action: 'dispatch/add-cases' },
  'GET /dispatch/listCases':{ action: 'dispatch/list-cases' },
  'POST  /api/v1/dispatch/saveCases':
 { action: 'dispatch/save-cases' },
};


所有POST/GET 的網址都要在Config/routes.js 設定

設定Assets/JS/ Cloud.setup.js
Cloud.setup({

  /* eslint-disable */
  methods: {"saveCases":
{"verb":"POST","url":"/api/v1/dispatch/saveCases","args":["title","content","caseType","dispatchTime","dispatchTime"]}
  /* eslint-enable */

});

將參數結果送出某個controller (前端語法),再由後端controllerinputs 變數接收下來,參數一定要一致,否則無法傳送到後端喔這很重要!!!!

儲存頁面

列表:
以上是簡單的介紹喔~