laravel 框架以及关键概念重新理解

laravel 重新理解
首先 laravel 核心就是一个 Ioc (依赖注入 )容器。框架本身需要的很多东西其实就是各个服务,每一个服务的实现我们可以称为服务容器。
服务举例,有auth 认证服务、cache缓存服务、DB数据库服务、fileSystem文件系统服务 等等,当然你也可以自己添加第三方的 excel 服务 zip服务等。
有了各种各样的服务来实现我们的需求,那么如何使用这些服务呢?即服务的绑定和解析。
首先服务需要被绑定,类似变量赋值一样,我们使用这个变量就相当于用这个值,那么服务绑定到某个名称上,例如:

$this->app->singleton('cache', function ($app) {
return new CacheManager($app);
});

这样当我们通过某种方式调用 cache这个名称 的时候就相当于调用了 cache 服务。cache 服务的实现主要就是 上述代码 CacheManager 中实现的。
服务绑定的方式:
简单绑定:
$this->app->bind('HelpSpot\API', function ($app) {
    return new HelpSpot\API($app->make('HttpClient'));
});
第一个参数是想要注册的类名或者接口名,第二个参数是返回类的实例的闭包。
绑定一个单例:
singleton 方法绑定一个只需要解析一次的类或接口到容器,然后接下来对容器的调用将会返回同一个实例:
$this->app->singleton('HelpSpot\API', function ($app) {
    return new HelpSpot\API($app->make('HttpClient'));
});
绑定实例 :
你还可以使用 instance 方法绑定一个已存在的对象实例到容器,随后调用容器将总是返回给定的实例:
$api = new HelpSpot\API(new HttpClient);
$this->app->instance('HelpSpot\Api', $api);
绑定原始值 :
你可能有一个接收注入类的类,同时需要注入一个原生的数值比如整型,可以结合上下文轻松注入这个类需要的任何值:
$this->app->when('App\Http\Controllers\UserController')
    ->needs('$variableName')
    ->give($value);
类似的还有上下文绑定
有时侯我们可能有两个类使用同一个接口,但我们希望在每个类中注入不同实现,
例如,两个控制器依赖 Illuminate\Contracts\Filesystem\Filesystem 契约的不同实现。
Laravel 为此定义了简单、平滑的接口:
use Illuminate\Support\Facades\Storage;
use App\Http\Controllers\VideoController;
use App\Http\Controllers\PhotoControllers;
use Illuminate\Contracts\Filesystem\Filesystem;
$this->app->when(PhotoController::class)
    ->needs(Filesystem::class)
    ->give(function () {
        return Storage::disk('local');
    });
$this->app->when(VideoController::class)
    ->needs(Filesystem::class)
    ->give(function () {
        return Storage::disk('s3');
    });
绑定接口到实现
服务容器的一个非常强大的功能是其绑定接口到实现。我们假设有一个 EventPusher 接口及其实现类RedisEventPusher ,
编写完该接口的 RedisEventPusher 实现后,就可以将其注册到服务容器:
$this->app->bind(
    'App\Contracts\EventPusher',
    'App\Services\RedisEventPusher'
);
这段代码告诉容器当一个类需要 EventPusher 的实现时将会注入 RedisEventPusher,
现在我们可以在构造器或者任何其它通过服务容器注入依赖的地方进行 EventPusher 接口的依赖注入:
use App\Contracts\EventPusher;
/**
 * 创建一个新的类实例
 *
 * @param  EventPusher  $pusher
 * @return void
 */
