Skip to content

2017

ZJU校园网Openwrt路由器设置

Why

学校这边上网每次都要输入账号,有登陆设备数量限制,玉泉这边还要申请静态IP地址,每人只能申请两个,申请下来还需要隔天才能生效……真的是有多不方便就多不方便。不过还好,学校的上网协议是标准的L2TP VPN认证,这几天想着把压箱底的小米路由器mini拿出来试一试看看能不能的openwrt上拨VPN然后分享出来。

刷机

Warning

刷机有变砖的风险,最好先刷入breed 或 uboot做一层保护

今日头条笔试解题报告(10.17)

之前随便投了一下今日头条竟然过了,虽然不是很想去,但是已经给了我笔试邀约好歹也就做一下,锻炼锻炼脑子,说句实话还是挺喜欢头条的题目的,做起来很有以前ACM刷题的感觉,不像其他公司总感觉"工程化"比较多。

推箱子

第一题比较简单,表面上无从下手但是仔细想想应该能想出来的,本质上跟走迷宫问题本质上是一致的,只不过在这题中状态既要保存人的位置也要保存箱子的位置。暴力搜索能够,AC代码:

Hugo使用笔记

Hugo是spf13大神写的一个静态博客生成器,拥有仅次于Hexo的用户量。相比于Hexo,Hugo使用Go编写,生成速度快了很多。除此之外,Hugo的设计更加合理,文档也比较详尽,比较适合我这种喜欢从零开始折腾的技术宅。本博客就是在hugo上搭建的,使用了自己编写的主题: canoe

迁徙博文

因为我以前使用的hexo,已经拥有相当一部分博文了,所以我需要将原来hexo格式的博文转换到hugo中。其中主要的差异在于front matter,hexo使用YAML格式,这也是支持最为广泛的格式。hugo则默认是toml,但是同时可以支持yaml和json格式。个人感觉toml格式并没有多大的方便,倒是YAML格式支持的最为广泛,所以我还是在hugo中指定了使用YAML格式的front matter:

metaDataFormat = "yaml"

GraphQL Learn (1) - Queries and Mutations

在此页面上,你将详细了解如何查询GrahQL服务器。

字段(Fields)

最简单的,GraphQL是关于要求对象上的特定字段。我们先来看一个非常简单的查询,当我们运行它时得到结果:

{
  hero {
    name
  }
}
{
  "data": {
    "hero": {
      "name": "R2-D2"
    }
  }
}
可以看到,查询与结果的形状完全相同。这对于GraphQL是至关重要的,因为您总是收到您期望的内容,并且服务器确切知道客户端要求哪些字段。

GraphQL Learn (2) - Schemas and Types

在此页面上,您将了解有关GraphQL类型系统的所有知识,以及如何描述可查询哪些数据。 由于GraphQL可以与任何后端框架或编程语言一起使用,因此我们将远离实现特定的详细信息,仅讨论概念。

类型系统(Type System)

如果您以前看过GraphQL查询,那么你应该知道GraphQL查询语言基本上是在对象上选择字段。 所以在以下查询中:

{
  hero {
    name
    appearsIn
  }
}

GraphQL Learn (3) - Validation

通过使用类型系统,可以预先确定GraphQL查询是否有效。 这样可以让服务器和客户端有效地通知开发人员在创建无效查询时,无需在运行时检查。

对于我们的星球大战示例,文件starWarsValidation-test.js包含许多无效的查询,可以用来测试当前实现的验证器。

首先,我们来看一个复杂的有效查询。 这是一个嵌套查询,类似于上一节的一个示例,但将重复的字段分解成一个片段:

GraphQL Learn (4) - Execution

经过验证,GraphQL查询由GraphQL服务器执行,然后返回一个与查询形状相同的结果,通常为JSON。

GraphQL无法执行没有类型系统的查询,让我们使用类型系统例子来说明执行查询,这个例子是我们教程中使用的类型系统中的一部分:

type Query {
  human(id: ID!): Human
}
type Human {
  name: String
  appearsIn: [Episode]
  starships: [Starship]
}
enum Episode {
  NEWHOPE
  EMPIRE
  JEDI
}
type Starship {
  name: String
}

GraphQL Learn (5) - Introspection

查询GraphQL架构有关它支持的查询的信息通常很有用。 GraphQL允许我们使用内省系统来做到这一点!对于我们的星球大战例子来说,文件starWarsIntrospection-test.js包含许多查询内省系统的查询,并且是一个完整的按照规范实现的测试文件。

我们设计了类型系统,所以我们应该知道系统中可用的类型。但是如果不知道,我们还可以通过查询__schema字段来询问GraphQL。这个字段始终存在于根类型中。

Polymer 2.0 文档笔记(1) Custom Elements

