Shadow DOM简介

这篇文章假设您已经掌握了DOM以及与DOM操作相关的JS部分。文中的代码符合ES6语法。

Shadow DOM是什么

一个网页会形成一颗DOM树,树上有很多结点,但过多的结点使结构复杂起来,Shadow DOM允许我们用封装的方式简化这种结构。Shadow DOM是网页DOM树上的特殊结点的结构,这个结点内部同样可以包含一颗DOM树,不过在网页DOM树上只会看到Shadow DOM的根节点。如<video>标签实际上运用了Shadow DOM来包含一系列组件。

Shadow DOM的用法

向普通元素附着Shadow DOM

let shadow = elementRef.attachShadow({mode:'open'});

配置参数可选open或closed,用参数决定Shadow DOM是否可在JavaScript内访问。open模式下,elementRef.shadowRoot返回shadowRoot,而closed模式下返回null,因此如果使用closed模式,需要在建立ShadowDOM时保存引用(如上)。

改变Shadow DOM的内容

获取到ShadowDOM的引用(shadow)后发现,shadowRoot也可以像其他DOM元素一样操作,比如设置innerHTML或者append元素等。

封装Custom Element

ShadowDOM的真正作用在于封装。我们可以使用类包装我们的元素。

//代码来自MDN
class PopUpInfo extends HTMLElement {
  constructor() {
    // 必须首先调用 super方法
    super();
    var shadow = this.attachShadow({mode: 'open'});
    // 元素的具体功能写在下面

    ...
  }
}

包装完成后使用以下方式在网页中调用:

customElements.define('popup-info', PopUpInfo);
<popup-info></popup-info>

关于屏幕共享/远程控制

远程控制

控制另一台电脑

Windows远程桌面

当之无愧的最优解,局域网环境下十分顺滑,外网环境下也很少感到卡顿(除非网络实在不好),据说有些企业版本还支持GPU,tql

VNC

有点卡慢,但通用性很强,几乎什么平台都支持。

Teamviewer

有点卡慢,但不得不说是远程环境下的最佳选择。Teamviwer的亮点也在于支持各种类型的设备,移动端到PC/Mac通吃。

屏幕共享/显示器拓展

一台电脑仅作为显示器或串流

Steam串流

支持各种应用程序而不仅是游戏,凭心而论,Steam串流的效果不错,不过延迟也是可以感受到的。只支持局域网。

Airserver

使用这个软件可以让Windows/Mac/iPad等设备的显示器作为mac/ios设备的拓展显示器,支持Airplay的设备可以将屏幕投射到安装了Airserver的设备上。实测中非常不稳定,很容易就掉线。

Windows10的投射和连接

这两个功能允许支持Miracast的安卓/Win设备投屏到Windows(将Windows设备作为Miracast显示器),也可以将这台电脑投射到支持Miracast显示的设备上。但稳定性和延迟都欠佳。

Duet Display

该软件支持将iPad作为Mac的第二显示屏,支持使用USB-lightning连接,速度尚可,画面质量一般(上述所有画面质量都挺一般的),可以作为选择。在iPad上的触控操作是有效的,这是一台触摸显示器。

计算机网络?(一)

基础概念

路由器

负责连接两条或以上传输线路的计算机。同时路由器也是一个网关,它在网络层交换数据包。

交换机

网络中每台计算机通过一条点对点的链路连接到交换机(switch)。交换机有多个端口(port),每个端口连接一台计算机。交换机的工作是中继网络中的数据包,通过数据包中的地址确定数据发送给哪台计算机。

网关

将两个不同的网络连接起来并提供必要转换的机器,其硬件和软件的总称叫网关(gateway),网关可以工作在协议的不同层次。

子网

定义一

广域网中运行应用程序的计算机被称为主机(host),而连接这些主机的网络的其余部分被称为通信子网(communication subnet)/子网(subnet)。子网的工作是把信息从一台主机传递给另一台主机。

在多数广域网中,子网由传输线路和交换元素组成。传输线路(transmission line)指有线或无线链路,交换元素(switching element)/交换机(switch)是负责连接两条或以上传输线路的计算机,他们现在又叫路由器(router)

层次相关

OSI模型

OSI(Open Systems Interconnection,开放系统互联)模型描述了较为通用的网络模型,它本身不定义服务或协议。

物理层(physical layer)

物理层关注在一条通信信道上传输原始比特,涉及传输方式和细节,以及物理传输介质等。

数据链路层(data link layer)

数据链路层的主要任务是隐藏物理传输中的错误,使物理连接变成逻辑上无差错的数据链路。发送方将数据拆分成数据帧(data frame)并顺序发送,如果服务是可靠的,接受方给发送方发回确认帧(acknowledgement frame),帧的尾部带有检查码。

