Root


  • Home

  • About

  • Tags

  • Categories

  • Archives

input组件

Posted on 2018-07-04 | In 微信小程序

当前微信小程序运行框架为mpvue1.0.12版本

  1. 添加button组件后@click可以使用,bindtap不可以使用
    报错信息:command根本无法跳转
    avatar
    原因:(1)mpvue框架问题,不支持使用bindchange、bindinput,需要修改为@chang、@input
    (2)这种错误,也有可能是第三方框架编译后生成的dist/app.json中pages顺序与第三方框架中定义的pages顺序不同,需要调整
  2. 需要数据绑定 v-model
    问题:去掉就会无法正常获取input数据
    讲解:(1)v-model:双向数据绑定(表单控件)< input> < textarea> < select>
    (2)v-bind:绑定数据和属性 e.g v-bind:class= –> :class
  3. event绑定在mpvue中也不同 e.detail.value

前端自动化测试

Posted on 2018-07-04 | In 自动化测试

测试工具:单元测试、功能测试、性能测试、安全测试

  1. Karma工具:功能强大
    Jasmine(基于BDD的测试框架)+PhantomJS(无界面的浏览器)
  2. SlimerJS 自动化的前台工具
    服务器端的JS API工具
  3. Selenium 直接运行在浏览器 <===> Katalon
  4. phantomJS 服务器端的JS API工具
  5. CasperJS 工具
    只能与无界面浏览器(Headless Browser结合),e.g PhantomJS、SlimerJS
    有可能有浏览器兼容问题
    开源的导航脚本和测试工具 <---> 自动化测试脚本
    提供方法组件 –> 基于PhantomJS或SlimerJS所提供的js API
    不支持ES6/ES7
  6. Protractor Angular官方
    测试用例的组织方式可以自由使用Jasmine或Mocha
    在真实的浏览器测试
    内置的页面加载等待,需要自己设置合理的超时
  7. Nightwatch.js
    手动在测试代码中添加合适的等待来保障测试的稳定
    安装繁琐
  8. TestCafe
    环境一键完成,对ES6/7
    社区生态不成熟
  9. CodeceptJS
    对测试运行工具进行一层封装
    支持ES6
  10. mocha + chai
  11. JEST

Ruby on Rails教程(第4版)-2017

Posted on 2018-07-02

第一章 从零开始,完成一次部署

  1. /bin 可执行的二进制文件
    /lib 代码库模块文件
    /vendor 第三方代码,例如插件和gem
  2. MVC架构模式
    MVC框架
    视图 <---> C <---> web <— 浏览器

MVC框架

Posted on 2018-07-01 | In 前端
  1. Model:负责管理数据,大部分业务逻辑也应该在Model中
    View:负责渲染用户界面,应该避免在View业务中设计业务逻辑
    Controller:负责接受用户输入,根据用户输入调用对应的Model部分逻辑,把产生的数据结果交给View部分,让View渲染出必要的输出
  2. 缺陷:实际框架中总是允许View和Model直接通信,所以数据流向会变得复杂
  3. 区别
    服务器端MVC框架往往就是每个请求只在Controller-Model-View三者之间走一圈,结果返回给浏览器去渲染或者处理,然后销毁请求的生命周期,严格的单向数据流;浏览器端MVC框架,存在用户交互处理
  4. 系统提供什么样的服务,通过Controller暴露函数来实现。每增加一个功能,Controller往往就要增加一个函数

深入浅出React和Redux

Posted on 2018-07-01 | In 前端

第1章 React新的前端思维方式

1.1 初始化react项目 create-react-app

React依赖于一个庞大的技术栈:比如转译Javascript代码需要Babel,模块打包工具需要webpack,定制build过程需要grunt或者gulp,技术栈各自需要配置文件

1.2 组件Component

  1. React首要思想是通过组件来开发应用
  2. import是ES6语法中倒入文件模块的方式,ES6语法的Javascript代码会被webpack和babel转译成所有浏览器都支持的ES5语法
  3. Component作为所有组件的基类

1.2.1 JSX

JSX使我们在Javascript中像HTML一样编写,e.g ReactDOM.render的第一个参数

  1. 在JSX中使用的“元素”不局限于HTML中的元素,可以是任何一个React组件,根据第一个字母是否大写判断是否为React元素
  2. JSX中通过onclick给元素添加事件处理函数,onclick控制在组件范围内,将onclick挂载在最顶端的DOM节点上

最顶端DOM节点添加一个事件处理函数,使用事件委托(event delegation)方式处理,所有点击事件被事件处理函数捕获,
然后根据具体组件分配给特定函数

1.3 分解React应用

  1. 所有的配置文件设置在node_modules/react=scripts目录下
  2. build:创建生产环境优化daima
    test:单元测试
    eject:弹射命令,一系列技术栈配置弹射到顶层;但是命令不可逆,建议备份
  3. babel
    1
    2
    3
    4
    5
    6
    //webpack.config.dev.js
    {
    test: /\.(js|jsx)/
    ......
    loader: 'babel'
    }

所有以js或者jsx为扩展名的文件,都由babel处理

1.4 React的工作方式

1.4.1 jQuery如何工作 $

jQuery逻辑:1.根据CSS规则找到id为clickCount按钮;2.挂上一个匿名事件处理函数;3.事件处理函数中选中需要修改的DOM元素;4.读取文本值并加以修改;5.修改这个DOM元素
缺点:项目庞大时代码容易纠缠

1.4.2 React如何工作

