codekissyoung

codekissyoung 查看完整档案

北京编辑中国地质大学(北京)  |  地质学 编辑深圳卡尔酷软件  |  php工程师 编辑 codekissyoung.com 编辑
编辑

coder

个人动态

codekissyoung 关注了专栏 · 8月30日

GO语言笔记

GO笔记

关注 7

codekissyoung 关注了专栏 · 6月1日

这里好像没有人的技术分享

干货总结分享

关注 10

codekissyoung 关注了用户 · 2月29日

宜信技术学院 @crediteasetech

宜信技术学院是宜信旗下的金融科技能力展示与输出平台。通过分享在金融科技领域的开源成果、研发实践促进金融科技生态圈企业创新升级。

关注 2364

codekissyoung 赞了文章 · 2月10日

使用Prometheus针对自己的服务器采集自定义的参数

用一个简单的例子来说明。

我用express和http搭了一个最简单的服务器,监听在8081端口上。

clipboard1,1

在metrics endpoint上,我会打印出这个服务器从启动至今,服务了多少次请求。这里我只是简单使用一个维护在memory中的计数器来模拟服务请求个数。每次metrics被请求,计数器加一。
localhost:8081/metrics测试一下:

clipboard2,2

打开Prometheus服务器的配置文件prometheus.yml:

clipboard3,3

添加一条作业,static_configs的target配置成我自己的服务器 localhost:8081.

localhost:9090访问Prometheus的web UI:

clipboard4,4

切换到图形界面,即可看到随时间推移,我的服务器响应了服务请求的趋势图。横轴为时间点,纵轴为Prometheus服务器从我的测试服务器每隔默认的15秒收集到的服务响应请求。

clipboard5,5

要获取更多Jerry的原创文章,请关注公众号"汪子熙":
公众号截图

查看原文

赞 2 收藏 0 评论 0

codekissyoung 关注了标签 · 2月10日

prometheus

一个开源的 Docker 容器监控工具,基于时间序列。

关注 47

codekissyoung 回答了问题 · 2019-11-19

有10亿个整数,怎么设计散列函数,让它们均匀分布?

(整数) mod (大于10亿的最小素数)

(整数) mod (大于10亿的最小素数) 作为数组下标,下标的个数是够了,对素数取模的话,理论上来说,不同整数 计算出 相同下标值 的 概率 会比较小。这样 10 亿个整数 可以看成是 均匀分布的吧 !

关注 4 回答 1

codekissyoung 赞了回答 · 2019-10-25

解决文件空洞apue

这是原文,翻译的锅?
clipboard.png

关注 2 回答 1

codekissyoung 提出了问题 · 2018-12-26

这段C#加密方式是什么意思,能翻译成PHP么?

public static string Encrypt(string Text, string sKey)
{
    DESCryptoServiceProvider dESCryptoServiceProvider = new DESCryptoServiceProvider();
    byte[] bytes = Encoding.Default.GetBytes(Text);
    dESCryptoServiceProvider.Key = Encoding.ASCII.GetBytes(FormsAuthentication.HashPasswordForStoringInConfigFile(sKey, "md5").Substring(0, 8));
    dESCryptoServiceProvider.IV = Encoding.ASCII.GetBytes(FormsAuthentication.HashPasswordForStoringInConfigFile(sKey, "md5").Substring(0, 8));
    MemoryStream expr_5B = new MemoryStream();
    CryptoStream expr_68 = new CryptoStream(expr_5B, dESCryptoServiceProvider.CreateEncryptor(), CryptoStreamMode.Write);
    expr_68.Write(bytes, 0, bytes.Length);
    expr_68.FlushFinalBlock();
    StringBuilder stringBuilder = new StringBuilder();
    byte[] array = expr_5B.ToArray();
    for (int i = 0; i < array.Length; i++)
    {
        byte b = array[i];
        stringBuilder.AppendFormat("{0:X2}", b);
    }
    return stringBuilder.ToString();
}

问题出现的环境背景及自己尝试过哪些方法

相关代码

// 请把代码文本粘贴到下方(请勿用图片代替代码)

你期待的结果是什么?实际看到的错误信息又是什么?

关注 1 回答 0

codekissyoung 提出了问题 · 2018-12-01