网络层(network layer)

网络层的主要功能是控制子网的运行。网络层负责路由,处理拥塞,决定服务质量,允许不同协议的异构网络相互连接成为互联网络。

传输层(transport layer)

传输层接受上一层的数据,在必要的时候把这些数据分割成较小的单元,然后把这些数据单元传递给网络层,并且确保数据正确抵达另一端。OSI的1~3层是链式连接的,而4~7层是端到端的。

会话层(session layer)与表示层(presentation layer)

会话层提供了对话控制、令牌管理、同步功能等服务,表示层管理数据的语义、抽象结构。由于现在的应用层实现了部分会话层与表示层的功能,在TCP/IP协议中不存在这两层。

应用层(application layer)

应用层包含了用户通常需要的各种协议,如HTTP(HyperText Transfer Protocol)、HTTPS、FTP、SFTP等协议。

层次设计问题

路由(routing)

在源和目的地之间找到合适的路径。网络有时有一些链路或者路由器偶尔发生故障,网络应该能够选出别的线路,这个主题叫做路由。

寻址(addressing)和命名(naming)

每一层在特定的消息中都需要一种机制来标识发送方和接收方,这种机制在下层叫寻址,上层叫命名。

拥塞(congestion)

由于太多的计算机发送太多的流量,网络没有能力传递所有的数据包。此时需要流量控制,发生拥塞时,每台计算机都减少对网络的宽带需求,这种策略对每一层都适用。

服务质量(Quality of Service)

网络为需要实时(real-time)传递的应用程序与高吞吐量的应用程序提供服务,QoS是调和这些竞争需求的机制的名称。

php展示当前目录下文件

挺简单的一个文件,耗时一两个小时看UIkit文档以及熟悉了下php的相关函数,该文件配合伪静态规则可以实现通过浏览器查看下载文件。UIkit好看。

<?php 
$files;
class fileinfo
{
    public $filename;
}
$handler = opendir(__DIR__);
while(($filename=readdir($handler))==true){
    if($filename=="." || $filename=="..")continue;
    $temp=new fileinfo();
    $temp->filename=$filename;
    $temp->filedate=date('r',filemtime(getcwd().'/'.$filename));
    $temp->filesize=filesize(getcwd().'/'.$filename);
    $files[]=$temp;
    
}
closedir($handler);
echo '<div class="uk-card uk-card-body uk-card-default" style="margin:20px"><table class="uk-table uk-table-divider">
<thead>
    <tr>
        <th>文件名</th>
        <th>修改时间</th>
        <th>文件大小</th>
    </tr>
</thead>
<tbody>';
echo '<tr><td><a class="" href="../">..</a><br></td><td></td><td></td></tr>';
foreach($files as $fileinfo){
    echo'<tr>';
    echo '<td><a class="" href="'.$fileinfo->filename.'">'.$fileinfo->filename.'</a></td>';
    echo '<td>'.$fileinfo->filedate.'</td>';
    echo '<td>'.$fileinfo->filesize.'bytes</td>';
    echo'</tr>';
}
echo '    </tbody>
</table></div>';
echo '<!-- UIkit CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/uikit/3.0.3/css/uikit.min.css" />

<!-- UIkit JS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/uikit/3.0.3/js/uikit.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/uikit/3.0.3/js/uikit-icons.min.js"></script>';

?>

http://demo.guohere.com/files/

unsyntactic break/continue

从unsyntactic可以看出来,这个报错其实是异步导致的。

使用jsonp请求的时候不知道它是异步的,于是我在for循环内发送jsonp请求。而我也在promise对象的then方法内写了continue,由于promise是异步的,触发break的时候循环可能已经执行完了,所以break与continue就不能用(在then方法中)了。

根据第一个请求结果决定发送第二个请求的场景,看来需要写到then方法里了。

说到js异步,我们来看一下async函数:

async function refresh(){
console.log(1);
var reply = await getData();
console.log(2);
return reply;
}

refresh().then(function(re){console.log(re)});

这段代码会先输出1,遇到await时等待getData()执行完后输出2,最后执行回调函数。

这么做有什么用呢?比如在等待getData完成的时候(通常网络请求耗时较长),该函数由于await交出了程序执行权,程序就不用等了,可以先执行下面的代码。

之所以能够这么顺利地交出执行权,是因为refresh()实际上在遇到await的时候先返回了一个promise对象,并且async函数自带执行器,待getData完成又能够继续执行函数。

async函数是属于es7的语法,但babel已经支持,实质上是对generator函数和自动执行器的包装。想了解更多可以访问下面的链接:

http://www.ruanyifeng.com/blog/2015/05/async.html