关注于“我想要显示什么”,UI = render(data)
React通过重复渲染来实现用户交互,每次渲染只重复渲染最少的DOM元素

第五章关注对比过程

JSX会被Babel解析为一条条创建React组件或者HTML元素的语句

DOM树是对HTML的抽象,Virtual DOM是对DOM树的抽象;DOM不触及浏览器的部分,只存在于Javascript空间的树形结构

事件 –> render –> Virtual DOM –> DOM修改

第二章 设计高质量的React组件

组件设计原则:高内聚、低耦合

2.2 组织组件数据prop和state

2.2.1 prop

  1. prop为组件的对外接口,state为组件的内部状态
    prop属性不限于纯,数据prop的类型不是字符类型时,JSX中必须用{}把prop包住,所以style两层{}

    1
    2
    //外层{},JSX语法;内层{},代表对象常量
    style = {{color: "red"}}
  2. constructor函数
    给this.props赋值是React.Component构造函数的工作之一
    定义super(props),进而类实例的所有成员函数可以通过this.props访问父组件传递的props值

  3. 解构赋值

    1
    const {caption} = this.props
  4. propType检查:组件声明接口规范
    propTypes能够发现开发阶段问题,不建议在产品阶段,e.g babel-react-optimize

    1
    2
    3
    4
    Counter.propTypes = {
    caption: PropTypes.string.isRequired,
    initValue: PropTypes.number //无isRequired,非必须属性
    }

2.2.2 state:存在的目的是让组件来改变

  1. 组件的state必须是一个Javascript对象,不能是string或者number这样的简单数据
  2. React的defaultProps功能:优化isRequired的频繁判断
  3. 组件内部修改this.state,并没有驱动组件进行重新渲染,调用this.setState改变组件状态

2.3 组件生命周期

组件第一次渲染:constructor –> getInitialState –> getDefaultProps –> componentWillMount –> render –> componentDidMount

  1. constructor
    无状态的React组件往往不需要定义构造函数
    目的:(1)初始化state;(2)绑定成员函数的this环境,this始终指向当前组件实例
    类实例this.onClickIncrementButton = this.onClickIncrementButton.bind(this)
  2. getInitialState和getDefaultProps
    getInitialState:只有在React.createClass方法创造的组件中才能初始化组件的this.state
    getDefaultProps: 返回值作为props初始值

    1
    2
    3
    4
    5
    6
    7
    //ES6 在构造函数中通过this.state赋值完成状态的初始化
    class Sample extends React.component {

    }
    Sample.defaultProps = {

    }
  3. render:纯函数(根据this.props和this.state)
    render并不做实际的渲染动作,只是返回一个JSX描述的结构,最终由React来操作渲染过程

  4. componentWillMount和componentDidMount
    调用关系:componentWillMount –> render –> componentDidMount
    componentWillMount:“将要装载”,没有任何渲染出来的结果,所有可以在componentWillMount中做的事情,都可以提前到constructor中去做,可以在服务器端和浏览器端调用

服务器端js:Node.js
componentDidMount:render函数调用完之后,componentDidMount函数并不会立即调用,componentDidMount被调用的时候,render函数返回的东西已经引发了渲染,组件已经“装载”到DOM树上,只在浏览器端被调用

  1. React和其他UI库的结合

d3.js已经支持了丰富的绘制图表的功能
React+jQuery:利用componentDidMount函数,此时React的DOM组件对应的DOM已经存在,所有的事件处理函数已经设置好,可以调用jQuery在已经绘制号的DOM基础上增强新的功能

组件更新过程:componentWillReceiveProps –> shouldComponentUpdate –> componentWillUpdate –> render –> componentDidUpdate

  1. componentWillReceiveProps(nextProps)
    (1)在render函数里面被渲染的子组件就会经历更新过程,不管父组件传给子组件的props有没有改变,都会触发子组件的componentWillReceiveProps函数

this.setState方法不会触发这个过程,因为函数会根据新的props值来计算是不是要更新内部状态state,更新内部状态的方法就是this.setState,若调用就形成死循环

(2)在JSX中直接把匿名函数赋值给onclick,并不提倡,每次渲染都会创造一个新的匿名对象,可能会引发子组件不必要的重新渲染

1
<button onclick = { () => this.forceUpdate() }></button>

(3)nextProps代表着一次渲染传入的props的值,this.props代表的是上一次渲染的props值,只有两者有变化时才有必要调用this.setState更新内部状态

  1. shouldComponentUpdate(nextProps,nextState):定制函数
    决定了一个组件什么时候不需要渲染
    在组件添加shouldComponentUpdate函数,就沿用所有React组件父类React.Component中的默认实现方式(即简单的返回true)
  2. componentWillUpdate和componentDidUpdate
    两个函数将render夹在中间
    若componentDidMount调用jQuery,则重新渲染时在coomponentDidUpdate函数再次调用jQuery

卸载过程

componentWillUnmount: 和componentDidMout有关,把创造的DOM元素清理掉

组件向外传递数据

函数是一等功名,函数本身可以被看做一种对象

React组件state和Prop的局限

每个Counter组件由自己的状态记录当前计数,而父组件ControlPanel也有一个状态来存储所有Counter计数总和,即数据重复
把数据源放在React组件之外形成全局状态,把各个组件保持和全局状态一致

第三章 从Flux到Redux