Mac下开发linux c程序,VS Code如何配置才能提示Linux下的专有库(比如epoll)定义的变量?

  1. 我在Mac下使用vs code 写 Linux c程序,自动同步到我远程Linux服务器机器上编译测试运行。
  2. 因为要使用 <epoll.h> 库, 里面的各种常量定义,在vs code下是没有提示的,或者提示该常量未定义,很不爽,问下有木有方法让Vscode 在Mac下也能识别epoll库?

clipboard.png

关注 1 回答 0

codekissyoung 提出了问题 · 2018-12-01

Mac下开发linux c程序,VS Code如何配置才能提示Linux下的专有库(比如epoll)定义的变量?

  1. 我在Mac下使用vs code 写 Linux c程序,自动同步到我远程Linux服务器机器上编译测试运行。
  2. 因为要使用 <epoll.h> 库, 里面的各种常量定义,在vs code下是没有提示的,或者提示该常量未定义,很不爽,问下有木有方法让Vscode 在Mac下也能识别epoll库?

clipboard.png

关注 1 回答 0

codekissyoung 提出了问题 · 2018-11-30

Mac下开发linux c程序,VS Code如何配置才能提示Linux下的专有库(比如epoll)定义的变量?

  1. 我在Mac下使用vs code 写 Linux c程序,自动同步到我远程Linux服务器机器上编译测试运行。
  2. 因为要使用 <epoll.h> 库, 里面的各种常量定义,在vs code下是没有提示的,或者提示该常量未定义,很不爽,问下有木有方法让Vscode 在Mac下也能识别epoll库?

clipboard.png

关注 1 回答 0

codekissyoung 赞了文章 · 2018-11-23

对 SegmentFault 社区提问标准的一些解释

有心的用户应该发现最近 SegmentFault 问答的审核趋向严格,甚至一些已经正常展示的问题都会因质量问题提示作者修改。随着社区用户的增长,新进入用户的习惯正逐渐冲击着之前社区形成的默契,我们的问答质量出现了一定程度的下降。这对整个社区的运营提出了挑战,我们不希望发生劣币驱逐良币的状况,因此有必要在这个问题上达成新的共识。