https://www.polymer-project.org/2.0/docs/devguide/custom-elements

Custom element names. By specification, the custom element's name must start with a lower-case ASCII letter and must contain a dash (-). There's also a short list of prohibited element names that match existing names. For details, see the Custom elements core concepts section in the HTML specification.

自定义元素的命名规则: 按照规范,自定义元素的命名中必须以一个小写字母开始,必须包含一个连接符(-)

Custom properties can only be defined in rule-sets that match the html selector or a Polymer custom element. This is a limitation of the Polymer implementation of custom properties.

Polymer实现方式的局限: 只有html元素或者Polymer自定义元素才能使用自定义CSS属性。(个人感觉虽然shadowDOM原生支持CSS隔离,但是一部分元素能用cssnext一部分元素不能用,割裂感太严重了。)

Polymer does not currently support extending built-in elements. The custom elements spec provides a mechanism for extending built-in elements, such as <button> and <input>. The spec calls these elements customized built-in elements. Customized built-in elements provide many advantages (for example, being able to take advantage of built-in accessibility features of UI elements like <button> and<input>). However, not all browser makers have agreed to support customized built-in elements, so Polymer does not support them at this time.

因为浏览器厂商的争议,Polymer不支持扩展内建元素。

在生产环境下main document不要定义自定义元素。基于实验目的可以使用 HTMLImports.whenReady(callback)方法等待所有html import 加载完毕。

组件生命周期

标准的几个生命周期回调:

Reaction Description
constructor Called when the element is upgraded (that is, when an element is created, or when a previously-created element becomes defined).
connectedCallback Called when the element is added to a document.
disconnectedCallback Called when the element is removed from a document.
attributeChangedCallback Called when any of the element's attributes are changed, appended, removed, or replaced,

For each reaction, the first line of your implementation must be a call to the superclass constructor or reaction.

开始写自己的回调事件之前都必须先调用super上面的回调。Super.connectedCallback();  

The constructor can't examine the element's attributes or children, and the constructor can't add attributes or children.

Constructor函数中不能对DOM进行任何操作。

In general, work should be deferred to connectedCallback as much as possible—especially work involving fetching resources or rendering. However, note that connectedCallback can be called more than once, so any initialization work that is truly one-time will need a guard to prevent it from running twice. In general, the constructor should be used to set up initial state and default values, and to set up event listeners and possibly a shadow root.

https://html.spec.whatwg.org/multipage/custom-elements.html#custom-element-conformance

Constructor里面只应该做一些初始化状态、值、绑定事件,建立shadowroot之类的工作。其他工作应该推迟到connectedCallback里面做,但是需要注意的是__connectedCallback可能会调用多次__。

The custom elements specification doesn't provide a one-time initialization callback. Polymer provides a readycallback, invoked the first time the element is added to the DOM.

Polymer提供了一个规范里面没有的回调: Ready, 只在元素第一次加入DOM时候触发。

ready() { 
  super.ready(); 
  // When possible, use afterNextRender to defer non-critical 
  // work until after first paint. 
  Polymer.RenderStatus.afterNextRender(this, function() { 
    ... 
  }); 
} 

Elements have a custom element state that takes one of the following values:

  1. uncustomized: The element does not have a valid custom element name. It is either a built-in element (<p>, <input>) or an unknown element that cannot become a custom element (<nonsense>)
  2. undefined: The element has a valid custom element name (such as "my-element"), but has not been defined.
  3. custom: The element has a valid custom element name and has been defined and upgraded.
  4. failed: An attempt to upgrade the element failed (for example, because the class was invalid).

元素内部拥有四个状态,我们不能直接获得,但是可以使用:defined伪类来选择"uncustomized"和"custom"的元素。

自定义元素

Hybrid elements: should continue to use the Polymer DOM APIs, but may require some changes. Legacy elements: can use the Polymer DOM APIs or the native DOM APIs. Class-based elements: should use native DOM APIs.

总共有三种自定义元素:

  • Hybird element: 主要是为了兼容Polymer 1.x;但 Gesture Events只支持Hybird elements。详见下文。
  • Legacy element:处于两者之间(没有看出有什么用处)
  • Class-based element:Polymer 2.0 最常用的自定义元素方式。
Class-based elements
// define the element's class element
class MyElement extends Polymer.Element {
  // 'is' getter, return the tag name which is lowercased. required.
  static get is(){
    return 'my-element';
  }
  // Define the properties.
  static get properties() {}
  // Element class can define custom element reactions
  constructor() { super(); }
  connectedCallback() {
    super.connectedCallback();
    console.log('my-element created!');
  }
  ready() {
    super.ready();
    this.textContent = 'I\'m a custom element!';
  }
}

// Associate the new class with an element name
customElements.define(MyElement.is, MyElement);