3.1 Flux

  1. MVC框架
    分为四个部分:Dispatcher,Store,Action,View
    Dispatcher:处理动作action分发,维持Store之间的依赖关系
    Store:负责存储数据和处理数据相关逻辑
    Action:驱动Dispatcher的Javascript对象
    View:视图
    数据流向:Action –> Dispatcher –> Store –> View —Action—> (Dispatcher)
  2. 创建Flux
    (1)Dispatcher:几乎所有应用都只需拥有一个Dispatcher
    (2)action:纯粹的数据,必须有type字段
    定义需要两个文件:一个定义action类型,一个定义action的构造函数
    1
    2
    3
    4
    AppDispatcher.dispatch({
    type: ActionType.INCREMENT,
    counterCaption: counterCaption
    })

(3)Store:为一个对象,每一个Store都是一个全局惟一的对象,存储应用状态,同时还要接受Dispatcher派发的动作,根据动作决定是否要更新应用
Store只有注册到Dispater实例上才能真正发挥作用

注册过程:把CounterStore注册到全局惟一的Dispatcher上。Dispatcher有一个函数为register,接受一个回调函数作为参数,返回值为token,token可用于Store之间的同步,保存在dispathchToken字段上。

1
2
3
AppDispatcher.register((action) => {

})

当通过register函数把一个回调函数注册到Dispatcher之后,所有派发给Dispatcher的action对象,都会传递到这个回调函数中来,回调函数要做的,就是根据action对象来决定该如何更新自己的状态
(4)View
存在于Flux框架中的React组件需要实现以下的功能:
a.创建时读取Store上状态来初始化组件内部状态
b.当Store上状态发生变化,组件立即同步更新内部状态保持一致
c.View如果改变Store状态,必须且只能派发action

  1. Flux不足
    (1)Store之间依赖关系,有依赖关系的Store必须用上Dispatcher的waitFor桉树
    (2)难以进行服务器端渲染
    (3)Store混杂了逻辑和状态

3.2 Redux(Redux是Flux的一种实现)

基本原则

  1. 唯一数据源:只存储在惟一的一个Store
  2. 保持状态只读:修改状态只能创建一个新的状态对象返回给Redux,由Redux完成新的状态的组装
  3. 数据改变只能通过纯函数完成:纯函数Reducer
    1
    reducer(state,action)

React的Rudex只负责计算状态,不负责存储状态

Redux实例

React和Redux是两个独立的产品,Redux中每个构造函数都返回一个action对象,Flux中的Dispatcher简化为Store上的一个dispatcher,state是由Store管理的

容器组件和傻瓜组件

容器组件:负责和Redux Store打交道,读取、监听store的状态,派发action对象,通过props将状态传递给展示组件
傻瓜组件(展示组件):负责渲染界面的组件,没有state

组件Context “上下文环境”

解决问题:解决需要一层层传递props
解决方法:让一个树状组件所有组件都能访问一个共同的对象,创建特殊React组件(Provider)为Context提供者
Provider的render函数简单的把子组件渲染出来

  1. 每个React组件props都有一个特殊属性children代表子组件
  2. childContextTypes属性,getChildContext函数,两者相互对应,子组件才能访问到context

    1
    2
    3
    Provider.childContextType = {
    store: PropTypes.object
    }
  3. 子组件通过this.context访问context对象

  4. 更新constructor
    1
    super(props,context)

React-Redux

  1. connect连接容器组件和傻瓜组件
    执行两次函数:第一次执行connect函数,第二次执行connect函数返回的函数;最后产生容器组件
    1
    export default connect(mapStateToProps,mapDispatchToProps)(Counter)

connect函数具体工作:把Store上的状态转化为内层傻瓜函数的prop(mapStateToProps);把内层傻瓜组件中的用户动作转化为派送给Store的动作(mapDispatchToProps)

  1. Provider
    store必须包含三个函数的object,即subscribe、dispatch、getState

第四章 模块化React和Redux应用

4.2 代码文件的组织方式

  1. 按角色组织
  2. 按功能组织
    index.js文件作为模块公开接口

4.3 状态树的设计:Store上状态树的设计

  1. 一个状态节点只属于一个模块
    Store上的state只能通过reducer来更改,导出的reducer只能修改Redux的状态树上一个节点下的数据
  2. 避免冗余数据

范式化:传统的关系型数据库对数据结构进行的操作,其实就是去除数据的冗余,对数据结构的处理和关系型数据库正好相反,通过数据冗余来减少读取数据库时的数据关联工作

  1. 树形结构扁平

4.5 ToDo应用实例

  1. Redux的createStore只接受一个reducer,却可以把多个reducer结合起来
  2. render函数对ref的用法
    (1)当一个包含ref属性的组件完成装载过程时,会检测ref是不是一个函数,如果是,就会调用render,参数为这个组件代表的DOM元素render={this.refInput},通过这种方法,我们的代码可以访问到实际的DOM元素
    (2)组件完成mount后,可以直接通过this.input访问input元素,即为一个DOM元素,可以使用DOM API 访问元素内容
    (3)表格提交时,可以通过ev.preventDefault()取消浏览器默认网页跳转行为
    (4)ref实际触及了DOM元素,不推荐使用
    解决方案
    利用组件状态来同步记录DOM元素的值,这种方法可以控制住组件不使用ref
  3. 动态数量组件:使用数组的map属性,子组件需要添加key属性。JSX中可以使用任何形式的js表达式,只要js表达式在符号{}之间,for或者while产生的是”表达式”。JSX最终会被babel转移成一个嵌套的函数调用

第七章 Redux和服务器通信

1.React组件访问服务器

  1. Provider提供包含store的context

Javascript教程笔记

Posted on 2018-06-30 | In 前端