public function __construct(EventPusher $pusher){
    $this->pusher = $pusher;
}
绑定有了 ,接下来就是考虑怎么使用的问题了。即 解析:
make方法 :
有很多方式可以从容器中解析对象,首先,你可以使用 make 方法,该方法接收你想要解析的类名或接口名作为参数:
$fooBar = $this->app->make('HelpSpot\API');
如果你所在的代码位置访问不了 $app 变量,可以使用辅助函数resolve
$api = resolve('HelpSpot\API');
自动注入 :
最后,也是最常用的,你可以简单的通过在类的构造函数中对依赖进行类型提示来从容器中解析对象,
控制器、事件监听器、队列任务、中间件等都是通过这种方式。在实践中,这是大多数对象从容器中解析的方式。
容器会自动为其解析类注入依赖,例如,你可以在控制器的构造函数中为应用定义的仓库进行类型提示,该仓库会自动解析并注入该类:
<?php
namespace App\Http\Controllers;
use App\Users\Repository as UserRepository;
class UserController extends Controller{
    /**
     * 用户仓库实例
     */
    protected $users;
    /**
     * 创建一个控制器实例
     *
     * @param  UserRepository  $users
     * @return void
     */
    public function __construct(UserRepository $users)
    {
        $this->users = $users;
    }
}
至此服务的使用也就理清楚了。回过头来,再考虑我们说了服务绑定,但是细致的说 还要讲明白绑定声明在哪里。
也就是概念:服务提供者  (serviceProvider) 所有的的 laravel 服务都是通过服务提供者启动的。
即所有的服务都继承自 Illuminate\Support\ServiceProvider 类。大部分服务提供者都包含两个方法: register 和 boot 。
在 register 方法中,你唯一要做的事情就是绑事物到服务容器,不要尝试在其中注册事件监听器,路由或者任何其它功能。
通过 Artisan 命令 make:provider 即可生成一个新的提供者:
php artisan make:provider RiakServiceProvider
register方法
正如前面所提到的,在 register 方法中只绑定事物到服务容器,而不要做其他事情,否则,一不小心就能用到一个尚未被加载的服务提供者提供的服务。
现在让我们来看看一个基本的服务提供者长什么样:
<?php
namespace App\Providers;
use Riak\Connection;
use Illuminate\Support\ServiceProvider;
class RiakServiceProvider extends ServiceProvider{
    /**
     * 在容器中注册绑定.
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton(Connection::class, function ($app) {
            return new Connection(config('riak'));
        });
    }
}
该服务提供者只定义了一个 register 方法,并使用该方法在服务容器中定义了一个 Riak\Contracts\Connection 的实现。
boot方法
如果我们想要在服务提供者中注册视图 composer 该怎么做?这就要用到 boot 方法了。
该方法在所有服务提供者被注册以后才会被调用,这就是说我们可以在其中访问框架已注册的所有其它服务:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class ComposerServiceProvider extends ServiceProvider{
    /**
     * Perform post-registration booting of services.
     *
     * @return void
     */
    public function boot()
    {
        view()->composer('view', function () {
            //
        });
    }
}
我们也可以在boot方法中类型提示依赖
use Illuminate\Contracts\Routing\ResponseFactory;
public function boot(ResponseFactory $response){
    $response->macro('caps', function ($value) {
        //
    });
}
这样服务提供者有了,服务就能顺利的被调用了。再接着往回想,那么服务提供者又是怎么注册声明的呢?
即:注册服务提供者
所有服务提供者都是通过配置文件 config/app.php 中进行注册,该文件包含了一个列出所有服务提供者名字的 providers 数组,
默认情况下,其中列出了所有核心服务提供者,这些服务提供者启动 Laravel核心组件,比如邮件、队列、缓存等等。
要注册你自己的服务提供者,只需要将其追加到该数组中即可:
'providers' => [
    // 其它服务提供者
    App\Providers\ComposerServiceProvider::class,
],
注: 在这里声明的服务,laravel在启动的时候会自动的运行所有服务提供者的内容。
延迟加载服务提供者
框架启动的时候只启动必要的服务,其它不必要的服务在用的时候启动这就是延迟加载服务提供者,这才是合理的或者说好的启动方案。
想要延迟加载一个提供者,设置 defer 属性为 true 并定义一个 provides 方法,该方法返回该提供者注册的服务容器绑定,
可以自行参考 RedisServiceProvider (声明 defer 以及 注册了多个服务绑定)
终于一个完整的服务提供,注册,绑定,解析流程完成了。
接下来为了使服务的调用更加简单,Laravel 使用了 Facades(门面)
门面:
门面为应用服务容器中的绑定类提供了一个“静态”接口。我们完全可以只使用服务,例如
$value = resolve('cache')->get('key'); // laravel 要解析 cache ,通过服务提供者列表找到 cache 的服务提供者 进而找到 服务绑定 的类实现,然后最终调用其 get方法
但是有了门面,我们调用起来就更加简单明了
use cache;
$value = cache::get('key');
上面的例子,内部工作流程实际上是:
laravel 在 config/app.php 里面声明的别名 aliases 找到 cache对应的门面类: Illuminate\Support\Facades\Cache::class
这个里面主要声明了方法:getFacadeAccessor   返回 cache  这次这个cache对应的就是服务容器绑定的名称了,
服务提供者会在启动的时候绑定 cache 对应的类实现,那么laravel自然就找到了对应的实现,进而调用其 get方法。
而对开发来说表面看起来就像是直接调用 cache这个类的 get静态方法一样,语义明确。
其实浏览门面的基类代码,Facade 就会发现魔术方法 __calStatic() 这里去调用指定的方法。
契约:
Laravel 中的契约是指框架提供的一系列定义核心服务的接口,Contracts(契约)使得实现更加的松耦合和简单
举例看一个紧耦合代码:
<?php
namespace App\Orders;
class Repository
{
    protected $cache;
    /**
     * 创建一个新的Repository实例
     *
     * @param  \SomePackage\Cache\Memcached  $cache
     * @return void
     */
    public function __construct(\SomePackage\Cache\Memcached $cache)
    {
        $this->cache = $cache;
    }
    /**
     * 通过ID获取订单
     *
     * @param  int  $id
     * @return Order
     */
    public function find($id)
    {
        if ($this->cache->has($id))    {
            //
        }
    }
}
在类初始化的时候自动注入 \SomePackage\Cache\Memcached 类对象,但是如果下次想换成 redis 等,就不得不来这里修改 注入的类。
那么如果使用契约呢:
<?php
namespace App\Orders;
use Illuminate\Contracts\Cache\Repository as Cache;
class Repository
{
    /**
     * 创建一个新的Repository实例
     *
     * @param  Cache  $cache
     * @return void
     */
    public function __construct(Cache $cache)
    {
        $this->cache = $cache;
    }
}
松耦合:
无论 cache 怎么变,实现处不用修改代码,所以降低了耦合性。
简单:
当所有 Laravel 服务都统一在简单接口中定义,很容易判断给定服务提供的功能。契约可以充当框架特性的简明文档
契约的使用:
Laravel中很多类都是通过服务容器进行解析,包括控制器,以及监听器、中间件、队列任务,甚至路由闭包。所以,要实现一个契约,需要在解析类的构造函数中类型提示这个契约接口。
契约和门面不同之处:
从使用上的不同,我们在使用门面的时候都是主动 声明 哪个门面,然后调用其"静态"方法,
而门面更多的是声明到类的构造函数中,系统会自动注入,接着就可以使用了。
契约允许你在类中定义显示的依赖,这样更加明确。

 

 

