美文网首页
KeystoneJS 源码分析(1)

KeystoneJS 源码分析(1)

作者: sinlight | 来源:发表于2017-09-03 22:36 被阅读115次

    KeystoneJS 是一个优秀的并且非常有个性的 Node CMS,数据库使用 MongoDB,而手头的一个项目,因为主要数据库便是 MongoDB,结合当时的需求,评估后采用了 KeystoneJS 作为运营后台的基础。在较短的时间内,达到了不错的应用效果,满足了初期的各项业务迭代需求。

    应用过程中,感受到 KeystoneJS 的文档算是优秀,但作为一个快速发展的开源项目,文档中有些缺失也在所难免,并且文档偏重于纯使用,若有更多改造的需求,分析源码便是个必修课。

    为了更好的满足后续的业务改进需求,便计划分析下 KeystoneJS 的源码,也希望从中学习优秀框架的设计思想。


    一. 沿调用栈(纵向)分析

    1. 调用示例

    • keystone.js

      keystone.import('models')
      ...
      keystone.start()
      
    • models/Project.js

      var Project = new keystone.List('Project', {
          schema: { collection: 't_project' },
          label: '项目',
      })
      
      Project.add({
        name: { type: String, required: true, label: '项目名称'},
        pv: { type: Number, label: 'PV' }
      })
      
      ...
      Project.register()
      

    2. keystone 源码中的核心类型

    List

    • lib/list.js

      module.exports = function (keystone) {
        function List (key, options) {
          var defaultOptions = { 
            schema: {
                      collection: keystone.prefixModel(key),
                  },
                  ...
          };
          ...
          this.options = utils.options(defaultOptions, options)
          ...
          this.schema = new keystone.mongoose.Schema({}, this.options.schema);
          ...
        }
        
        ...
        // 笔记:依赖到 mongo Schema
            Object.defineProperty(this, 'nameIsVirtual', { 
              get: function () {
                  return this.model.schema.virtuals[this.mappings.name] ? true : false
              } 
            })
        ...
        
        List.prototype.add = require('./list/add')
        ...
        List.prototype.field = require('./list/field')
        ...
        return List
      }
      
    • lib/list/add.js

      function add () {
        var add = function(obj, prefix) {
          ...
          var keys = Object.keys(obj)
          for(...keys) {
            // 笔记:addField(path, fieldOptions)
            addField(prefix + key, obj[key])
          }
        }
          
        var addField = function (path, options) {
          ...
          this.uiElements.push({
            type: 'field',
            field: this.field(path, options)
          })
        }.bind(this)
        
        var args = Array.prototype.slice.call(arguments)
        ...
        
        _forEach(args, function (def) {
          
          ...
          add(def);
        }
      }
      

    Field (belongs to List)

    • lib/list/field.js

      function field (path, options) {
        ...
        if (options.type === String) {
          options.type = Field.Types.Number
        }
        ...
        
        // 笔记:new Field(list, path, options)
        var field = new options.type(this, path, options)
        ...
        return field
      }
      
      module.exports = field
      

    Field Type

    • fields/types/number/NumberType.js

      var FieldType = require('../Type');
      ...
      
      function number (list, path, options) {
        this._nativeType = Number
        ...
      }
      
      util.inherits(number, FieldType)
      
    • fields/types/Type.js

      function Field (list, path, options) {
        ...
        this.addToSchema(this.list.schema)
        ...
      }
      
      ...
      
      Field.prototype.addToSchema = function (schema) {
        var ops = (this._nativeType) ? _.defaults({ type: this._nativeType }, this.options) : this.options;
        // 笔记:listSchema.path(field.path, field.options)
        schema.path(this.path, ops)
        ...
      }
      

    二. 沿搜索(横向)分析

    1. 关键词 schema.

    • 依赖 schema 的属性/方法
      • add()
      • path()
      • nested[]
      • virtual()
      • pre()
      • methods
      • paths[]
      • statics
      • collection
      • url
      • mimetype
      • size
    • 依赖 schema 的模块
      • List
        • list.js
        • list/add.js
        • list/buildSearchTextIndex.js
        • list/declaresTextIndex.js
        • list/expandColumns.js
        • list/register.js
      • 一些非基本 Field 类型的 field type, 如 NameType, PasswordType, SelectType, RelationType
      • 一些高级 Field 类型, 如 LocalFilesType, LocationType, MarkdownType
      • schemaPlugins
        • autokey
        • history
        • sortable
        • track
      • lib/storage.js

    2. 关键词 query.{ $(query 相关)

    • fields/types/number/NumberType.js
    • lib/core/createItem.js
    • lib/list/addSearchToQuery.js
    • lib/list/apiForGet.js
    • lib/list/pageinate.js
    • lib/middleware/api.js
    • lib/schemaPlugins/methods/getRelated.js
    • lib/view.js
    • fidleds/types/*Type.js
    • lib/list/addFiltersToQuery.js
    • lib/list/getSearchFilter.js

    .exec

    • lib/core/createItems.js
    • lib/list/apiForGet.js
    • lib/list/getUniqueValue.js
    • lib/list/paginate.js
    • lib/list/updateItem.js
    • lib/schemaPlugins/autokey.js
    • lib/schemaPlugins/methods/getRelated.js
    • lib/schemaPlugins/sortable.js
    • lib/session.js
    • lib/view.js

    相关文章

      网友评论

          本文标题:KeystoneJS 源码分析(1)

          本文链接:https://www.haomeiwen.com/subject/qdqsjxtx.html