一.快速入门

  1. 代码使用方法:(1)放在< head>中,在< script>…< script>包含的代码即为
    JavaScript代码
    (2)把JavaScript放在单独的.js文件,然后再HTML中引入文
    件
  2. 如何运行JavaScript?以file://开头的地址无法执行如联网等JavaScript代码
    你还是需要架设一个Web服务器,然后以http://开头的地址来正常
    
    执行所有JavaScript代码
  3. 如何调试JavaScript?。。。Chrome用不了啊。。。。悲伤
  4. 注释:以//开头直到行末的字符被视为行注释,或者/…/
  5. 大小写:区分大小写
  6. 数据结构:(1)Number:
    (2)布尔值
     (3)字符串:多行字符串(`   `使用反引号)
                  连接字符串(用${ },也可以用+)
                 字符串不可变
                 返回不用的字符串,实际上并不改变原来的字符串:toUpperCase,toLowerCase,indexOf,substring
    
  7. 运算:(1)比较运算:==比较,它会自动转换数据类型再比较,很多时候,
    会得到非常诡异的结果;===比较,它不会自动转换数据类型,
    如果数据类型不一致,返回false,如果一致,再比较
    注意:NaN与任何数值都不相同,包括自己,只能使用isNaN()
         比较浮点数:注意计算机会产生小数点
          null表示一个空的值,而undefined表示值未定义
    
  8. 数组:(1)[]或者Array,
    (2)Array如果通过索引赋值时,索引超过了范围,同样会引起Array
    大小的变化
    (3)相关函数:slice()截取Array的部分元素,返回一个新的Array
                  Unshift(),shift():如果要往Array的头部添加若干元素,
    
    使用unshift()方法,shift()方法则把
    Array的第一个元素删掉
  9. 对象:键-值组成的无序集合(动态类型)
    object.prop或者xiaohong['middle-school'](单引号)
    添加或者删除:xiaoming.age; // undefined
    
    xiaoming.age = 18; // 新增一个age属性
    xiaoming.age; // 18
    delete xiaoming.age;//删除属性
    判断属性是否存在:in(要判断一个属性是否是xiaoming自身拥有的,
    
    而不是继承得到的,可以用hasOwnProperty()方法)
    for (var key in o) {
    if (o.hasOwnProperty(key)) {
    alert(key); // ‘name’, ‘age’, ‘city’
    }
    }
  10. 变量:动态变量:var(一个变量名称只能用var声明一次,用var声明后,可
    以不用var再定义一个名称相同的变量,前后的数据类型
    可以不痛)
    静态变量:int等定义,前后数据类型必须相同

  11. strict模式:强制性用var定义,不用var定义就会是全局变量,会在同一个页
    面的不同的JavaScript文件中出错,未使用var申明变量就使用
    的,将导致运行错误
    ‘use strict’;

  12. Map和Set:(1)Map:Map是一组键值对的结构
    (2)Set和Map类似,也是一组key的集合,但不存储value
    
  13. Array、Map和Set都属于iterable类型。
    为什么要使用for……of?和for…..in有什么区别?
    for … of循环则完全修复了这些问题,它只循环集合本身的元素

    1
    2
    3
    4
    5
    6
    7
    var a = ['A', 'B', 'C'];
    a.name = 'Hello';for (var x in a) {
    a.name = 'Hello';for (var x of a) {
    alert(x); // '0', '1', '2', 'name'
    alert(x); // 'A', 'B', 'C'
    }
    }
  14. iterable类型,在Array,Set,Map等都可以使用函数forEach

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    var a = ['A', 'B', 'C'];
    a.forEach(function (element, index, array) {
    // element: 指向当前元素的值
    // index: 指向当前索引
    // array: 指向Array对象本身
    alert(element);
    });
    var s = new Set(['A', 'B', 'C']);
    s.forEach(function (element, sameElement, set) {
    alert(element);
    });
    var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]);
    m.forEach(function (value, key, map) {
    alert(value);
    });

二.函数

  1. arguments:它只在函数内部起作用,并且永远指向当前函数的调用者传入的所有参数,(常用于判断参数的个数)
  2. rest参数:arguments中多余的参数,无则为“空数组”
  3. 如果内部函数和外部函数的变量名重名怎么办?
    JavaScript的函数在查找变量时从自身函数定义开始,从
    “内”向“外”查找
  4. 引擎自动提升了变量y的声明,但不会提升变量y的赋值
  5. 全局作用域:变量:默认有一个全局对象window,全局作用域的
    (只有一个) 变量实际上被绑定到window的一个属性
    函数:foo(); // 直接调用foo()
    
    window.foo(); // 通过window.foo()调用
    windows.foo都可以当成是全局变量
  6. 名字空间:不同的JavaScript文件如果使用了相同的全局变量,
    或者定义了相同名字的顶层函数,都会造成命名冲
    突,并且很难被发现。
    减少冲突的一个方法是把自己的所有变量和函数全部绑定到一个全局变量中。例如:
    // 唯一的全局变量MYAPP:
    var MYAPP = {};
  7. 局部作用域:用let替代var可以申明一个块级作用域的变量
    let i=0
    
  8. 常量:关键字const来定义常量,const与let都具有块级作用域
  9. 对象中定义函数(方法):
    1
    2
    3
    4
    5
    6
    7
    8
       var xiaoming = {
    name: '小明',
    birth: 1990,
    age: function () {
    var y = new Date().getFullYear();
    return y - this.birth;
    }
    };

调用方法:(错误)因为有this,不能在外部调用
修改方法:(1)var that = this;