larevel学习笔记 程序体系结构

初学Laravel, 但是什么Laravel 安装,简介这里就不说了。这个去网上找找还是不少资料的

这里先浅显的说一下laravel的结构(当作抛砖引玉吧,好吧连砖都算不上。。。)

安装完Laravel 可以看到有4个文件夹:

app

包含了站点的controllers(控制器),models(模型),views(视图)和assets(资源)。这些是网站运行的主要代码,你会将你大部分的时间花在这些上面。

bootstrap

用来存放系统启动时需要的文件,这些文件会被如index.php这样的文件调用。

public

这个文件夹是唯一外界可以看到的,是必须指向你web服务器的目录。它含有laravel框架核心的引导文件index.php,这个目录也可用来存放任何可以公开的静态资源,如css,Javascript,images等。

vendor

用来存放所有的第三方代码,在一个典型的Laravel应用程序,这包括Laravel源代码及其相关,并含有额外的预包装功能的插件。

但我们的大部分开发都是在app文件夹下进行的

所以app 文件夹的详细介绍如下:

文件的文件夹

作用

/app/config/

配置应用程序的运行时规则、 数据库、 session等等。包含大量的用来更改框架的各个方面的配置文件。大部分的配置文件中返回的选项关联PHP数组。

/app/config/app.php

各种应用程序级设置,即时区、 区域设置(语言环境)、 调试模式和独特的加密密钥。

/app/config/auth.php

控制在应用程序中如何进行身份验证,即身份验证驱动程序。

/app/config/cache.php

如果应用程序利用缓存来加快响应时间,要在此配置该功能。

/app/config/compile.php

在此处可以指定一些额外类,去包含由‘artisan optimize’命令声称的编译文件。这些应该是被包括在基本上每个请求到应用程序中的类。

/app/config/database.php

包含数据库的相关配置信息,即默认数据库引擎和连接信息。

/app/config/mail.php