应该说 SegmentFault 的提问一直都是有具体的标准的(https://segmentfault.com/faq#...),但是在具体理解的时候每个人都会产生偏差,为了尽量缩小这个偏差,我们约定如下几个提问的原则:

  1. 回答者优先
  2. 考虑后来者

回答者优先

当你理解了回答者优先的原则,就会自然而然地理解我们的运营规范,甚至你都不需要时刻记住这些规范,因为它们只是保证这一原则的最低要求。

什么是回答者优先?简而言之,就是你在提问的时候要优先考虑回答者能否清晰准确地知晓你要表达的意思,我们在审核的时候也是以这一条标准做为最优先的准则。提问者怎么判断呢?很简单,把自己置于回答者的位子上去审视一下你的问题,看看做为回答者的你是否可以通过这些表述知晓题意。

以这条原则为出发点,我们会对存在以下情况的问题说不:

  1. 问题表述过于简略,往往就一句话甚至一个标题的。(举例:标题是“如何实现一个淘宝一样的网站?”,内容是:“如题”)
  2. 问题中完全没有自己的观点,也就是传说中的伸手党。伸手党的存在主要有两大害处,第一,你没有说出已经尝试过哪些方法,没有尽量为回答者排除错误情况,会大大降低回答者的答题效率。第二,你的付出过少,无法达到回答者的心里预期,会大大影响回答者的答题积极性。用通俗的话说就是,你自己都不重视自己的事情,其他人又凭什么去帮你呢?
  3. 问题的排版过于混乱。从语法上讲,我们并不认为 Markdown 语法比你手上要写的任何编程语言语法更加复杂。而混乱的排版至少表明你并不重视这个问题,也不重视回答者的感受。很多人没有把代码用 Markdown 包裹起来,我们也视为排版混乱。
  4. 没有代码或者用图片代替了代码。这是一个最近比较突出的问题,代码胜千言,准确简短的描述配上必要的代码,比你说一大堆废话要好得多,我们已经看到了无数可爱的回答者在问题下方的评论中呼唤代码。与不贴代码相比,用代码截图来代替代码走入了另一个误区,让我们还是站在回答者的角度,当你面对上百行没头没尾的代码时,怎么去调试它们呢?你想让回答者浪费自己宝贵的时间,照着你们的图片一个字一个字的敲进去么?所以,当你要这么做的时候,想一想本章的标题“回答者优先”。在这里,还有一个比较特殊的情况,就是错误信息算不算代码,可不可以用截图代替?在这里,给出明确的答复:算。大部分的错误信息,包括浏览器的出错,c, java等预编译语言的运行时错误,都是一个简单的文本,你可以直接用鼠标选中复制,用 Markdown 的代码块语法包裹后附加到问题里。这样可以大大方便回答者定位错误。

考虑后来者

考虑后来者可以说是我们创建这个社区的一大目的,我们之所以让大家的问题可以公开讨论,就是为了降低在开发领域的信息不对称,让后来者少走弯路。为了做到这一点,我们提倡大家:

  1. 标题应该直接地表达问题的中心思想,如果你是因为运行时抛出某些错误而提问,你可以直接写“为什么JAVA运行时抛出xxxx异常?”。而不要写什么“一个关于JAVA的问题?”,请问做为一个后来者,我能从你的标题里获得什么重要的信息呢?如果这则问题被搜索引擎索引了,后来者遇到同类问题是怎么搜索的呢?大家想想你们搜问题,是不是喜欢把错误信息直接丢到搜索框里,那么怎样才算一个有用的问题就不言而喻了。
  2. 不要用图片代替代码,不要用图片代替代码,不要用图片代替代码!图片里的内容不能被任何搜索引擎检索到,你的问题会变成信息海洋里的垃圾沉没水底,这不是我们做为社区所提倡的。
  3. 用好标签。标签的作用在于更好地组织内容,这也是为了方便后来者。所以首先不要滥用,你的标签一定要跟问题相关。其次,标签不是用来描述问题的,不要自己创造一些描述性的语言做为标签。通常选择标签就选择这个问题所涉及到的技术就可以了,而且尽量至少使用一个大的语言标签,比如“php, java, c, javascript” 等等。

一些措施

俗话说“用霹雳手段,显菩萨心肠”,我们的菩萨心肠在上面已经告诉大家了。为了保证这些目的能够达到,我们将采取一系列措施。除了在审核时我们会严格按照标准来执行之外,我们还鼓励大家共同维护社区的秩序。大家可以通过评论来提醒一些违规的内容,或者使用举报和建议关闭功能。

我们针对把代码截图到图片里的行为,专门开发了自动扫描机器人,它会最大程度地去监控这一行为,一旦发现这一情况会提醒你修改问题。如果在一小时内没有修改的话,这个问题会被提交人工审核后处理。注意:机器人可能存在误判行为,如果你确定你的内容没有存在这种情况,请放心交给我们人工审核即可,我们会及时处理。

写在最后

当我们在6年前创立 SegmentFault 的时候,愿景是做一个高质量的中文技术问答社区。当然现在 SegmentFault 上承载的不止有问答的内容,但它依然是整个社区重要的组成部分。经常有人向我们抱怨国内技术社区的讨论氛围,思想浮躁,问题质量差,伸手党盛行等等。当我们体量比较小的时候,我们总是以提高素质还需要时间之类的理由来安慰自己或者他人。而当我们逐渐成长为国内技术问答领域一支重要力量之后,我们已经无法逃避肩上的责任,因此我们希望带领整个社区一起进步,共同打造一个属于我们自己的技术家园。

更多阅读

查看原文

赞 143 收藏 11 评论 54

codekissyoung 关注了专栏 · 2018-09-04

codingstudy

编程文章

关注 17

codekissyoung 赞了回答 · 2018-04-25

解决php是否适合做后台长驻程序

既然这个问题问的是php 是否适合 做后台常驻程序,我觉得还是应该给一个非常明确的答案,即 不适合

诚如其他答案中所说,php可以实现所有功能,内存问题也逐步变好,这是好事,但这并不是php适合做这件事的理由。要说可以实现功能,采用awk + nc也可以写一个常驻后台的web server且性能不一定比php差,但实际上绝不会有人采用这种geek的技术方案。

php不适合做这件事的理由有三:

  1. php的设计目的是方便的构建动态网页,并非后台服务,使用一种语言工具应当尽可能扬长避短,勉力而为之并不合适。
  2. php缺乏内建的线程和非阻塞机制,采用fork的非阻塞方案已经在好几年前被证明是低效的,并非现在最合适的技术方案
  3. php缺乏制作后台常驻程序的库、框架、成功案例,相比其他在这个领域发展了许多年的语言、或专门为制作后台程序而生的语言(如C、Java、Go等),php并不合适

不过,php就算不适合做后台常驻程序,也并不妨碍它在某些情况下使用,比如

  • 没什么性能压力、对稳定性也没什么特别要求时
  • 必须调用很多php写的库,不方便使用其他语言重写时
  • 开发同学只会写php,又找不到更好的人来实现这个项目时

总之,能不使用php做后台程序就别用,如果用了且未来还会上量,最好早做用其他语言重写的打算吧。

关注 8 回答 12

codekissyoung 关注了用户 · 2018-04-25

Laruence @laruence

新浪微博平台及大数据部总架构师,PHP官方开发组核心成员, Zend外聘顾问

关注 199

codekissyoung 赞了回答 · 2018-04-19

解决微信支付HTTPS服务器证书更换问题

我也遇到了这个问题,向微信的技术客户发了邮件。
邮件如下:
你好,打扰了,在接到你们的证书更换通知以后
图片描述
我检查了我们发起支付调用的linux centos7.3 服务器
图片描述
发现我们的服务器应该内置了DigiCert的证书

但是我们通过curl发起post请求到你们的沙箱接口,却报错400错误
图片描述
我相信我们的服务器确实内置了DigiCert的证书了的,但是你们接口报这个错误,我确实不明白。
还望您能答疑解惑,非常感谢。

微信技术很快回复了。
“报400错误,说明你们没有新证书,请按照文档要求,仔细查看。”

直觉告诉我,最新的CentOS7.3应该跟浏览器差不多,已经内置DigiCert的根证书。

下午6点时候,再试了一次:
curl -X POST -H 'content-type: application/xml' -d /root/data.xml https://apitest.mch.weixin.qq...
图片描述

结论:楼主也不用担心这个问题了。这个「400BadRequest No required SSL certificate was sent」是微信那边给出了错误的提示。

微信那边对错误的提示,已经默默改好了。

关注 23 回答 16

codekissyoung 赞了回答 · 2018-03-12

ruby 的rvm 安装失败

错误信息里说得挺清楚,是因为签名验证没有通过,你可以尝试:

gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3

关注 4 回答 2

codekissyoung 收藏了文章 · 2018-02-07

Backbone.js学习笔记(二)细说MVC

对于初学backbone.js的同学可以先参考我这篇文章:Backbone.js学习笔记(一)

Backbone源码结构

图片描述

   1:  (function() {

   2:      Backbone.Events        // 自定义事件

   3:      Backbone.Model        // 模型构造函数和原型扩展

   4:      Backbone.Collection    // 集合构造函数和原型扩展

   5:      Backbone.Router        // 路由配置器构造函数和原型扩展

   6:      Backbone.History        // 路由器构造函数和原型扩展

   7:      Backbone.View            // 视图构造函数和原型扩展

   8:      Backbone.sync            // 异步请求工具方法

   9:      var extend = function (protoProps, classProps) { ... } // 自扩展函数

  10:      Backbone.Model.extend = Backbone.Collection.extend = Backbone.Router.extend = Backbone.View.extend = extend; // 自扩展方法

  11:  }).call(this);

JS MVC职责划分

M 模型

业务模型:业务逻辑、流程、状态、规则
(核心)数据模型:业务数据、数据校验、增删改查(AJAX)

V 视图

(核心)视图:定义、管理、配置
模板:定义、配置、管理
组件:定义、配置、管理
(核心)用户事件配置、管理
用户输入校验、配置、管理

C 控制器/分发器

(核心)事件分发、模型分发、视图分发
不做数据处理、业务处理,即业务无关
扩展:权限控制、异常处理等
C是JSMVC框架的核心,实现集中式配置和管理,可以有多个控制器

工具库

主要是异步请求、DOM操作,可以依赖于jQuery等

来源:http://www.cnblogs.com/nuysoft/archive/2012/03/14/2395272.html

Model指的是一条一条的数据,而集合Collection指的是对Model中的多条数据进行管理。

模型 Model

我们用Backbone.Model表示应用中所有数据,models中的数据可以创建、校验、销毁和保存到服务端。

对象赋值的方法

1、直接定义,设置默认值

 Trigkit = Backbone.Model.extend({
             initialize : function () {
                 alert('hi!');
             },
             defaults:{
                 age : '22',
                 profession : 'coder'
             }
         });
        var coder = new Trigkit;
        alert(coder.get('age'));//22

2、 赋值时定义

<script type="text/javascript">
     Trigkit = Backbone.Model.extend({
         initialize : function () {
             alert('hi!');
         }
     });
     var t = new Trigkit;
     t.set({name :'huang',age : '10'});
     alert(t.get('name'));
</script>        

对象中的方法

<script type="text/javascript" data-original="Underscore.js"></script>
<script type="text/javascript" data-original="backbone-1.1.2.js"></script>
<script type="text/javascript">
        var Trigkit4 = Backbone.Model.extend({
            initialize : function () {
                alert("hello world!");
            },
            defaults : {
                name : 'zhangsan',
                age : 21
            },
            aboutMe: function () {
                return '我叫' + this.get('name') + ',今年' + this.get('age') + '岁';
            }
        });
        var t = new Trigkit4;
        alert(t.aboutMe());
    </script>

当模型实例化时,他的initialize方法可以接受任意实例参数,其工作原理是backbone模型本身就是构造函数,所以可以使用new生成实例:

var User = Backbone.Model.extend({
    initialize: function (name) {
        this.set({name: name});
    }
});
var user = new User('trigkit4');
alert(user.get('name'), 'trigkit4');//trigkit4

看下backbone的源码:

var Model = Backbone.Model = function(attributes, options) {
    var attrs = attributes || {};
    options || (options = {});
    this.cid = _.uniqueId('c');
    this.attributes = {};
    if (options.collection) this.collection = options.collection;
    if (options.parse) attrs = this.parse(attrs, options) || {};
    attrs = _.defaults({}, attrs, _.result(this, 'defaults'));
    this.set(attrs, options);
    this.changed = {};
    this.initialize.apply(this, arguments);
  };

 initialize: function(){},//initialize是默认的空函数

Model 的事件绑定

为了能及时更新view,我们需要通过事件绑定机制来处理和响应用户事件:

    <script type="text/javascript">
        var Task = Backbone.Model.extend({
            initialize: function () {
                this.on("change:name", function (model) {
                    alert("my name is : " + model.get("name"));
                });
            }
        });

        var task = new Task({ name:"oldname", state:"working"});
        task.set({name:"trigkit"});
//        object.on(event, callback, [context])
    </script>
</head>

关于事件绑定,有on,off,trigger,once,listenTo,stopListening,listenToOnce等方法,具体参照:http://documentcloud.github.io/backbone/#Events

图片描述

集合 Collection

Backbone.Collection就是一个Model对象的有序集合。因为Model是一条数据记录,也就是说,Collection相当于是一个数据集。具有增加元素,删除元素,获取长度,排序,比较等一系列工具方法,说白了就是一个保存models的集合类。

<script type="text/javascript">
    var Book = Backbone.Model.extend({
        defaults : {
            title:'default'
        },

        initialize: function(){

             alert('hello backbone!');//弹出3次
        }
    });

    BookShelf = Backbone.Collection.extend({

        model : Book

    });

    var book1 = new Book({title : 'book1'});

    var book2 = new Book({title : 'book2'});

    var book3 = new Book({title : 'book3'});

    //var bookShelf = new BookShelf([book1, book2, book3]); //注意这里面是数组,或者使用add

    var bookShelf = new BookShelf;

    bookShelf.add(book1);
    bookShelf.add(book2);
    bookShelf.add(book3);
    bookShelf.remove(book3);

    //基于underscore这个js库,还可以使用each的方法获取collection中的数据
    bookShelf.each(function(book){

        alert(book.get('title'));

    });
</script>

collection.model覆盖此属性来指定集合中包含的模型类。可以传入原始属性对象(和数组)来 add, create,和 reset,传入的属性会被自动转换为适合的模型类型。
图片描述

视图 View

Backbone.View中可以绑定dom元素和客户端事件。页面中的html就是通过viewsrender方法渲染出来的,当新建一个view的时候通过要传进一个model作为数据

view.$el:一个视图元素的缓存jQuery对象。 一个简单的引用,而不是重新包装的DOM元素。 

一个简单的View:

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script type="text/javascript" data-original="jquery-1.9.1.min.js"></script>
    <script type="text/javascript" data-original="Underscore.js"></script>
    <script type="text/javascript" data-original="backbone-1.1.2.js"></script>
    <script type="text/javascript">

            var TestView = Backbone.View.extend({ //创建一个view,其实就是一个HTML的DOM节点
                initialize: function() {
                    this.render();
                },
                render: function() {  // 渲染方法
                    this.$el.html('Hello World');  //this.el就是HTML节点,通过jQuery的html方法填充内容
                    return this;
                }
            });

            $(function () {
                var test = new TestView({el: $('#body')});// 以目标节点为el参数,创建一个view的实例,render函数将会被自动调用并将渲染结果填充到el中
                //test.render(); // 如果没在 initialize 里调用 render 的话,就需要在这里调用一次
            });
    </script>
</head>
<body>
<div id="body"></div>
</body>

elview.el所有的视图都拥有一个 DOM 元素(el 属性),即使该元素仍未插入页面中去。 视图可以在任何时候渲染,然后一次性插入 DOM 中去,这样能尽量减少 reflowsrepaints 从而获得高性能的 UI 渲染。 this.el 可以从视图的 tagName, className, idattributes 创建,如果都未指定,el 会是一个空 div。 --官网

图片描述

扩展方法 extend

模型、集合、视图、路由器都有一个extend方法,用于扩展原型属性和静态属性,创建自定义的模型、集合、视图、路由器类。

Backbone.Model.extend

Backbone.Model.extend(properties, [classProperties])

要创建自己的 Model 类,你可以扩展 Backbone.Model 并提供实例 properties(属性) , 以及可选的可以直接注册到构造函数的classProperties(类属性)。

Backbone.View.extend

Backbone.View.extend(properties, [classProperties])

开始创建自定义的视图类。 通常我们需要重载 render 函数,声明 events, 以及通过 tagName, className, 或 id 为视图指定根元素。 Backbone.View通过绑定视图的 render 函数到模型的 "change" 事件 — 模型数据会即时的显示在 UI 中。

Backbone.Collection.extend

Backbone.Collection.extend(properties, [classProperties])

通过扩展 Backbone.Collection 创建一个 Collection 类。实例属性参数 properties 以及 类属性参数 classProperties 会被直接注册到集合的构造函数。

Backbone.Router.extend

Backbone.Router.extend(properties, [classProperties])

开始创建一个自定义的路由类。当匹配了 URL 片段便执行定义的动作,并可以通过 routes 定义路由动作键值对。

Router与controller

controllerBackbone 0.5以前的叫法,现在改名叫Router了。

Backbone.Router 为客户端路由提供了许多方法,并能连接到指定的动作(actions)和事件(events)。
页面加载期间,当应用已经创建了所有的路由,需要调用 Backbone.history.start()

查看下面示例:

<script type="text/javascript">
        var AppRouter = Backbone.Router.extend({
            routes: {
                "index" : "index",
                "task/:id": "task",
                "*acts": "tasklist"
            },
            index: function() {
                alert("index");
            },
            tasklist: function(action) {
                alert(action);
            },
            task: function(id) {
                alert(id);
            }
        });

        var app = new AppRouter;
        Backbone.history.start();
    </script>

在浏览器里打开页面后,在urlhtml后面依次加上:

#/index
#/task/1
#/test/xxxx

将分别弹出出:index, 1, test/xxxx

这就是Router的功能。

backbone github官网:http://documentcloud.github.io/backbone/

查看原文

codekissyoung 赞了文章 · 2018-02-07

Backbone.js学习笔记(二)细说MVC

对于初学backbone.js的同学可以先参考我这篇文章:Backbone.js学习笔记(一)

Backbone源码结构

图片描述

   1:  (function() {

   2:      Backbone.Events        // 自定义事件

   3:      Backbone.Model        // 模型构造函数和原型扩展

   4:      Backbone.Collection    // 集合构造函数和原型扩展

   5:      Backbone.Router        // 路由配置器构造函数和原型扩展

   6:      Backbone.History        // 路由器构造函数和原型扩展

   7:      Backbone.View            // 视图构造函数和原型扩展

   8:      Backbone.sync            // 异步请求工具方法

   9:      var extend = function (protoProps, classProps) { ... } // 自扩展函数

  10:      Backbone.Model.extend = Backbone.Collection.extend = Backbone.Router.extend = Backbone.View.extend = extend; // 自扩展方法

  11:  }).call(this);

JS MVC职责划分

M 模型

业务模型:业务逻辑、流程、状态、规则
(核心)数据模型:业务数据、数据校验、增删改查(AJAX)

V 视图

(核心)视图:定义、管理、配置
模板:定义、配置、管理
组件:定义、配置、管理
(核心)用户事件配置、管理
用户输入校验、配置、管理

C 控制器/分发器

(核心)事件分发、模型分发、视图分发
不做数据处理、业务处理,即业务无关
扩展:权限控制、异常处理等
C是JSMVC框架的核心,实现集中式配置和管理,可以有多个控制器

工具库

主要是异步请求、DOM操作,可以依赖于jQuery等

来源:http://www.cnblogs.com/nuysoft/archive/2012/03/14/2395272.html

Model指的是一条一条的数据,而集合Collection指的是对Model中的多条数据进行管理。

模型 Model

我们用Backbone.Model表示应用中所有数据,models中的数据可以创建、校验、销毁和保存到服务端。

对象赋值的方法

1、直接定义,设置默认值

 Trigkit = Backbone.Model.extend({
             initialize : function () {
                 alert('hi!');
             },
             defaults:{
                 age : '22',
                 profession : 'coder'
             }
         });
        var coder = new Trigkit;
        alert(coder.get('age'));//22

2、 赋值时定义

<script type="text/javascript">
     Trigkit = Backbone.Model.extend({
         initialize : function () {
             alert('hi!');
         }
     });
     var t = new Trigkit;
     t.set({name :'huang',age : '10'});
     alert(t.get('name'));
</script>        

对象中的方法

<script type="text/javascript" data-original="Underscore.js"></script>
<script type="text/javascript" data-original="backbone-1.1.2.js"></script>
<script type="text/javascript">
        var Trigkit4 = Backbone.Model.extend({
            initialize : function () {
                alert("hello world!");
            },
            defaults : {
                name : 'zhangsan',
                age : 21
            },
            aboutMe: function () {
                return '我叫' + this.get('name') + ',今年' + this.get('age') + '岁';
            }
        });
        var t = new Trigkit4;
        alert(t.aboutMe());
    </script>

当模型实例化时,他的initialize方法可以接受任意实例参数,其工作原理是backbone模型本身就是构造函数,所以可以使用new生成实例:

var User = Backbone.Model.extend({
    initialize: function (name) {
        this.set({name: name});
    }
});
var user = new User('trigkit4');
alert(user.get('name'), 'trigkit4');//trigkit4

看下backbone的源码:

var Model = Backbone.Model = function(attributes, options) {
    var attrs = attributes || {};
    options || (options = {});
    this.cid = _.uniqueId('c');
    this.attributes = {};
    if (options.collection) this.collection = options.collection;
    if (options.parse) attrs = this.parse(attrs, options) || {};
    attrs = _.defaults({}, attrs, _.result(this, 'defaults'));
    this.set(attrs, options);
    this.changed = {};
    this.initialize.apply(this, arguments);
  };

 initialize: function(){},//initialize是默认的空函数

Model 的事件绑定

为了能及时更新view,我们需要通过事件绑定机制来处理和响应用户事件:

    <script type="text/javascript">
        var Task = Backbone.Model.extend({
            initialize: function () {
                this.on("change:name", function (model) {
                    alert("my name is : " + model.get("name"));
                });
            }
        });

        var task = new Task({ name:"oldname", state:"working"});
        task.set({name:"trigkit"});
//        object.on(event, callback, [context])
    </script>
</head>

关于事件绑定,有on,off,trigger,once,listenTo,stopListening,listenToOnce等方法,具体参照:http://documentcloud.github.io/backbone/#Events

图片描述

集合 Collection

Backbone.Collection就是一个Model对象的有序集合。因为Model是一条数据记录,也就是说,Collection相当于是一个数据集。具有增加元素,删除元素,获取长度,排序,比较等一系列工具方法,说白了就是一个保存models的集合类。

<script type="text/javascript">
    var Book = Backbone.Model.extend({
        defaults : {
            title:'default'
        },

        initialize: function(){

             alert('hello backbone!');//弹出3次
        }
    });

    BookShelf = Backbone.Collection.extend({

        model : Book

    });

    var book1 = new Book({title : 'book1'});

    var book2 = new Book({title : 'book2'});

    var book3 = new Book({title : 'book3'});

    //var bookShelf = new BookShelf([book1, book2, book3]); //注意这里面是数组,或者使用add

    var bookShelf = new BookShelf;

    bookShelf.add(book1);
    bookShelf.add(book2);
    bookShelf.add(book3);
    bookShelf.remove(book3);

    //基于underscore这个js库,还可以使用each的方法获取collection中的数据
    bookShelf.each(function(book){

        alert(book.get('title'));

    });
</script>

collection.model覆盖此属性来指定集合中包含的模型类。可以传入原始属性对象(和数组)来 add, create,和 reset,传入的属性会被自动转换为适合的模型类型。
图片描述

视图 View

Backbone.View中可以绑定dom元素和客户端事件。页面中的html就是通过viewsrender方法渲染出来的,当新建一个view的时候通过要传进一个model作为数据

view.$el:一个视图元素的缓存jQuery对象。 一个简单的引用,而不是重新包装的DOM元素。 

一个简单的View:

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script type="text/javascript" data-original="jquery-1.9.1.min.js"></script>
    <script type="text/javascript" data-original="Underscore.js"></script>
    <script type="text/javascript" data-original="backbone-1.1.2.js"></script>
    <script type="text/javascript">

            var TestView = Backbone.View.extend({ //创建一个view,其实就是一个HTML的DOM节点
                initialize: function() {
                    this.render();
                },
                render: function() {  // 渲染方法
                    this.$el.html('Hello World');  //this.el就是HTML节点,通过jQuery的html方法填充内容
                    return this;
                }
            });

            $(function () {
                var test = new TestView({el: $('#body')});// 以目标节点为el参数,创建一个view的实例,render函数将会被自动调用并将渲染结果填充到el中
                //test.render(); // 如果没在 initialize 里调用 render 的话,就需要在这里调用一次
            });
    </script>
</head>
<body>
<div id="body"></div>
</body>

elview.el所有的视图都拥有一个 DOM 元素(el 属性),即使该元素仍未插入页面中去。 视图可以在任何时候渲染,然后一次性插入 DOM 中去,这样能尽量减少 reflowsrepaints 从而获得高性能的 UI 渲染。 this.el 可以从视图的 tagName, className, idattributes 创建,如果都未指定,el 会是一个空 div。 --官网

图片描述

扩展方法 extend

模型、集合、视图、路由器都有一个extend方法,用于扩展原型属性和静态属性,创建自定义的模型、集合、视图、路由器类。

Backbone.Model.extend

Backbone.Model.extend(properties, [classProperties])

要创建自己的 Model 类,你可以扩展 Backbone.Model 并提供实例 properties(属性) , 以及可选的可以直接注册到构造函数的classProperties(类属性)。

Backbone.View.extend

Backbone.View.extend(properties, [classProperties])

开始创建自定义的视图类。 通常我们需要重载 render 函数,声明 events, 以及通过 tagName, className, 或 id 为视图指定根元素。 Backbone.View通过绑定视图的 render 函数到模型的 "change" 事件 — 模型数据会即时的显示在 UI 中。

Backbone.Collection.extend

Backbone.Collection.extend(properties, [classProperties])

通过扩展 Backbone.Collection 创建一个 Collection 类。实例属性参数 properties 以及 类属性参数 classProperties 会被直接注册到集合的构造函数。

Backbone.Router.extend

Backbone.Router.extend(properties, [classProperties])

开始创建一个自定义的路由类。当匹配了 URL 片段便执行定义的动作,并可以通过 routes 定义路由动作键值对。

Router与controller

controllerBackbone 0.5以前的叫法,现在改名叫Router了。

Backbone.Router 为客户端路由提供了许多方法,并能连接到指定的动作(actions)和事件(events)。
页面加载期间,当应用已经创建了所有的路由,需要调用 Backbone.history.start()

查看下面示例:

<script type="text/javascript">
        var AppRouter = Backbone.Router.extend({
            routes: {
                "index" : "index",
                "task/:id": "task",
                "*acts": "tasklist"
            },
            index: function() {
                alert("index");
            },
            tasklist: function(action) {
                alert(action);
            },
            task: function(id) {
                alert(id);
            }
        });

        var app = new AppRouter;
        Backbone.history.start();
    </script>

在浏览器里打开页面后,在urlhtml后面依次加上:

#/index
#/task/1
#/test/xxxx

将分别弹出出:index, 1, test/xxxx

这就是Router的功能。

backbone github官网:http://documentcloud.github.io/backbone/

查看原文

赞 9 收藏 77 评论 1

codekissyoung 关注了专栏 · 2017-10-13

差的很多

每一个真实现在都是你曾经幻想未来

关注 41