1
2
3
4
5
6
7
8
9
10
11
var xiaoming = {
name: '小明',
birth: 1990,
age: function () {
var that = this; // 在方法内部一开始就捕获this
function getAgeFromBirth() {
var y = new Date().getFullYear();
return y - that.birth; // 用that而不是this
}
return getAgeFromBirth();
}};

(2)用apply修复getAge()调用
getAge.apply(xiaoming, []):第一个参数就是需要
绑定的this变量,第二个参数是
Array,表示函数本身的参数。
(3)call()函数
call()把参数按顺序传入
E.g Math.max.call(null, 3, 5, 4);

  1. 高阶函数:
    (1) map:map()传入的参数是pow,即函数对象本身
    arr.map(pow);
    arr.map(function(str){
    
    return str[0].toUpperCase()+str.slice(1).toLowerCase();
    })
    (2)reduce:sum=arr.reduce(function (x,y){
          return x*y;});
    //运算
    
    (3)filter:arr.filter(function (element, index, self) {
    index=第一个元素所在的位置,所以便于滤掉重复的元素
    区别:返回值为True或者False
    (4)sort()方法也是一个高阶函数,它还可以接收一个比较函数来实现自定义的排序。
  2. 闭包:
    为什么使用闭包?可以定义一个函数,返回值为函数内定义的(内部)
    函数,调用这个函数的时候,内部函数不会立即执
    行,需要var f = lazy_sum([1, 2, 3, 4, 5]);
    f();
    但是因为每次调用互不干涉,返回多个参数时出错
    1
    2
    3
    4
    var results = count();
    var f1 = results[0];//16
    var f2 = results[1];//16
    var f3 = results[2];//16

使用闭包的格式:在内部函数中定义:定义后会立即执行
对:(function (x) {
return x x;
})(3);
错:function (x) { return x
x } (3);
使用闭包的好处:(1)闭包就是携带状态的函数
(2)闭包还可以把多参数的函数变成单参数的函数。例如,要计算x^y可以用Math.pow(x, y)函数,不过考虑到经常计算x2或x3,我们可以利用闭包创建新的函数pow2和pow3:

1
2
3
4
5
6
7
8
function make_pow(n) {
return function (x) {
return Math.pow(x, n);
}
}
// 创建两个新函数:var pow2 = make_pow(2);var pow3 = make_pow(3);
pow2(5); // 25
pow3(7); // 34

经典例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
'use strict'; 
// 定义数字0:
var zero = function (f) {
return function (x) { return x;
}
};
// 定义加法:
function add(n, m) {
return function (f) {
return function (x) {
return m(f)(n(f)(x));
}
}
}
// 计算数字2 = 1 + 1:
var two = add(one, one);

  1. 箭头函数:相当于简化函数

    1
    fn = () => new Date().getFullYear() - this.birth; // this指向obj对象

    修改前面函数中this的问题

  2. generator:返回多个参数
    格式:function* 和yield返回
    调用格式:for……of或者
    f.next()不断调用(每次遇到yield x;就返回一个对象{value: x, done: true/false},然后“暂停”。返回的value就是yield的返回值,done表示这个generator是否已经执行结束了。如果done为true,则value就是return的返回值。)
    定义的函数:比如定义自加的函数,函数内就直接自己加,加到头

三.标准对象

  1. 不要使用new Number()、new Boolean()、new String()创建包装对象
  2. 通常不必把任意类型转换为boolean再判断,因为可以直接写if (myVar) {…}
  3. 函数内部判断某个变量是否存在用typeof myVar === ‘undefined’
  4. Date
    (1)月份范围用整数表示是0~11,0表示一月,1表示二月
    (2)创建一个指定日期和时间的Date对象
    1
    var d = new Date(2015, 5, 19, 20, 15, 30, 123);

第二种创建方法是解析一个符合ISO 8601格式的字符串

1
2
3
4
var d = Date.parse('2015-06-24T19:49:22.875+08:00');
d; // 1435146562875 -------时间戳
var d = new Date(1435146562875);
d; // Wed Jun 24 2015 19:49:22 GMT+0800 (CST)

  1. RegExp(正则表达式)】
    /…./或者new RegExp(‘正则表达式’)
    (1)正则表达式写法:\s 空格
    \w   字母或者数字
    \d   字母
     .    任意字符
    转义(\)   特殊符号
    个数:*为任意个数
          +一个
          {n,m}n-m个字符
          {n}n个字符
    
    (2) 正则进阶:使用[]
    [0-9a-zA-Z_]匹配一个数字、字母或者下划线;
    [0-9a-zA-Z\_]+可以匹配至少由一个数字、字母或者下划线组成的字符串,比如'a100','0_Z','js2015'等等;
    *,{0,19}。。。。。。
    A|B可以匹配A或B
    ^表示行的开头,^\d表示必须以数字开头。
    
    $表示行的结束,\d$表示必须以数字结束
    (3)test()方法用于测试给定的字符串是否符合条件
    (4)用()分组,提取子串的功能
    1
    2
    3
    var re = /^(\d{3})-(\d{3,8})$/;
    re.exec('010-12345'); // ['010-12345', '010', '12345']
    re.exec('010 12345'); // nul

exec()方法在匹配成功后,会返回一个Array,第一个元素是正则表达式匹配到的整个字符串,后面的字符串表示匹配成功的子串。

1
2
var re = /^(\d+?)(0*)$/;
re.exec('102300'); // ['102300', '1023', '00']

?用来表示:取消正则化的贪婪匹配
(5)全局匹配:/…../g 即可以多次执行exec()函数来多次匹配
(6)验证一个Email地址:
var re = /^[a-zA-Z0-9.]+@\w+.\w+$/;(进行分析)
[]内字符之间不需要用+或者其他符号表示不同
后面的+号表示至少匹配一个字符
@不是转义字符,直接用@就好,不用\@
\w+表示@后面的字符
.表示Email的.
\w+表示com、cn等字符
注意添加(),()用来分组,区分不同的字符串

  1. JSON
    (1)字符集必须是UTF-8
    (2)JSON的字符串规定必须用双引号””,Object的键也必须用双引号””
    (3)序列化:使用JSON.stringify(参数1,参数2,参数3)格式
    参数1:对象序列
    参数2:A.Array定义想要显示的键[‘’,‘’....]
             默认为null
           B.传入函数,将每个键值对都会被函数先处理
               (key,value)
    参数3: '  '按缩进输出
    
    另一种方法:精确控制序列化小明,可以给xiaoming定义一个toJSON()的方法,直接返回JSON应该序列化的数据(和属性格式一样)
    1
    2
    3
    4
    5
    6
    toJSON: function () {
    return { // 只输出name和age,并且改变了key:
    'Name': this.name,
    'Age': this.age
    };
    }

(4)反序列化:直接用JSON.parse()把它变成一个JavaScript对象

四.面向对象编程

  1. 不区分类和实例:所有对象都是实例,所谓继承关系不过是把一个对象的原型指向另一个对象而已
  2. 创建对象:(1)xiaoming.proto = Student;
    (Student为var定义)通过原型定义
     (2)方式二:
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     // 原型对象:var Student = {
    name: 'Robot',
    height: 1.2,
    run: function () {
    console.log(this.name + ' is running...');
    }
    };
    function createStudent(name) {
    // 基于Student原型创建一个新对象:
    var s = Object.create(Student); //用create()方法传入一个原型对象
    // 初始化新对象:
    s.name = name;
    return s;
    }
    var xiaoming = createStudent('小明');
    xiaoming.run(); // 小明 is running...
    xiaoming.__proto__ === Student; // true

new Student创建方法从原型上获取了一个constructor属性,指向Student函数本身

1
2
3
4
5
6
7
8
9
10
11
12
xiaoming ↘
xiaohong -→ Student.prototype ----> Object.prototype ----> null
xiaojun ↗
function Student(name) { //构造函数
this.name = name;
this.hello = function () {
alert('Hello, ' + this.name + '!'); //不需要return
}
}
var xiaoming = new Student('小明'); //使用关键字new
xiaoming.name; // '小明'
xiaoming.hello(); // Hello, 小明!

(4)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function Student(props) {
this.name = props.name || '匿名'; // 默认值为'匿名'
this.grade = props.grade || 1; // 默认值为1
}
Student.prototype.hello = function () {//将hello函数调出
alert('Hello, ' + this.name + '!');
};
function createStudent(props) { //防止忘记写new
return new Student(props || {})
}
var xiaoming = createStudent({
name: '小明'
});
xiaoming.grade; // 1

avatar

  1. 原型继承

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    function inherits(Child,Parent)
    {
    var F=function(){};
    F.prototype=Parent.prototype;
    Child.prototype=new F();
    Child.prototype.constructor=Child;
    }
    function Student(props){//初级定义的对象
    this.name=props.name||’Unnamed’;
    }
    Student.prototype.hello=function(){
    alert(‘Hello,’+this.name+’!’);
    }
    function PrimaryStudent(props){//下一级的定义的对象
    Student.call(this,props);
    this.grade=props.grade||1;
    }
    //实现原型继承链
    Inherits(PrimaryStudent,Student);

    //绑定其他方面到PrimaryStudent原型
    PrimaryStudent.prototype.getGrade=function(){
    return this.grade;
    }
  2. Class继承
    需要一个工具把class代码转换为传统的prototype代码,可以试试Babel这个工具。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    class Student {
    constructor(name) {
    this.name = name;
    }
    hello() {
    alert('Hello, ' + this.name + '!');
    }
    }
    var xiaoming = new Student('小明');
    xiaoming.hello();
    class PrimaryStudent extends Student { //已经继承了hello方法
    constructor(name, grade) {
    super(name); // 记得用super调用父类(Student的props)的构造方法!否则父类的name属性无法正常初始化
    this.grade = grade;
    }
    myGrade() {
    alert('I am at grade ' + this.grade);
    }
    }

五.浏览器

  1. window对象有innerWidth和innerHeight属性,可以获取浏览器窗口的内部宽度和高度 (outerWidth和outerHeight)
  2. document对象表示当前页面。由于HTML在浏览器中以DOM形式表示为树形结构,document对象就是整个DOM树的根节点。
    document的title属性是从HTML文档中的< title>xxx</ title>读取的,但是可以动态改变:
  3. DOM属性:(1)通过两种函数找到DOM节点
    menu = document.getElementById(‘drink-menu’);
    drinks = document.getElementsByTagName(‘dt’);
    (2)document对象还有一个cookie属性
    应该始终坚持使用httpOnly(安全问题)
  4. 操作DOM
    寻找DOM节点:getElementById返回节点唯一
    document.getElementsByTagName()和document.getElementsByClassName()总是返回一组DOM节点
    
    (1)更新DOM
    innerHTML:节点文本内容
    CSS格式:p.style.color = ‘#ff0000’;
    p.style.fontSize = ‘20px’;
    (2)删除DOM
    找到父节点—-调用父节点的removeChild
    删除后则实时更新children属性
    注意删除多个节点时
  5. 操作表单
    (1)文本框,对应的< input type=”text”>,用于输入文本;
    口令框,对应的< input type=”password”>,用于输入口令;
    单选框,对应的< input type=”radio”>,用于选择一项;
    复选框,对应的< input type=”checkbox”>,用于选择多项;
    下拉框,对应的< select>,用于选择一项;
    隐藏文本,对应的< input type=”hidden”>,用户不可见,但表单提交时会把隐藏文本发送到服务器。
    (2)获取值:input.value #输入框
    Input.checked #单选框和复选框,false和true
    (3)提交表单:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <!-- HTML --><form id="login-form" method="post" onsubmit="return checkForm()">
    <input type="text" id="username" name="username">
    <input type="password" id="input-password"> //不定义name属性,表示数据不会被提交
    <input type="hidden" id="md5-password" name="password">//转化为MD5类型
    <button type="submit">Submit</button></form>
    <script>function checkForm() {//定义checkForm()函数
    var input_pwd = document.getElementById('input-password');
    var md5_pwd = document.getElementById('md5-password');
    // 把用户输入的明文变为MD5:
    md5_pwd.value = toMD5(input_pwd.value);
    // 继续下一步:
    return true;
    }</script>

(4)提交文件:
< input type=”file”> 选择本地文件
当一个表单包含< input type=”file”>时,表单的enctype必须指定为multipart/form-data,method必须指定为post,浏览器才能正确编码并以multipart/form-data格式发送表单的数据。

typescript官网

Posted on 2018-06-30 | In 服务器

ts的配置文件tsconfig.json,包含输入文件列表和编译选项
教程地址

Introduction

TypeScript具有类型系统,且是JavaScript的超集。 它可以编译成普通的JavaScript代码。 TypeScript支持任意浏览器,任意环境,任意系统并且是开源的。

快速上手

了解typescript

  1. 编译代码
    1
    2
    3
    4
    5
    6
    //greeter.ts
    function greeter(person) {
    return "Hello," + person
    }
    let user = "Jane User"
    document.body.innerHTML = greeter(user)

编辑器运行

1
tsc greeter.ts

  1. 类型注解
    typescript提供静态的代码分析,分析代码结构和提供的类型注解,e.g:person:string
    代码错误仍可以执行
  2. 接口 interface

    1
    2
    3
    4
    5
    interface Person {
    firstName: string;
    lastName: string;
    }
    // person:Person
  3. 类:支持基于类的面向对象编程,可定义一个构造函数和一些公共字段

构造函数的参数上使用public等同于创建了同名的成员变量
类和接口可以一起共同作用

  1. 运行Typescript应用
    1
    2
    //greeter.html
    <script src="greeter.js"></script>

ASP.NET Core

Augular 应用

ASP.NET 4

Gulp

Gulp工程,Typescript文件放在src文件夹下,经ts编译生成的目标文件放在dist目录下

  1. 初始化工程
    init```
    1
    2
    3
    4
    5
    6
    7
    8
    入口文件为/dist/main.js
    2. 安装依赖: typescript gulp gulp-typescript
    gulp-typescript为一个插件,能够访问Typescript编译器
    3. src下创建main.ts
    4. 根目录下新建tsconfig.json:添加compilerOptions
    5. 创建gulpfile.js
    6. 测试
    更改代码后

gulp

1
![avatar]("../picture/gulp1.png")

node dist/main.js

1
2
3
4
5
6
返回运行结果

### 向代码里添加模块
导入模块:构建代码后再添加一些混入的模块
1. 在tsconfig.json中file添加模块src/greet.ts
2. 导入模块

import { sayHello } from “./greet”;

1
2
3
4
5

### Browserify:把所有的模块捆绑成一个Javascript文件
~支持Node.js的CommonJS模块~
1. 安装Browserify,tsify和vinyl-source-stream
tsify为Browserify的一个插件,访问Typescript编译器;vinyl-source-stream将Browserify的输出文件适配成gulp能够解析的格式

//gulpfile.js
gulp.task(“default”, [“copy-html”], function () { //默认先调用copy-html,作为default的依赖项
return browserify({
basedir: ‘.’,
debug: true,
entries: [‘src/main.ts’],
cache: {},
packageCache: {}
})
.plugin(tsify) //使用tsify插件调用Browserify
.bundle()
.pipe(source(‘bundle.js’)) //source为vinyl-source-stream别名,输出文件为bundle.js
.pipe(gulp.dest(“dist”)); //文件生成在dist文件夹中
});

1
2
3
4
5
6
7
8
9
10
11
2. 调试 gulp

### Watchify,Babel,Uglify
Watchify:;Babel:;Uglify:;
1. Watchify:启动Gulp并保持运行状态,自动编译
执行gulp
2. Babel为编译器,将ES2015及以上的版本转换为ES5和ES3
类似于Uglify,Babelify也会混淆代码,所以需要vinyl-buffer和gulp-sourcemap,需要将.ts添加到Babelify选项
更改tsconfig.json中compilerOptions-target为ES2015,compilerOptions-target定义的为Typescript生成的格式,Babel会将Typescript生成的ES2015编译为es5
3. Uglify压缩代码
Uglify用以混淆代码,安装vinyl-buffer和gulp-sourcemaps来支持sourcemaps

gulp.task(“default”, [“copy-html”], function () {
return browserify({
basedir: ‘.’,
debug: true,
entries: [‘src/main.ts’],
cache: {},
packageCache: {}
})
.plugin(tsify)
.bundle()
.pipe(source(‘bundle.js’))
.pipe(buffer()) //调用自身buffer
.pipe(sourcemaps.init({loadMaps: true}))
.pipe(uglify())
.pipe(sourcemaps.write(‘./‘))
.pipe(gulp.dest(“dist”));
});

1
2
3
```
gulp //检查bundle.js是否被压缩
cat dist/bundle.js ////# sourceMappingURL=bundle.js.map

React和webpack

初始化项目

ts文件放在src文件夹下,通过ts编译器变异,经webpack处理,生成bundle.js文件放在dist目录

安装依赖 安装typescript为一个开发依赖

webpack将所有代码和可选择地将依赖捆绑为一个单独的.js文件

react
react-dom
@types/react
@types/react-dom
后两个为前两个的声明文件,并非所有的包都包含了声明文件,所以ts会检查
awesome-typescript-loader
source-map-loader
第一个让webpack使用(ts的标准配置文件)tsconfig.json编译ts代码
第二个使用ts输出的sourcemap文件来告诉webpack什么时候生成自己的sourcemaps

添加代码

import组件使用相对路径,否则ts只会在node_modules中寻找

添加webpack配置文件

创建webpack.config.js

React

create-react-app

create-react-app my-app –scripts-version=react-scripts-ts

创建使用typescript开发的reactjs工程

Posted on 2018-06-30 | In 前端

使用create-react-app安装:react-script-ts是一系列适配器

1
create-react-app project_name --scripts-version=react-scripts-ts

github地址
官网地址
github参考资料

webpack简单教程

Posted on 2018-06-30 | In webpack

当前webpack 的最新稳定版本为 3.10.0。

Hello World!

当前项目是一个空文件夹,在项目根目录的命令行中执行:yarn add -D webpack,将会生成与 webpack 相关的必要文件。

  1. 在项目根目录下新建 src 文件夹用于存放源文件。
  2. 新建 src/index.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    //src/index.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    </head>
    <body>
    <script src="bundle.js"></script>
    </body>
    </html>
  3. 新建 src/index.js

    1
    2
    // src/index.js
    console.log("Hello World!");
  4. 新建 webpack.config.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // webpack.config.js

    const path = require('path');

    module.exports = {
    entry: './src/index.js',
    output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'src')
    }
    };
  5. 项目根目录命令行下执行:webpack,在 src 文件夹下生成 bundle.js 文件,用浏览器打开 src/index.html,可以在浏览器的命令行中看到 Hello World! 输出。