为电子邮件发件引擎的配置文件,即 SMTP 服务器,From:标头

/app/config/session.php

控制Laravel怎样管理用户sessions,即session driver, session lifetime。

/app/config/view.php

模板系统的杂项配置。

/app/controllers

包含用于提供基本的逻辑、 数据模型交互以及加载应用程序的视图文件的控制器类。

/app/database/migrations/

包含一些 PHP 类,允许 Laravel更新当前数据库的架构并同时保持所有版本的数据库的同步。迁移文件是使用Artisan工具生成的。

/app/database/seeds/

包含允许Artisan工具用关系数据来填充数据库表的 PHP 文件。

/app/lang/

PHP 文件,其中包含使应用程序易于本地化的字符串的数组。默认情况下目录包含英语语言的分页和表单验证的语言行。

/app/models/

模型是代表应用程序的信息(数据)和操作数据的规则的一些类。在大多数情况下,数据库中的每个表将对应应用中的一个模型。应用程序业务逻辑的大部分将集中在模型中。

/app/start/

包含与Artisan工具以及全球和本地上下文相关的自定义设置。

/app/storage/

该目录存储Laravel各种服务的临时文件,如session, cache,  compiled view templates。这个目录在web服务器上必须是可以写入的。该目录由Laravel维护,我们可以不关心。

/app/tests/

该文件夹给你提供了一个方便的位置,用来做单元测试。如果你使用PHPUnit,你可以使用Artisan工具一次执行所有的测试。

/app/views/

该文件夹包含了控制器或者路由使用的HTML模版。请注意,这个文件夹下你只能放置模版文件。其他的静态资源文件如css, javascript和images文件应该放在/public文件夹下。

/app/routes.php

这是您的应用程序的路由文件,其中包含路由规则,告诉 Laravel 如何将传入的请求连接到路由处理的闭包函数、 控制器和操作。该文件还包含几个事件声明,包括错误页的,可以用于定义视图的composers。

/app/filters.php

此文件包含各种应用程序和路由筛选方法,用来改变您的应用程序的结果。Laravel 具有访问控制和 XSS 保护的一些预定义筛选器。

这就是 Laravel 的大致结构。Laravel不像其它框架那样有许多xml文件用来系统配置,她更看重的是目录约定,在指定的目录下编写指定的操作。

顺带说一下 Laravel 的启动流程吧(这个在官方文档中有介绍)

  1. 请求进入 public/index.php 文件。
  2. bootstrap/start.php 文件创建应用程序对象并检测环境。
  3. 内部的 framework/start.php 文件配置相关设置并加载服务提供器。
  4. 加载应用程序 app/start 目录下的文件。
  5. 加载应用程序的 app/routes.php 文件。
  6. 将 Request 对象发送给应用程序对象,应用程序对象返回一个 Response 对象。
  7. 将 Response 对象发回客户端。

应用程序的启动文件被存放在app/start目录中。默认情况下,该目录下包含三个文件:global.php、local.php 和 artisan.php文件。

global.php启动文件默认包含一些基本项目,例如日志的注册以及载入app/filters.php 文件。

然而,你可以在该文件里做任何你想做的事情。无论在什么环境下,它都将会被自动包含进_每一个_request中。而local.php 文件仅在local环境下被执行。

当然,如果除了local环境你还有其他环境的话,你也可以为针对这些环境创建启动文件。

这些文件将在应用程序运行在该环境中时被自动包含。假设你在 bootstrap/start.php 文件中配置了一个 development 环境,

你可以创建一个 app/start/development.php 文件,在那个环境下任何进入应用程序的请求都会包含该文件。

查看和设置当前环境这个就另写一遍文档吧。

参考资料:

http://v4.golaravel.com/docs/4.2

http://www.cnblogs.com/huangbx/p/3586704.html (这个写的很好啊,大家去看这个博客吧,我的也就我自己能看懂。 - -!)

-------------------------------------------开始扯淡---------------------------------------------------

进来抽时间开始学习Laravel,过程应该是断断续续的。

最近忙的事情比较多,有很多事情都无从下手。艰难啊!

早就打算学Laravel了,但是时间有限,想了想不能再拖了,

所以即使忙也抽点时间看看。

Laravel 目前中文资料还是挺少的。 大牛们赶快行动起来吧。

-------------------------------------------扯淡完毕---------------------------------------------------

