php自动加载规范:PSR-0

[翻译自官网http://www.php-fig.org/psr/psr-0/]

自动加载规范

下面描述了自动加载操作时必须遵守的强制要求。

要求:

  • 一个完全合格的命名空间和类名必须有以下的结构 \()*
  • 每个命名空间必须有提供者名称(“Vendor Name”)作为顶级的命名空间
  • 每个命名空间可以有多个子命名空间
  • 每个命名空间在被从文件系统加载时须将分隔符转换为”系统分隔符”(DIRECTORY_SEPARATOR)
  • 每个”“字符在”类名”中应被转换为系统分隔符。”“符号在命名空间中没有特殊含义
  • 加载文件时完全合格的命名空间和类名必须以”.php”结尾
  • 提供者名称,命名空间,类名可以由任意大小写字母组成

举个栗子

\Doctrine\Common\IsolatedClassLoader => /path/to/project/lib/vendor/Doctrine/Common/IsolatedClassLoader.php
\Symfony\Core\Request => /path/to/project/lib/vendor/Symfony/Core/Request.php
\Zend\Acl => /path/to/project/lib/vendor/Zend/Acl.php
\Zend\Mail\Message => /path/to/project/lib/vendor/Zend/Mail/Message.php

下划线在命名空间及类中的使用


\namespace\package\Class_Name => /path/to/project/lib/vendor/namespace/package/Class/Name.php
\namespace\package_name\Class_Name => /path/to/project/lib/vendor/namespace/package_name/Class/Name.php

示例实现

下面是一个简单的示例函数演示如何使用上述标准来自动加载。


<?php
function autoload($className)
{
    $className = ltrim($className, '\\');
    $fileName  = '';
    $namespace = '';
    if ($lastNsPos = strrpos($className, '\\')) {
        $namespace = substr($className, 0, $lastNsPos);
        $className = substr($className, $lastNsPos + 1);
        $fileName  = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
    }
    $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
    require $fileName;
}

SplClassloader的实现

接下来这个gist是一个SplClassLoader实现例子,通过它你可以加载按照上面标准来实现的通用类库,这是目前推荐的方式加载遵循这些标准的php类。

http://gist.github.com/221634

PHP编码规范

PHP社区百花齐放,拥有大量的函数库、框架和组件。
PHP开发者通常会在自己的项目中使用若干个外部库,因而PHP代码遵循或尽量接近同一个代码风格就非常重要,可以让开发者方便地把多个代码库集成在自己的项目中。

框架互操作组(PHP Framework Interoperability Group)发布了一系列代码风格推荐标准,即PSR规范(Proposing a Standard Recommendation)。

目前已有5个代码规范:

  • PSR-0 自动加载规范
  • PSR-1 基本代码规范
  • PSR-2 代码样式规范
  • PSR-3 日志接口规范
  • PSR-4 改进的自动加载规范

目前参照PHP-FIG提供的编码规范开发的知名项目已经有很多,如Laravel、Drupal、Zend 、Symfony、composer等,详见:http://www.php-fig.org

为什么要遵守这些规范?这个就不用多说吧,世界上最好的PHP框架及项目都是遵守这些规范写的。

最后,虽然不强迫大家必须按照这些规范开发,但若PHP程序员都遵照这样一种好的协议开发,养成习惯,那全世界的PHP程序员就能幸福快乐的生活在一起了╮(╯▽╰)╭

Wordpress插件开发

Wordpress插件允许你通过一种简单的方式来修改、定义和强化博客的功能。
你可以在不修改WordPress的核心代码的情况下,通过插件来直接向WordPress中增加功能。
WordPress插件可以是一个程序,也可以是PHP语言编写的一个或一组函数。
它可以通过插件 API提供的一系列方法和接口,来向WordPress中增加一些特定的功能或服务,并且让它们看上去就像是WordPress原有的功能一样。

钩子机制、动作和过滤器

在说开发wordpress插件之前先讲下wordpress中的钩子机制。

WordPress 中有一种钩子机制,允许插件把一些功能“挂载”到 WordPress 当中。
也就是说,在系统运行至某一个环节时,去调用插件内的一些函数。执行挂勾分为两种:动作和过滤器。

动作 (Action):

动作是WordPress运行到某些环节,或者在某些事件发生时,就执行指定的 PHP 函数。
wordpress中的动作响应函数是add_action(),如下:
add_action( ‘动作名’, ‘响应函数名’, [优先级], [参数数目] );

wordpress中的动作:http://codex.wordpress.org/Plugin_API/Action_Reference

过滤器 (Filter):

过滤器是一类函数,WordPress执行传递和处理数据的过程中,在针对这些数据做出某些动作之前的特定点运行(例如将数据写入数据库或将其传递到浏览器页面)。
wordpress中注册过滤器的函数是add_filter(),如下:
add_filter(‘过滤名’, ‘过滤函数’, [优先级], [参数数目] );

开始创建一个插件

知道了wordpress中的钩子机制直接之后让我们来创建一个百度分享的插件 。

wordpress中的插件目录为:wp_content/plugins

让我们在该目录下创建一个文件夹bdShare,并在bdShare文件夹下创建插件主文件bdShare.php。

标准插件信息:

插件的主文件顶部必须包括一个标准插件信息头。WordPress通过标准信息头识别插件的存在,并把它加入到控制面板的插件管理页面,这样插件才能激活,载入插件,并运行里面的函数。

在bdShare.php中写入标准插件信息:

<?php

/*

Plugin Name: 百度分享插件
Plugin URI: http://yuankeqiang.lofter.com
Description: 百度你这么吊你妈知道吗
Version: 1.0
Author: 袁克强
Author URI: http://yuankeqiang.lofter.com

*/

保存文件,登陆wordpress后台并进入插件菜单就可以看到我们的插件信息了

ykq

但是目前就算启用了插件也没有任何功能。

接着在bdShare.php加上百度分享的代码,并在wordpress加载完头部模板(wp_head)后执行这段代码:

function bdShare(){echo '<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"slide":{"type":"slide","bdImg":"1","bdPos":"right","bdTop":"100.5"}};with(document)0[(getElementsByTagName("head")[0]||body).appendChild(createElement("script")).src="http://bdimg.share.baidu.com/static/api/js/share.js?v=89343201.js?cdnversion="+~(-new Date()/36e5)];</script>';}

add_action("wp_head","bdShare");

最后保存代码并在后台启用该插件,刷新wordpress首页即可看到我们的百度分享插件:
ykq

完毕

wordpress中的插件开发就是这么简单,利用wordpress中的钩子机制及其自带的强大的函数就能创造出各种神奇的插件。。。。。。

wordpress主题开发教程

WordPress是一种使用PHP语言开发的博客平台,免费、开源。

作为最流行的博客平台,海量的插件和主题可以说是WordPress 最大的特色了,没有哪一个Blog 平台拥有如此多的插件和主题,拥有如此多的用户和爱好者。

ykq

下面介绍如何开发设计你自己的 WordPress 主题。

主题的剖析

WordPress主题目录位于 wp-content/themes/。主题目录拥有所有样式文件、模板文件、可选的函数文件 (functions.php)、JavaScript 文件、图片等。比如说一个叫做 “test” 的主题就会放在 wp-content/themes/test/目录里。

WordPress 主题一般由三种文件构成:

  1. 样式表文件 style.css, 控制着页面的外观。
  2. 函数文件 (functions.php)。
  3. 模板文件,它控制着从数据库中调出的数据所呈现的外观。

主题样式表

style.css为该主题的主题样式,该样式文件须在文件开头以注释的形式列出主题的详细信息。

/*

Theme Name: ykqTheme
Theme URI: yuankeqiang.lofter.com
Author: ykq
Tag : hehe
.......

*/

这样启用主题后wordpress会自动读取该主题的相关信息,我们可以在后台->外观->主题->主题详情 来查看我们我们的主题信息。

ykq

缩略图来自哪里:

在主题目录创建一张图片重命名为screenshot.png或者screenshot.jpg,wordpress会自动读取该图片为主题的缩略图。

还有一个样式rtl.css:

作用是如果网站的阅读方向是自右向左的,他会自动被包含进来。你可以使用 the RTLer 插件来生成这个文件。

函数文件

一个主题可以使用一个函数文件,位于主题的根目录,叫做 functions.php。

这个文件就像一个插件, 如果它位于你正在使用的主题里的话,他在你的主题初始化的时候就会自动加载(后台页面和前台页面都一样加载)。对于这个文件的建议:

  • 启用主题功能,例如:侧边栏,菜单,文章缩略图,文章格式,自定义标题栏。
  • 定义用于模板文件中的函数。
  • 设置一个选项菜单,让网站拥有者可以自定义颜色,样式,和你的主题的其他特性。

模板文件

模板是一些PHP文件,不同的模板代表不同的页面:

常见模板如下:

  • index.php 主模板.必须.
  • comments.php 留言区域文件(包括留言列表和留言框)
  • single.php 日志单独页面模板。显示单独的一篇文章时被调用。
  • single-{post-type}.php 自定义单独页面模板。例如,
  • single-books.php 展示自定义文章类型为 books的文章。
  • page.php 页面文件
  • archvie.php 分类和日期存档页文件
  • tag.php 标签模板。
  • author.php 作者模板。作者页面调用
  • search.php 搜索页面文件
  • header.php 网页头部文件
  • sidebar.php 网页侧边栏文件
  • footer.php 网页底部文件
  • image.php 图片附件模板。当在wordpress中查看单个图片时将调用此模板
  • 404.php 错误页面 模板。当WordPress无法查找到匹配查询的日志或页面时,使用404.php文件。

自定义单页模板

我们可以自定义页面模板page.php,创建一个自定义页面需要首先创建一个文件,建议文件的命名为page-{name}.php,

假设我们创建一个公司简介的页面,自定义页面可以叫做page-about.php。在page-about.php的文件顶部必须写上页面名称:

<?php /* Template Name: 公司简介  */  ?>

这样我们创建页面的时候就可以选择我们自定义的模板:
ykq

注意:我们可以在主题文件夹的任何地方创建页面模板,若模板文件很多的话我们可以创建一个文件夹如page-templates,然后将模板文件都放到该文件夹下。

包含模板

为了加载其他模板(除了 header, sidebar, footer 这些已经被预先定义了加载命令的例如 get_header())到某个模板中,你可以使用 get_template_part()。这利于主题的代码重用。

Wordpress 函数代码

创建完模板,如何在模板中动态显示内容?那就要用到wordpress的函数代码了

WordPress 中定义了许多有用的 PHP 函数,大概有几百个。参考:http://codex.wordpress.org/zh-cn:%E5%87%BD%E6%95%B0%E5%8F%82%E8%80%83

一些常见的函数有:


<?php the_content(); ?> 日志内容 
<?php if(have_posts()) : ?> 确认是否有日志 
<?php while(have_posts()) : the_post(); ?> 如果有,则显示全部日志 
<?php endwhile; ?> 结束PHP函数”while<?php endif; ?> 结束PHP函数”if<?php get_header(); ?> header.php文件的内容 
<?php get_sidebar(); ?> sidebar.php文件的内容 
<?php get_footer(); ?> footer.php文件的内容 
<?php the_time(’m-d-y’) ?> 显示格式为”10-12-13″的日期 
<?php comments_popup_link(); ?> 显示一篇日志的留言链接 
<?php the_title(); ?> 显示一篇日志或页面的标题 
<?php the_permalink() ?> 显示一篇日志或页面的永久链接/URL地址 
<?php the_category(’, ‘) ?> 显示一篇日志或页面的所属分类 
<?php the_author(); ?> 显示一篇日志或页面的作者 
<?php the_ID(); ?> 显示一篇日志或页面的ID 
<?php edit_post_link(); ?> 显示一篇日志或页面的编辑链接 
<?php get_links_list(); ?> 显示链接 
<?php comments_template(); ?> comments.php文件的内容 
<?php wp_list_pages(); ?> 显示一份博客的页面列表 
<?php wp_list_cats(); ?> 显示一份博客的分类列表 
<?php next_post_link(’ %link ‘) ?> 下一篇日志的URL地址 
<?php previous_post_link(’%link’) ?> 上一篇日志的URL地址 
<?php get_calendar(); ?> 调用日历 
<?php wp_get_archives() ?> 显示一份博客的日期存档列表 
<?php posts_nav_link(); ?> 显示较新日志链接(上一页)和较旧日志链接(下一页) 
<?php bloginfo(’description’); ?> 显示博客的描述信息

<?php bloginfo(’name’); ?> 网站标题 
<?php wp_title(); ?> 日志或页面标题 
<?php bloginfo(’stylesheet_url’); ?> Wordpress主题样式表文件style.css的相对地址 
<?php bloginfo(’pingback_url’); ?> Wordpress博客的Pingback地址 
<?php bloginfo(’template_url’); ?> Wordpress主题文件的相对地址 
<?php bloginfo(’version’); ?> 博客的Wordpress版本 
<?php bloginfo(’url’); ?> Wordpress博客的绝对地址 
<?php bloginfo(’charset’); ?> 网站的字符编码格式

其他

到目前为止基本讲完了wordpress的主题开发

简单的说,开发一个wordpress分以下几步:

  1. 在wp-content/themes/文件夹下创建属于你自己的主题文件夹
  2. 然后在主题文件夹下创建2个必须的基本文件 index.php 和style.css
  3. 接着根据需要创建其他模板和文件及利用wordpress内置的函数在模板中动态显示内容
  4. 最后登陆后台在外观中启用我们创建的主题就可以了

当然,还有个简便的方法就是把wordpress默认的主题复制一份,然后在其基础上二次开发就OK了。

最后

什么?看完了文章你还不会wordpress的主题开发?

那一定是你看的方式不对,请刷个牙再来看一遍。

Angular.js整合socket.io

前言

作为下一代的 Web 标准,HTML5 拥有许多引人注目的新特性,如 Canvas、本地存储、多媒体编程接口、WebSocket 等等。
这其中WebSocket使得浏览器对 Socket 的支持成为可能,从而在浏览器和服务器之间提供了一个基于 TCP 连接的双向通道。Web 开发人员可以非常方便地使用 WebSocket构建实时 web 应用,开发人员的手中从此又多了一柄神兵利器。

socket.IO

Socket.IO 是一个功能非常强大的框架,能够帮助你构建基于 WebSocket的跨浏览器的实时应用。支持主流浏览器,多种平台,多种传输模式,还可以集合 Exppress 框架构建各种功能复杂的实时应用。
官网:http:www.socket.io

AngularJs

AngularJs是一个Google出的现代化MVVM前端框架,具有数据绑定、依赖注入、模板等功能。
通过AngularJs的数据双向绑定,利用socket.io从服务端推送一个消息到客户端,客户端内容自动发生改变,这是多么令人兴奋得一件事。

把Socket.IO封装到一个AngularJS服务里

代码如下:
ykq

此处只封装了两个函数,分别是Socket.IO API中的on事件和emit事件方法。
API中还有很多事件方法,我们可以以类似的方式封装他们。

封装完成后我们就可以在angularJs的控制器或其他地方注入该服务,
让我们用该服务向node.js服务端发送一个socket消息:
ykq

执行代码后打开node.js控制台,可以看到服务端正确的接收到了该消息
ykq

什么是 Event Loop?

[转载自阮一峰的网络日志]

Event Loop 是一个很重要的概念,指的是计算机系统的一种运行机制。

JavaScript语言就采用这种机制,来解决单线程运行带来的一些问题。

ykq

本文参考C. Aaron Cois的《Understanding The Node.js Event Loop》,解释什么是Event Loop,以及它与JavaScript语言的单线程模型有何关系。

想要理解Event Loop,就要从程序的运行模式讲起。运行以后的程序叫做”进程”(process),一般情况下,一个进程一次只能执行一个任务。

如果有很多任务需要执行,不外乎三种解决方法。

  1. 排队。因为一个进程一次只能执行一个任务,只好等前面的任务执行完了,再执行后面的任务。
  2. 新建进程。使用fork命令,为每个任务新建一个进程。
  3. 新建线程。因为进程太耗费资源,所以如今的程序往往允许一个进程包含多个线程,由线程去完成任务。

以JavaScript语言为例,它是一种单线程语言,所有任务都在一个线程上完成,即采用上面的第一种方法。一旦遇到大量任务或者遇到一个耗时的任务,网页就会出现”假死”,因为JavaScript停不下来,也就无法响应用户的行为。

你也许会问,JavaScript为什么是单线程,难道不能实现为多线程吗?

这跟历史有关系。JavaScript从诞生起就是单线程。原因大概是不想让浏览器变得太复杂,因为多线程需要共享资源、且有可能修改彼此的运行结果,对于一种网页脚本语言来说,这就太复杂了。后来就约定俗成,JavaScript为一种单线程语言。(Worker API可以实现多线程,但是JavaScript本身始终是单线程的。)

如果某个任务很耗时,比如涉及很多I/O(输入/输出)操作,那么线程的运行大概是下面的样子。

ykq

上图的绿色部分是程序的运行时间,红色部分是等待时间。可以看到,由于I/O操作很慢,所以这个线程的大部分运行时间都在空等I/O操作的返回结果。这种运行方式称为”同步模式”(synchronous I/O)或”堵塞模式”(blocking I/O)。

如果采用多线程,同时运行多个任务,那很可能就是下面这样。
ykq

上图表明,多线程不仅占用多倍的系统资源,也闲置多倍的资源,这显然不合理。

Event Loop就是为了解决这个问题而提出的。Wikipedia这样定义:

“Event Loop是一个程序结构,用于等待和发送消息和事件。(a programming construct that waits for and dispatches events or messages in a program.)”

简单说,就是在程序中设置两个线程:一个负责程序本身的运行,称为”主线程”;另一个负责主线程与其他进程(主要是各种I/O操作)的通信,被称为”Event Loop线程”(可以译为”消息线程”)。

ykq

上图主线程的绿色部分,还是表示运行时间,而橙色部分表示空闲时间。每当遇到I/O的时候,主线程就让Event Loop线程去通知相应的I/O程序,然后接着往后运行,所以不存在红色的等待时间。等到I/O程序完成操作,Event Loop线程再把结果返回主线程。主线程就调用事先设定的回调函数,完成整个任务。

可以看到,由于多出了橙色的空闲时间,所以主线程得以运行更多的任务,这就提高了效率。这种运行方式称为”异步模式”(asynchronous I/O)或”非堵塞模式”(non-blocking mode)。

这正是JavaScript语言的运行方式。单线程模型虽然对JavaScript构成了很大的限制,但也因此使它具备了其他语言不具备的优势。如果部署得好,JavaScript程序是不会出现堵塞的,这就是为什么node.js平台可以用很少的资源,应付大流量访问的原因。

使用r.js优化require.js项目[require.js工具]

RequireJS提供一个基于node.js的命令行工具r.js用来压缩多个js文件。
它的主要作用是将多个模块文件压缩合并成一个脚本文件,以减少网页的HTTP请求数。
require.js

如何使用?

官方文档:http://www.requirejs.org/docs/optimization.html

这里具体如何使用就不多说了,无非就是用npm下载后几个命令而已。
由于目前端项目大多数都是使用grunt构建的,且r.js也支持grunt。
这里就讲下如何使用grunt配合r.js实现自动化优化require.js项目。

grunt-contrib-requirejs

grunt-contrib-requirejs是grunt官方出的一款用于优化require.js项目的grunt插件,基于r.js。

安装grunt-contrib-requirejs

npm install grunt-contrib-requirejs --save-dev

使用npm install即可完成该插件的安装。

(另外关于如何安装grunt及大概的使用方法可参考本人之前的博客。)

配置grunt-contrib-requirejs

module.exports = function(grunt){
    grunt.initConfig({
        pkg : grunt.file.readJSON('package.json'),
        requirejs : {
            compile: {
                options: {
                    name : "main",
                    optimize: "uglify",
                    mainConfigFile: "./js/main.js",
                    out: "./compile/all.js"
                }
            }
        }
    });
    grunt.loadNpmTasks('grunt-contrib-requirejs');
    grunt.registerTask('default',['requirejs']);
}

配置说明:主要配置项在option属性中
optimize代表使用uglify进行压缩。
mainConfigFile代表require.js主模块位置,通过读取主模块里的require.config({})配置来获取各个js的路径。
out代表压缩后的输出位置。

当然不止仅仅这几个配置,详细请看: https://github.com/jrburke/r.js/blob/master/build/example.build.js

运行

配置好后命令行下输入grunt执行任务。

执行完毕后可以看到compile文件夹下多个个all.js,打开可以看到所有通过require.js加载的js文件被压缩成了一行。

require.js

额。。。require.js部分暂时告一段落。。

text.js异步加载文本资源[require.js插件]

text.js是require.js的一个插件,用于异步加载文本资源,如txt、css、html、xml、svg等。

安装text.js

$ bower install requirejs-text

text.js使用

在require.js主模块main.js配置text.js路径

require.config({
    paths: {
        text : "../bower_components/requirejs-text/text"
    }
});

使用text.js加载资源


require(['text!../text/a.txt','text!../css/a.css','text!../templates/a.html'], function (aTxt,aCss,aHtml){
    console.log(aTxt);
    console.log(aCss);
    console.log(aHtml);
    document.getElementsByTagName("style")[0].innerHTML = aCss;
    document.getElementsByTagName("body")[0].innerHTML = aHtml;
});

text.js 使用text!+资源路径 来加载资源
上例使用text.js异步加载了a.txt a.css a.html,使用的是相对路径加载,当然还可以使用绝对路径加载及在配置中的path定义一个目录。
加载完成后分别在控制台输出及插入到网页里。

javascript

网页里显示
javascript

使用require.js进行JavaScript模块化编程

随着互联网的飞速发展,Javascript开发越来越复杂。Javascript的模块化开发显的越来越重要。
目前,主要的Javascript模块规范共有两种:CommonJS和AMD。

CommonJS

CommonJS主要指服务器端的javascript模块的规范。它的终极目标是提供一个类似Python,Ruby和Java标准库。这样的话,开发者可以使用CommonJS API编写应用程序,然后这些应用可以运行在不同的JavaScript解释器和不同的主机环境中。CommonJS的实现有Node.js、CouchDB等。

AMD规范

AMD是”Asynchronous Module Definition”的缩写,意思就是”异步模块定义”。它采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。require.js是AMD规范最著名的实现。

选择哪种?

CommonJS规范加载模块是同步的,也就是说,只有加载完成,才能执行后面的操作。AMD规范则是异步加载模块,允许指定回调函数。由于Node.js主要用于服务器编程,模块文件一般都已经存在于本地硬盘,所以加载起来比较快,不用考虑非同步加载的方式,所以CommonJS规范比较适用。但是,如果是浏览器环境,要从服务器端加载模块js,加载的过程中,浏览器会停止网页渲。这时就建议采用异步加载方式,很好的避免模块加载的过程中网页失去响应。

require.js介绍

Require.JS是一个基于AMD规范的javascript模块加载框架。实现js文件的异步加载,管理模块之间的依赖性,提升网页的加载速度。
官网:www.requirejs.org/

alt require.js

在网页中使用require.js

<script src="js/require.js" data-main="js/main"></script>

下载后在网页中引入require.js并指定data-main属性。该属性的作用是指定网页程序的主模块。在上例中,就是js目录下面的main.js,这个文件会第一个被require.js加载。

定义模块

根据AMD规范,定义一个模块采用define函数

define(id, dependencies, factory);

参数:
id : 模块标示符[可省略]
dependencies : 所依赖的模块[可省略]
factory : 模块的实现,或者一个JavaScript对象。

require.js定义模块的几种方式

1.定义一个最简单的模块:

define({
    color: "black",
    size: "unisize"
});

2.传入匿名函数定义一个模块:

define(function () {
    return {
        color: "black",
        size: "unisize"
    }
});

3.定义一个模块并依赖于cart.js

define(["./cart"], function(cart) {
    return {
        color: "blue",
        size: "large",
        addToCart: function() {
            cart.add(this);
        }
    }
});
  1. 定义一个名称为hello且依赖于cart.js的模块
define("hello",["./cart"],function(cart) {
    //do something
});

5.兼容commonJS模块的写法(使用require获取依赖模块,使用exports导出API)

define(function(require, exports, module) {
    var base = require('base');
    exports.show = function() {
        // todo with module base
    } 
});

require.js加载模块

require.js通过require()函数来异步加载模块,其接受两个参数。
第一个参数是一个数组,表示所依赖的模块。第二个参数是一个回调函数,当前面指定的模块都加载成功后,它将被调用,且加载的过程中浏览器不会失去响应。

 //main.js
require(['cart'], function (cart){
     //假设我们使用前面第2种方法定义一个模块cart.js,然后这里加载cart.js,下面输出"black"
    alert(cart.color);
});

模块加载的配置

使用require.config()方法,我们可以对模块的加载行为进行自定义配置。
require.config()方法一般写在主模块(main.js)最开始。参数为一个对象,通过对象的键值对加载进行配置:

require.config({
    paths: {
        "angular": "https://ajax.googleapis.com/ajax/libs/angularjs/1.2.4/angular.min",
        "angularRoute": "../bower_components/angular-route/angular-route"
    },
    shim: {
        'angular' : {'exports' : 'angular'},
        'angularRoute': {deps:['angular']}
    }
});

上面代码意思是配置angular.js及angular-route.js的加载路径,并配置angular的外部输出名、angularRoute依赖于angular(加载顺序)。

其他一些配置:

  • baseUrl : 指定模块根路径
  • paths : 指定模块的加载路径
  • shim :声明依赖项、外部输出等
  • map : 对于给定的相同的模块名,加载不同的模块,而不是加载相同的模块
  • config : 传递一个配置信息到模块
  • packages : 配置从CommonJS 包来加载模块
  • deps : 全局配置模块的依赖项的数组
  • callback : 所有依赖项加载后执行的回调函数

require.js一些插件

domready插件,可以让回调函数在页面DOM结构加载完成后再运行。
text插件,让require.js除了能加载js文件还能加载txt文件、css文件等。
插件清单:https://github.com/jrburke/requirejs/wiki/Plugins


呼,看了半天官方文档终于把require.js基本用法写完了。

常见开源协议介绍

BSD开源协议

BSD开源协议是一个给于使用者很大自由的协议。基本上使用者可以”为所欲为”,可以自由的使用,修改源代码,也可以将修改后的代码作为开源或者专有软件再发布。
但”为所欲为”的前提当你发布使用了BSD协议的代码,或则以BSD协议代码为基础做二次开发自己的产品时,需要满足三个条件:

如果再发布的产品中包含源代码,则在源代码中必须带有原来代码中的BSD协议。
如果再发布的只是二进制类库/软件,则需要在类库/软件的文档和版权声明中包含原来代码中的BSD协议。
不可以用开源代码的作者/机构名字和原来产品的名字做市场推广。
BSD 代码鼓励代码共享,但需要尊重代码作者的著作权。BSD由于允许使用者修改和重新发布代码,也允许使用或在BSD代码上开发商业软件发布和销售,因此是对 商业集成很友好的协议。而很多的公司企业在选用开源产品的时候都首选BSD协议,因为可以完全控制这些第三方的代码,在必要的时候可以修改或者二次开发。

Apache Licence 2.0

Apache Licence是著名的非盈利开源组织Apache采用的协议。该协议和BSD类似,同样鼓励代码共享和尊重原作者的著作权,同样允许代码修改,再发布(作为开源或商业软件)。需要满足的条件也和BSD类似:
需要给代码的用户一份Apache Licence
如果你修改了代码,需要再被修改的文件中说明。
在延伸的代码中(修改和有源代码衍生的代码中)需要带有原来代码中的协议,商标,专利声明和其他原来作者规定需要包含的说明。

如果再发布的产品中包含一个Notice文件,则在Notice文件中需要带有Apache Licence。你可以在Notice中增加自己的许可,但不可以表现为对Apache Licence构成更改。

Apache Licence也是对商业应用友好的许可。使用者也可以在需要的时候修改代码来满足需要并作为开源或商业产品发布/销售。

GPL

我们很熟悉的Linux就是采用了GPL。GPL协议和BSD, Apache Licence等鼓励代码重用的许可很不一样。GPL的出发点是代码的开源/免费使用和引用/修改/衍生代码的开源/免费使用,但不允许修改后和衍生的代 码做为闭源的商业软件发布和销售。这也就是为什么我们能用免费的各种linux,包括商业公司的linux和linux上各种各样的由个人,组织,以及商 业软件公司开发的免费软件了。

GPL协议的主要内容是只要在一个软件中使用(”使用”指类库引用,修改后的代码或者衍生代码)GPL 协议的产品,则该软件产品必须也采用GPL协议,既必须也是开源和免费。这就是所谓的”传染性”。GPL协议的产品作为一个单独的产品使用没有任何问题,还可以享受免费的优势。

由于GPL严格要求使用了GPL类库的软件产品必须使用GPL协议,对于使用GPL协议的开源代码,商业软件或者对代码有保密要求的部门就不适合集成/采用作为类库和二次开发的基础。

其它细节如再发布的时候需要伴随GPL协议等和BSD/Apache等类似。

LGPL

LGPL是GPL的一个为主要为类库使用设计的开源协议。和GPL要求任何使用/修改/衍生之GPL类库的的软件必须采用GPL协议不同。LGPL 允许商业软件通过类库引用(link)方式使用LGPL类库而不需要开源商业软件的代码。这使得采用LGPL协议的开源代码可以被商业软件作为类库引用并 发布和销售。

但是如果修改LGPL协议的代码或者衍生,则所有修改的代码,涉及修改部分的额外代码和衍生的代码都必须采用LGPL协议。因此LGPL协议的开源 代码很适合作为第三方类库被商业软件引用,但不适合希望以LGPL协议代码为基础,通过修改和衍生的方式做二次开发的商业软件采用。

GPL/LGPL都保障原作者的知识产权,避免有人利用开源代码复制并开发类似的产品

MIT

MIT是和BSD一样宽范的许可协议,作者只想保留版权,而无任何其他了限制.也就是说,你必须在你的发行版里包含原许可协议的声明,无论你是以二进制发布的还是以源代码发布的.