将编译结果移动至 dist 文件夹

  1. 删除之前编译生成的 src/bundle.js。
  2. 项目根目录命令行下执行:

    1
    2
    yarn add -D clean-webpack-plugin
    yarn add -D html-webpack-plugin
  3. 修改 webpack.config.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    // webpack.config.js

    const path = require('path');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    const CleanWebpackPlugin = require('clean-webpack-plugin');

    module.exports = {
    entry: './src/index.js',
    output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
    },
    plugins: [
    new CleanWebpackPlugin(['dist']),
    new HtmlWebpackPlugin({
    filename: 'index.html',
    template: 'src/index.html'
    })
    ]
    };
  4. 删除 src/index.html 中

    src
    1
    2
    3
    4
    5
    6
    7

    # webpack-dev-server
    1. 在项目根目录的命令行中执行:```yarn add -D webpack-dev-server```。
    2. 在项目根目录的命令行中执行:```node_modules/.bin/webpack-dev-server```,可以进入 webpack 的开发者模式。

    # npm 脚本
    在 package.json 中添加:

{
…
“scripts”: {
“build”: “webpack”,
“start”: “node_modules/.bin/webpack-dev-server”
}
…
}

1
2
3
4
5
在项目根目录的命令行中可以使用 yarn build 代替 webpack 进行编译;可以使用 yarn start 代替 node_modules/.bin/webpack-dev-server 进入开发者模式。