此文章通过 python 爬虫创建,原文是自己的csdn 地址: larevel学习笔记 程序体系结构

Laravel 查看和配置当前环境

可以通过

$environment = App::environment();
var_dump($environment);

获取当前环境

默认情况下当前环境是 production

那是因为在 文件 bootstrapstart.php 中有
设置:
$env = $app->detectEnvironment(array(
     'local' => array('homestead'),
));

homestead 就是指计算机的名字  ,linux 或者mac可以使用hostname 查看,
windows可以在powershell下使用hostname或者在计算机属性中查看 你的计算机名字一般不会是
homestead 所以找不到这个名字就会返回是production 即当前的默认环境

我们可以简要分析一下 首先分析 函数detectEnvironment()

定义在vendorlaravelframeworksrcIlluminateFoundationApplication.php 中

public function detectEnvironment($envs)
    {
        $args = isset($_SERVER['argv']) ? $_SERVER['argv'] : null;

        return $this['env'] = (new EnvironmentDetector())->detect($envs, $args);
    }

继续分析 detect() 函数

定义在vendorlaravelframeworksrcIlluminateFoundationEnvironmentDetector.php 中

	public function detect($environments, $consoleArgs = null)
	{
		if ($consoleArgs)
		{
			return $this->detectConsoleEnvironment($environments, $consoleArgs);
		}
		else
		{
			return $this->detectWebEnvironment($environments);
		}
	}

默认 $consoleArgs 为null 那么接着分析 函数detectWebEnvironment()

protected function detectWebEnvironment($environments)
	{
		// If the given environment is just a Closure, we will defer the environment check
		// to the Closure the developer has provided, which allows them to totally swap
		// the webs environment detection logic with their own custom Closure's code.
		if ($environments instanceof Closure)
		{
			return call_user_func($environments);
		}

		foreach ($environments as $environment => $hosts)
		{
			// To determine the current environment, we'll simply iterate through the possible
			// environments and look for the host that matches the host for this request we
			// are currently processing here, then return back these environment's names.
			foreach ((array) $hosts as $host)
			{
				if ($this->isMachine($host)) return $environment;
			}
		}

		return 'production';
	}

可见最后renturn 'production'; 由此 可以知道为什么返回 production了

那么我们只需要把 'local' => array('homestead'), 中的homestead 改成我们自己的计算机名字就会是当前环境变成local
你也可以命名其他环境。
这样你就可以把许多配置写到自己的文件夹下面了
例如 app/config 文件夹

这个时候很多配置当当前环境例如是local 没有的时候使用的默认的配置文件例如

cache.php
但是你也可以直接在config/local 下面创建cache.php 覆盖默认的环境配置

使用不同环境另一个一个作用是  敏感信息的保护

这个作用可以查看官方文档,我这里就不 复制粘贴了。

此文章通过 python 爬虫创建,原文是自己的csdn 地址: Laravel 查看和配置当前环境

PHP魔术常量

魔术常量(Magic constants)

PHP中的常量大部分都是不变的,但是有8个常量会随着他们所在代码位置的变化而变化,这8个常量被称为魔术常量。

    __LINE__,文件中的当前行号
    __FILE__,文件的完整路径和文件名
    __DIR__,文件所在的目录
    __FUNCTION__,函数名称
    __CLASS__,类的名称
    __TRAIT__,Trait的名字
    __METHOD__,类的方法名
    __NAMESPACE__,当前命名空间的名称

这些魔术常量常常被用于获得当前环境信息或者记录日志。

此文章通过 python 爬虫创建,原文是自己的csdn 地址: PHP魔术常量

html5 全局属性

有几个属性之前并不熟悉,现在总结一下
其实我是无意间 看到一个关于  contenteditable 的奇淫技巧才决定把每个属性都看一下的。

(有些并不是html5才有的属性)

0.  属性规定是否可编辑元素的内容
contenteditable 奇淫技巧链接 http://blog.jobbole.com/32823

<p contenteditable="true">这是一段可编辑的段落。请试着编辑该文本。</p>

一行代码将浏览器变为一个临时编辑器:

data:text/html, <html contenteditable> (写到浏览器输入url的地方回车即可)

在这基础上大牛们是这么改造的

可编辑区域并且自动获取焦点

data:text/html, <textarea style="font-size: 1.5em; width: 100%; height: 100%; border: none; outline: none" autofocus />