// create an instance with createElement:
var el1 = document.createElement('my-element');

// ... or with the constructor:
var el2 = new MyElement();
Legacy elements
// register an element  
MyElement = Polymer({  
is: 'my-element',  
// See below for lifecycle callbacks  
created: function() { this.textContent = 'My element!'; }  
});  
// create an instance with createElement:  
var el1 = document.createElement('my-element'); 
// ... or with the constructor: 
var el2 = new MyElement();

Legacy元素的生命周期有着不同的名字:

Legacy lifecycle cb Class-based lifecycle cb
Created constructor
Ready ready
Attached connectedCallback
Detached disconnectedCallback
attributeChanged attributedChangedCallback
Hybird elements

这种方式主要是为了兼容Polymer 1.x。可以使用Class-based方式改写。详见Gesture Events。

自定义属性(properties)

自定义属性主要在properties getter中定义。可以直接传一个字符串。也可以传给他们一个Object。 Object需要包含下面几个属性:

type 数据类型

Type: constructor  Attribute type, used for deserializing from an attribute. Polymer supports deserializing the following types: Boolean, Date, Number, String, Array and Object. You can add support for other types by overriding the element's  _deserializeValue method. Unlike 0.5, the property's type is explicit, specified using the type's constructor. Seeattribute deserialization for more information.

When reflecting a property to an attribute or binding a property to an attribute, the property value is serialized to the attribute. By default, values are serialized according to value's current type, regardless of the property's type value:

String No serialization required.
Date or Number Serialized using toString. Boolean Results in a non-valued attribute to be either set (true) or removed (false). Array or Object Serialized using  JSON.stringify.

ArrayObject需要写成JSON的形式,Date需要写成任何符合Date解析形式的String。

可以重写属性序列化函数: _serializeValue method.

_serializeValue(value) { 
  if (value instanceof MyCustomType) { 
    return value.toString(); 
  }
  return super._serializeValue(value);
} 
value 默认值

Type: boolean, number, string or function. Default value for the property. If value is a function, the function is invoked and the return value is used as the default value of the property. If the default value should be an array or object unique to the instance, create the array or object inside a function. See Configuring default property values for more information

跟Vue一样,如果一个属性的默认值是以Array或者Object,那么所有该元素的实例的默认值都共享一个变量。如果要使每个元素拥有一份完全独立的拷贝的话,需要在这个值外面包一个函数。

class XCustom extends Polymer.Element { 
static get properties() { 
    return { 
      mode: { 
        type: String, 
        value: 'auto' 
      }, 
      data: { 
        type: Object, 
        notify: true, 
        value: function() { return {}; } 
      } 
    } 
}
reflectToAttribute

Type: boolean Set to true to cause the corresponding attribute to be set on the host node when the property value changes. If the property value is Boolean, the attribute is created as a standard HTML boolean attribute (set if true, not set if false). For other property types, the attribute value is a string representation of the property value. Equivalent to reflect in Polymer 0.5. See Reflecting properties to attributes for more information

值的变化是否同步更新DOM上面的attr

For a Boolean property to be configurable from markup, it must default to false. If it defaults to true, you cannot set it to false from markup, since the presence of the attribute, with or without a value, equates to true. This is the standard behavior for attributes in the web platform. If this behavior doesn't fit your use case, you can use a string-valued or number-valued attribute instead.

Boolean类型的属性只能把默认值设为false,因为标准的HTML属性行为(存在为true,不存在为false),如果必须把默认值设为true,可以用String或者Number类型属性代替。

readOnly

Type: boolean If true, the property can't be set directly by assignment or data binding.

notify

Type: boolean If true, the property is available for two-way data binding. In addition, an event, property-name-changed is fired whenever the property changes

DOM上面的属性变化是否调用回调(反向绑定)属性this.firstName的变化会触发first-name-changed事件。这些事件被用在了双向绑定系统,在外部代码里面我们可以直接使用addEventListener有点像Java里面的约定大于配置的思想,这样能使代码变得简单易懂

computed

Type: string The value is interpreted as a method name and argument list. The method is invoked to calculate the value whenever any of the argument values changes. Computed properties are always read-only. See Computed properties for more information

传入一个包含方法名和参数列表的字符串,参数必须readOnly,将该方法调用参数运行的结果作为该项的值

observer

Type: string The value is interpreted as a method name to be invoked when the property value changes. Note that unlike in 0.5, property change handlers must be registered explicitly. The propertyNameChanged method will not be invoked automatically. See Property change callbacks (observers) for more information

传入一个方法名称,当值发生变化时自动执行该方法

其他

  1. 隐式声明属性: if you add it to a data binding or add it as a dependency of an observer, computed property, or computed binding.
  2. Priavte和Protected属性:分别用__prop和_prop表示。