# 用 typescript 代替 javascript 进行开发
1. 在项目根目录的命令行中执行:```yarn add -D typescript ts-loader ```安装必要的包。
2. 在项目根目录下新建 tsconfig.json

// tsconfig.json

{
“compilerOptions”: {
“outDir”: “./dist/“,
“noImplicitAny”: true,
“module”: “es6”,
“target”: “es5”,
“jsx”: “react”,
“allowJs”: true
}
}

1
2
3. 将 src/index.js 修改成 src/index.ts。
4. 修改 webpack.config.js

// webpack.config.js

const path = require(‘path’);
const HtmlWebpackPlugin = require(‘html-webpack-plugin’);
const CleanWebpackPlugin = require(‘clean-webpack-plugin’);

module.exports = {
entry: ‘./src/index.ts’,
output: {
filename: ‘bundle.js’,
path: path.resolve(__dirname, ‘dist’)
},
plugins: [
new CleanWebpackPlugin([‘dist’]),
new HtmlWebpackPlugin({
filename: ‘index.html’,
template: ‘src/index.html’
})
],
module: {
rules: [
{
test: /.tsx?$/,
use: ‘ts-loader’,
exclude: /node_modules/
}
]
}
};

`

mongodb

Posted on 2018-06-30 | In 数据库

启动mongodb数据库

brew services start mongodb
mongod –config /usr/local/etc/mongod.conf

1…456…9

Root

87 posts
20 categories
23 tags
© 2018 Root
Powered by Hexo
|
Theme — NexT.Mist v5.1.4
本站总访问量 次 | 有人看过我的博客啦