编辑内容的时候背景颜色改变

data:text/html, <html><head><link href='http://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'><style type="text/css"> html { font-family: "Open Sans" } * { -webkit-transition: all linear 1s; }</style><script>window.onload=function(){var e=false;var t=0;setInterval(function(){if(!e){t=Math.round(Math.max(0,t-Math.max(t/3,1)))}var n=(255-t*2).toString(16);document.body.style.backgroundColor="#ff"+n+""+n},1e3);var n=null;document.onkeydown=function(){t=Math.min(128,t+2);e=true;clearTimeout(n);n=setTimeout(function(){e=false},1500)}}</script></head><body contenteditable style="font-size:2rem;line-height:1.4;max-width:60rem;margin:0 auto;padding:4rem;">

最适合装X的来了:
实现一个php编辑器:

data:text/html, <style type="text/css">#e{position:absolute;top:0;right:0;bottom:0;left:0;}</style><div id="e"></div><script src="http://d1n0x3qji82z53.cloudfront.net/src-min-noconflict/ace.js" type="text/javascript" charset="utf-8"></script><script>var e=ace.edit("e");e.setTheme("ace/theme/monokai");e.getSession().setMode("ace/mode/php");</script>


当然不仅仅是 php 编辑器

改造成支持其他语言语法高亮的,可把 ace/mode/php 替换为:

Python -> ace/mode/python
C/C++ -> ace/mode/c_cpp
Javscript -> ace/mode/javascript
Java -> ace/mode/java
Scala -> ace/mode/scala
Markdown -> ace/mode/markdown
CoffeeScript -> ace/mode/coffee
其他……

jakeonrails 语法高亮风格用的是 monokai。
如果需要换成其他风格,,可把 ace/theme/monokai 替换为:

Eclipse -> ace/theme/eclipse
TextMate -> ace/theme/textmate
其他……

1. accesskey 访问元素的键盘快捷键

<!DOCTYPE HTML>
<html>
<body>

<a href="http://www.w3school.com.cn/" accesskey="u">W3School</a><br />
<a href="http://www.google.com/" accesskey="g">Google</a>
<br />
<label for="aa" accesskey="r">输入:</label>
<input type="text" id="aa" />
<label for="hobby" accesskey="h">爱好:</label>
<input type="checkbox" id="hobby" />
<label for="food" accesskey="y">菜系:</label>
<input type="checkbox" id="food" />
<br />

<p><b>注释:</b>请使用 Alt + <i>accessKey</i> 来访问带有快捷键的元素。</p>

</body>
</html>

 注意 以上快捷键不要和浏览器或者自定义的快捷键冲突,否则可能没有效果。

2. dir 属性规定元素内容的文本方向

<!DOCTYPE HTML>
<html>
<body>

<p dir="rtl">,,look at me..</p>
<bdo dir="rtl">dcba</bdo>
<p dir="rtl">dcba</p>
</body>
</html>

ltr      从左向右的文本方向。
rtl      从右向左的文本方向。
auto      让浏览器根据内容来判断文本方向。仅在文本方向未知时推荐使用。

3. draggable  draggable 属性规定元素是否可拖动

<!DOCTYPE HTML>
<html>
<head>
<style type="text/css">
#div1 {width:350px;height:70px;padding:10px;border:1px solid #aaaaaa;}
</style>
<script type="text/javascript">
function allowDrop(ev)
{
ev.preventDefault();
}

function drag(ev)
{
ev.dataTransfer.setData("Text",ev.target.id);
}

function drop(ev)
{
var data=ev.dataTransfer.getData("Text");
ev.target.appendChild(document.getElementById(data));
ev.preventDefault();
}
</script>
</head>
<body>

<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<br />
<p id="drag1" draggable="true" ondragstart="drag(event)">这是一段可移动的段落。请把该段落拖入上面的矩形。</p>

</body>
</html>

true      规定元素是可拖动的。
false      规定元素是不可拖动的。
auto      使用浏览器的默认特性。

4.  tabindex 属性规定当使用 "tab" 键进行导航时元素的顺序

<a href="http://www.w3school.com.cn/" tabindex="2">W3School</a>
<a href="http://www.google.com/" tabindex="1">Google</a>
<a href="http://www.microsoft.com/" tabindex="3">Microsoft</a>

此文章通过 python 爬虫创建,原文是自己的csdn 地址: html5 全局属性