Giter VIP home page Giter VIP logo

m's Introduction


乌拉拉,一枚小前端。


大街上,有个小男孩吵着要买棉花糖。

妈妈指着他手里的小糖人,说:“刚买的孙悟空还没吃呢,怎么还要?”

小男孩不听,赖在原地,非要买棉花糖不可。

妈妈没办法,只好同意了。

小男孩终于拿到了棉花糖,开心地对小糖人说:“大圣你看,你的筋斗云来了!”

m's People

Contributors

wulala avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

m's Issues

数据结构与算法之数组

Array.length

返回或设置(截断、扩展,扩展后自动获得undefined值)数组的元素个数。但是并不一定表示定义项目个数

var letter = ['a', 'b', 'c']
letter[25] = 'z'
console.log( Object.keys(letter) ) // ['a', 'b', 'c', 'z']
console.log( letter.length ) // 26

创建数组

  • var arr = [] // javascript: the goods parts 推荐用法

  • var arr = new Array() // 没有参数,创建实例 ,,, [], length = 0

  • var arr = new Array(5) // 一个参数,指定数组的长度 ,,, [undefined × 5], length = 5

  • var arr = new Array(5,4) // 多个参数,作为数组的初始值 ,,, [5,4], length = 2

  • var arr = Array.of(5) // 一个参数,创建单项值的数组 ,,, [5], length = 1

  • var arr = Array.of(5,4) // 多个参数,创建多项值的数组 ,,, [5,4], length = 2

  • var arr = RegExp.exec(str)

  • var arr = String.match(regexp)

  • var arr = String.split

  • var arr = Object.keys(obj)

判断数组

arr instanceof Array

instanceof运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性

创建一个(构造)函数自动获得一个prototype属性,此属性指向函数的原型对象

// 原型对象自动获得一个 constructor 属性,此属性指向 prototype 属性所在函数的指针

当调用构造函数创建一个实例后,此实例内部将包含一个指针 proto,指向构造函数的原型对象,此连接存在于 实例与构造函数的原型对象 之间,而非实例与构造函数

Array.prototype.isPrototypeOf(arr)

isPrototypeOf() 方法用于测试一个对象是否存在于另一个对象的原型链上

Object.prototype.toString.call(arr) == "[object Array]"

没啥好说的,Object.toSring() 就是返回 [object type] (type 为对象类型), 自定义的构造函数返回 [object Object]

arr.constructor == Array

constructor 用来检测对象的类型,(系统级引用类型、自定义的构造函数)

对象是引用类型的一个实例,引用类型是一种数据结构,用来将数据和功能组织在一起,通常也成为 类 / 对象定义(描述的是一类对象所具有的属性和方法)

Array.isArray(arr)

撸js基础之数组

字体子集化

中文字体因为字符编码以及汉字个数的原因造成制作后的字体文件偏大,不适合网页引入使用。这时候字体子集化应运而生。

名词听着挺高端的。其实就是通过工具把页面上用到的中英文字从大文件字体中抽取出来,变成只包含用到文字的一个小字体文件,方便网页上调用。

目前市面上我所知道的工具来自BAT :

字蛛是一个中文字体压缩器 - 让网页自由引入中文字体成为可能。这货只针对静态页面的字体提取工具

Fontmin - 第一个纯 JavaScript 字体子集化方案。这货文档不行

font-carrier - 我们不生产字体,我们只是字体的搬运工。 这货我没用过,貌似更多的是为Iconfont-阿里巴巴矢量图标库服务。

有因必有果, 因为我用fonmin,所以我只能说说这货的使用。

fontmin可以全局执行,在这之前通过 npm i fontmin -g 全局安装。

fontmin -t [文本] [字体路径] [生成路径] 最简单的用法。

通过Node 执行:

var Fontmin = require('fontmin');
var argv = require('yargs').argv // 获取控制台cli输入的参数
var rename = require('gulp-rename'); // 重命名
var fs = require("fs");

var fontmin = new Fontmin()
  .use(Fontmin.glyph({ 
    text: argv['txt'],
    hinting: false
  }))
  .use(Fontmin.css({
    fontFamily: argv['fontname'],
    glyph: false,
    base64: true,
  }))
  .src('./fonts/'+ argv['fontname'] +'.ttf')
  .use(rename('small.ttf'))
  .dest(argv['destname'])
 
fontmin.run(function(err){
  if (err) throw err
})

node font.js --txt=我是必须要被压缩的文本 --fontname=yahei --destname=dist/

更多用法请访问官方API文档

flex使用指南

  ul.parent
    li.items*3

容器

开始使用flex,先让父元素变成一个 flex 容器

.parent { display: inline-flex; } or .parent { display: flex }

此时, .parent 自动变成 flex 容器了, 而对应的子元素 li 则成了 flex items (flex项目)

排列

flex-direction 告诉flex 容器,flex items 要如何排列,可以是 row (行/水平, 默认值),row-reverse (反向行),column (列/垂直),column-reverse(反向列)

换行

flex-wrap 告诉flex 容器,flex items是否可以换行。 nowrap(不换行, 默认值),wrap(自动换行),wrap-reverse(反转 flex items)

flex-flow 是 flex-direction + flex-wrap 的 缩写形式: flex-flow: flex-direction flex-wrap

水平对齐

justify-content 告诉flex 容器,flex items 水平方向如何对齐, 可以是flex-start(左对齐,默认值), flex-end(右对齐), center(居中),space-between(两端对齐), space-around(每份items相同空间)

垂直对齐

align-items 告诉flex 容器,flex items 垂直方向如何对齐, stretch(每份items跟flex容器同高度),flex-start(顶部对齐), flex-end(底部对齐), center(居中),baseline (基线对齐)

多列垂直对齐

align-content 告诉flex 容器,多列flex items 垂直方向如何对齐, stretch(每份items跟flex容器同高度),flex-start(顶部对齐), flex-end(底部对齐), center(居中),baseline (基线对齐)

项目

项目排序

order 默认是按html结构顺序来默认设置

剩余空间分配

flex-grow和flex-shrink, 接受一个 >= 0 的值

指定items初始大小

flex-basis 默认auto, 可取值css单位, 需要注意的是即使是 0 也要带单位

flex是flex-grow、flex-shrink和flex-basis三个属性的简写。

单个项目垂直对齐

align-self ,flex items在垂直方向如何排列, auto(自动),stretch(每份items跟flex容器同高度),flex-start(顶部对齐), flex-end(底部对齐), center(居中),baseline (基线对齐)

参考资料:

https://css-tricks.com/snippets/css/a-guide-to-flexbox/
https://www.w3cplus.com/css3/understanding-flexbox-everything-you-need-to-know.html

SASS编译支持中文

Syntax error: Invalid GBK character "\xE5" ...

在ruby安装目录下查找 engine.rb 文件,

在所有的 require 'xxx' 之后添加:Encoding.default_external = Encoding.find('utf-8')

CentOS相关

~ 目录为用户目录,相当于 在 根目录 / 下执行 cd root( root为用户名,会自动在根目录下创建用户名目录? )

CTRL + U 撤销全部输入

CTRL + W 删除最后一个由空格分隔的字符串

yum search softwarePackageName 查看源上的软件包

VI 操作

使用 / 键来查找字符串

使用 I 键 执行插入(绿色光标位置插入)

Esc 键退出插入模式

输入 :wq 后回车退出编辑

react-native踩坑汇总

react-native

Android

IOS

  1. 安装Xcode, 并且打开它(主要是同意协议)

  2. 安装Homebrew,

    /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

  3. 安装Node,

    brew install node

  4. 更改npm源,

    npm config set registry https://registry.npm.taobao.org --global
    npm config set disturl https://npm.taobao.org/dist --global

  5. 安装yarn,

    npm i -g yarn

  6. 更改yarn源,

    yarn config set registry https://registry.npm.taobao.org --global
    yarn config set disturl https://npm.taobao.org/dist --global

  7. 安装Watchman,

    brew install watchman

  8. 安装CocoaPods,

    gem sources --add https://gems.ruby-china.org/ --remove https://rubygems.org/
    sudo gem install cocoapods

以上,都是必须的,可减少80%+的报错!

坑,坑,坑

  1. 下载文件
https://github.com/google/glog/archive/v0.3.4.tar.gz 
https://github.com/google/double-conversion/archive/v1.1.5.tar.gz
https://github.com/react-native-community/boost-for-react-native/releases/download/v1.63.0-0/boost_1_63_0.tar.gz
	http://www.boost.org/users/history/version_1_63_0.html
https://github.com/facebook/folly/archive/v2016.09.26.00.tar.gz
  1. 复制文件到 ~/.rncache
  2. 给这些文件加上 .gz 后缀(好像下完后缀没掉了)
  3. Xcode 内 command + shift + k
  4. react-native run-ios
  • fatal error: 'QBImagePickerController/QBImagePickerController.h' file not found

请严格按照此步骤来

打包应用

  1. 修改 ios/项目名/AppDelegate.m
 // jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];
jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"tw" withExtension:@"jsbundle"];
  1. 打包文件为资源

react-native bundle --entry-file index.ios.js --bundle-output ./ios/tw.jsbundle --platform ios --assets-dest ./ios --dev false

  1. 工程中添加资源

工程项目名目录上 -> 右键 -> Add Files to 'Myapp'... -> 添加上一步骤导出的 tw.jsbundle / tw.jsbundle.meta文件, 以及 assets 文件夹( 导入后为__蓝色__文件夹 )

haha

  1. 修改构建模式

Xcode Product -> Scheme -> Edit Scheme -> Run -> Build Configuration -> Release

  1. 打包证书(有独立小节)

  2. 打包

Xcode 选择小锤子, Product -> Archive, 等待即可。

ai7a20b3q_5re 8a hu

提交应用

  • ERROR ITMS-90161:"Invalid Provisioning Profile.The provisioning profile included in the bundle x.x.x.x[Payload/x.x.x.app] is invalid.[Missing code-signing certificate.] For more information,visit the iOS developer Portal."

xcode - windows - organizer - 选中archive包,右键show in finder,找到安装包文件,右键显示包内容,把Products目录下的Application文件夹改名为Payload,修改info.plist文件 ApplicationProperties - ApplicationPath,把 Application/xxx 改为 Payload/xxx 重新上传即可。

  • No suitable application records were found. Verify your bundle identifier 'xxx' is correct.

https://itunesconnect.apple.com/ ,在 我的App 里面先创建应用。

Zepto源码解读一

写不好开头,如同讲不好故事,那么阅读就会食不知味,味同嚼蜡。所以我在思考,思考怎么让你们读完引言就让你醍醐灌顶大彻大悟,从此超脱世俗,走向极乐。
可是可是我胸无点墨,这是一个哲学问题。再多也我扯不出来了。

本文基于 http://zeptojs.com/zepto.js v1.2.0 解读。

Zepto的 $() 如同狗皮膏药,啥东西往里面一放都能给你整出一点用法。我们最常用的莫过于通过它来选择、创建元素了。
$('.class'), $('p'), $('#id'), $('[type="text"]'), $('<div>new element</div>') 这么写个用法。

那么Zepto是如何通过传递进来的值来识别需求,让我们一起走进Zepto的内心世界,层层解剖,看一看Zepto的心到底是不是黑的。

毫无疑问,$() 是一个接受参数的函数定义,查看源码得知:

$ = function(selector, context){
  return zepto.init(selector, context)
}

就是返回另一个函数 zepto.init() 的执行结果。很明显咧,这根本看不出啥,只能接着看 zepto.init() 的定义:

zepto.init = function(selector, context) {
  if (!selector) return zepto.Z()
  return zepto.Z(dom, selector)
}

通过 $() 我们晓得这货需要一个执行结果,来看看这货返回了什么。代码被我精简了一下, 看到的又是返回另一个函数 zepto.Z() 的执行结果。我走过最长的路,就是你的套路,这调用都是一层又一层啊。只能接着往下看了:

zepto.Z = function(dom, selector) {
  return new Z(dom, selector)
}

...套路差不多要完了吧。还好,到这里我们终于知道了,这货返回了一个对象。既然都是套路,我们用套路的想法理解下, 构造函数 Z(), 应该会给对象提供一些初始的属性或方法,(构造函数之所以是一个构造函数,一般来说咧需要给对象实例提供一些成员属性和方法,才能成为一个构造函数,要不空的构造函数,直接继承 Object 好了), 查看下 Z() 的定义:

function Z(dom, selector) {
  var i, len = dom ? dom.length : 0
  for (i = 0; i < len; i++) this[i] = dom[i]
  this.length = len
  this.selector = selector || ''
}

很简单咯, 就是添加 this.length, this.selector, 一个节点对应一个成员属性(this[i] = dom[i]

一轮下来,我们知道了调用 $() 最终得到了一个对象,对象有 2 + n (有多少节点就有多少个n) 个属性。归根到底咧,$() 就是通过参数取得节点信息。现在跟随镜头让我们重新走入 zepto.init() 的内心,看看它是怎么撩到node节点的芳心。

zepto.init = function(selector, context) {
  var dom
  // 如果没传递参数,返回空对象
  if (!selector) return zepto.Z()

  // 如果是字符串
  else if (typeof selector == 'string') {
    selector = selector.trim() // 去掉字符串的首尾空白

    // ...
    if (selector[0] == '<' && fragmentRE.test(selector))
      // 可以发现这里调用了一个 处理片段的方法,让我们跳出这里,先去看看这个函数怎么处理html片段,
      //    - 可以先看下传递进去的都是啥参数值:
      //      1. 字符串片段,
      //      2. 标签名,
      //      3. 上下文环境
      // 看完了,知道这货就是返回一个被处理成数组形式的 NodeList 对象
      dom = zepto.fragment(selector, RegExp.$1, context), selector = null
    // 如果提供上下文,则先创建上下文的Zepto对象,然后从$(context).find(selector)
    else if (context !== undefined) return $(context).find(selector)
    // 如果是一个CSS选择器(1.字符串,2. 没有<开头),则执行 zepto.qsa() 方法(代码挺简单,就不挂尸了),获取node节点列表的数组形式
    else dom = zepto.qsa(document, selector)
  }
  
  // 如果是对象
  else if (isFunction(selector)) return $(document).ready(selector)
  
  // 如果本身就是 Zepto对象,直接返回 Zepto对象, 这好**啊,
  //      $( $('div') ) => $('div') => zepto.init() => 就是,如果有双层皮,先剥掉一层在循环一遍...
  else if (zepto.isZ(selector)) return selector

  // 如果既不是对象,又不是 Zepto对象,也不是函数
  else {
    // 友情提示: 通过 var getNodes = document.querySelectorAll('div'), var getNodes = document.querySelector('body') 获取的是NodeList对象,不是数组,
    //    ... 一些成熟的类库就是判断过多导致体积变大,
    //    ... 通过 querySelectorAll 获取的 NodeList 对象可以 通过 Array.prototype.slice.call(getNodes) 转成这里需要的数组形式
    if (isArray(selector)) dom = compact(selector)
    // 如果传进来的是 NodeList 对象的话
    else if (isObject(selector))
      dom = [selector], selector = null
    // 如果传进来的是html片段, 就是:
    //    <xxx> => 判断比较简单咯, 只要匹配到  < \w | ! > 就可以了
    // 那么就通过html字符串取得它的节点列表
    else if (fragmentRE.test(selector))
      dom = zepto.fragment(selector.trim(), RegExp.$1, context), selector = null
    else if (context !== undefined) return $(context).find(selector)
    else dom = zepto.qsa(document, selector)
  }
  // create a new Zepto collection from the nodes found... 英文更好理解
  return zepto.Z(dom, selector)
}

这里是处理html 片段时间。我累了,有空再补上一行一行的注释

// `$.zepto.fragment` takes a html string and an optional tag name
// to generate DOM nodes from the given html string.
// The generated DOM nodes are returned as an array.
// This function can be overridden in plugins for example to make
// it compatible with browsers that don't support the DOM fully.
// 
// 我特意留着英文注释给你们看, generate DOM nodes from the given html string.
// 
zepto.fragment = function(html, name, properties) {
  var dom, nodes, container

  // 如果是简单标签,=> <div></div>, <br />
  // 直接创建一个节点
  if (singleTagRE.test(html)) dom = $(document.createElement(RegExp.$1))

  if (!dom) {
    if (html.replace) html = html.replace(tagExpanderRE, "<$1></$2>")
    if (name === undefined) name = fragmentRE.test(html) && RegExp.$1
    if (!(name in containers)) name = '*'
    container = containers[name]
    container.innerHTML = '' + html
    dom = $.each(slice.call(container.childNodes), function(){
      container.removeChild(this)
    })
  }

  if (isPlainObject(properties)) {
    nodes = $(dom)
    $.each(properties, function(key, value) {
      if (methodAttributes.indexOf(key) > -1) nodes[key](value)
      else nodes.attr(key, value)
    })
  }

  return dom
}

按照国际惯例,来个未完待续...

常用正则

身份证号码

/^(\d{15}$|^\d{18}$|^\d{17}(\d|X|x))$/

手机号码

/^(\+?0{0,2}86([\ |\-])?)?1[3|4|5|7|8][0-9]{9}$/

固定电话

/^0[0-9]{2,3}[2-9][0-9]{6,7}$/

去掉html标签

/<[^>]+>/

CentOS7瞎折腾

安装FFmpeg 之前的准备工作

RHEL 7 or compatible like CentOS:

  • sudo yum localinstall --nogpgcheck https://download1.rpmfusion.org/free/el/rpmfusion-free-release-7.noarch.rpm https://download1.rpmfusion.org/nonfree/el/rpmfusion-nonfree-release-7.noarch.rpm

  • yum install ffmpeg

山海经

南山

䧿[que]山(系)

从招摇之山到箕尾之山共有10座山,长约两千九百五十里。山神皆鸟身龙首。
祭祀诸山的礼仪:带毛动物+璋+玉埋地里,米用精米,白菅(植物名)作为神的坐席


🚀 第一山 招摇之山

  • 多桂树、多金属、玉石、
  • 祝馀(yu) 🍋 状如韭菜,开青花,食之不饥
  • 迷榖(gu) 🍋 状如榖(构树)、黑纹理、光华四照,佩之不迷路
  • 狌狌(猩猩) 🍋 状如禺(yu,猿)、白耳朵、直立行走、食之善走
  • 育沛 (琥珀)🍋 丽[字:上鹿下旨, ji]水中,佩之无蛊胀(病)
  • 丽ji水从此山发源、向西入大海

🚀 往东三百里 堂庭之山

  • 多棪木(苹果)、多白猿、多水玉、多金矿

🚀 往东三百八十里 即翼之山

  • 多怪兽、多怪鱼、多白玉、多蝮虫(反鼻虫,毒蛇名)、多怪蛇、多怪木
  • 险峻不可攀

🚀 往东三百七十里 杻阳之山

  • 阳(南)多赤金、阴(北)多白金
  • 鹿蜀 🍋 状如马,白脑袋、身像虎纹、红尾巴、声如人在吟唱、佩毛皮子孙繁衍
  • 旋龟 🍋 状如龟,鸟头、毒蛇样尾巴、音像破开木头的声音,佩之耳朵不聋,治脚底老茧
  • 怪水从此山发源,向东流入宪翼山

🚀 往东三百里 柢[di]山

  • 多水、无草木
  • 鯥(怪鱼) 🍋 状如牛、住山坡、蛇尾、长在肋下的翅膀、音像牦牛、冬蛰伏夏苏醒、食之无肿疾

🚀 往东四百里 亶爰[chanyuan]之山

  • 多水、无草木
  • 险峻不可攀
  • 类(兽) 🍋 状如狸猫、头上有毛、 雌雄同体(牝牡,牝:鸟兽雌性,牡:鸟兽雄性)、食之不妒(嫉妒)

🚀 往东三百里 基山

  • 阳(南)多玉、阴(北)多怪木
  • 猼訑[boshi](兽) 🍋 状如羊、九尾四耳、目在背、佩之不畏(恐惧)
  • 𪁺𩿧[changfu](鸟)🍋 状如鸡、三首六目、六足三翼、食之无卧(精神亢奋睡不着)

🚀 往东三百里 青丘之山

  • 阳多玉、阴多青雘[huo]
  • ...(兽)🍋 状如狐、九尾、音如婴儿、能食人、食之不蛊(妖邪之气)
  • 灌灌(鸟) 🍋 状如雉鸠、音像人在斥骂、佩之不惑(迷惑)
  • 赤鱬[ru] 🍋 状如鱼、人面、音如鸳鸯、食之不疥(不生疥疮)
  • 英水从此山发源,向南注入即翼泽

🚀 往东三百五十里 箕尾之山

  • 尾部盘踞在东海之上、多沙石、多白玉
  • 汸[fang]水从此山发源、向南注入淯水

第二山系


🚀 第一山 柜山

  • 西临流黄国、北望诸[字: 上囟下比, pi]山,东望长右山
  • 英水从此山发源,像西南注入赤水,水中多白玉、多红色细沙

图片转BASE64

File接口 可以获取文件信息、读取文件内容。File对象来自用户在一个元素上选择文件后返回的FileList对象,也可以是来自由拖放操作生成的 DataTransfer对象.

File接口基于Blob,继承blob功能并将其扩展为支持用户系统上的文件。

通过 dragenter 事件监听来自系统文件(或者是一个拖拽元素,标签设置了 draggable="true" 属性)被拖拽到可放置的当前区域,一般通过此事件告知用户当前位置为可放置区域。同时需要阻止默认行为(拖拽文件到浏览器的默认行为是读取并显示文件)

同时通过 drop 事件来响应接收被拖拽的数据及被可放置区域捕获。拖放操作生成 DataTransfer 对象。

Referer: https://developer.mozilla.org/zh-CN/docs/DragDrop/Drag_and_Drop

获取到图片数据后,我们可以通过new FileReader.readAsDataURL()或者URL.createObjectURL()来读取图片。

URL对象或构建简单的字符串对象,用来指向用户的文件地址,主要用来显示图片。 FileReader.readAsDataURL() 异步 的将文件读取为包含一个 data: URL 格式的字符串(即BASE64)。这里特别强调的是 FileReader的读取是异步操作。

下面是简单的代码时间:

<div id="toBase64">文件拖放到这里</div>
<ul id="result"></ul>
let getZONE = document.querySelector('#toBase64')

// 当拖动的元素进入可以放置区域时,高亮放置区域,同时阻止默认行为
getZONE.addEventListener('dragover', (e) => {e.preventDefault(); getZONE.classList.add('on')})

// 当拖动的元素离开可以放置区域时,清除高亮
getZONE.addEventListener('dragleave', (e) => getZONE.classList.remove('on'))

// 在可放置区域触发放的动作
getZONE.addEventListener('drop', (e) => {
  e.preventDefault()
  // e.dataTransfer是被放置的元素数据
  for (var i = 0; i < e.dataTransfer.files.length; i++) {
    let file = e.dataTransfer.files[i]
    const fileReader = new FileReader()
    fileReader.readAsDataURL(file)
    fileReader.addEventListener('load', (e) => {
      let createLI = document.createElement('li')
      createLI.innerHTML =  `
        <div class="pic" style="background: url(${window.URL.createObjectURL(file)}) center / cover no-repeat;"></div>
        <div class="base64">
            <textarea name="" id="">${e.target.result}</textarea>
        </div>
      `

      // 因为 FileReader 是异步读取图片文件,所以需要在 load 事件内处理数据
      document.querySelector('#result').appendChild(createLI)
    })
  }
})

访问这里进行简单体验。

文末的参考资料 在浏览器端对图片进行压缩 & 上传 有个很严重的问题没说到, iPhone上(Android不清楚)通过 input:file 读取的图片存在一个图片角度的问题,这个需要额外处理。
解决方案可以参考: Accessing JPEG EXIF rotation data in JavaScript on the client side

另一个问题就是: 通过canvas.toDataURL()处理gif是不生效的(目前对我来说是这样的),只能保持一帧的数据。所以手动撸上传功能时需要注意的这两个坑。

当然了,代码里头想把图片转成BASE64的字符串根本不用这么麻烦呐, 在有emmet插件的情况下,在图片路径的地方执行 Ctrl + " 即可。

参考资料:

在web应用中使用文件
在浏览器端对图片进行压缩 & 上传

Nginx + Express + Forever on CentOS 7

安装Nginx

yum install epel-release

yum -y install nginx

service nginx start

关闭防火墙

systemctl stop firewalld.service   // 停止firewall
systemctl disable firewalld.service   // 禁止firewall开机启动

// 附送其他命令
systemctl status firewalld 
systemctl start firewalld.service  

安装Express

npm i -g express-generator experss

听说生成器跟主体分开了,谁知道呢,反正一起全局安装又没副作用。

express 需要依赖node服务来运行,所以确保 node 是全局环境下,而非通过软连接执行的

安装Foreverjs

npm i -g foreverjs

编辑nginx.conf

路径: /etc/nginx/nginx.conf

upstream myAPI {
    server 127.0.0.1:3000;
}

server {
    listen 80;
    location / {
        proxy_pass http://myAPI;
    }
}

运行

forever start -w ./bin/www

这里有个 -w 参数,使用它的前提是在项目下有 .foreverignore :

node_modules

否则,你将看到如下报错:

error: Could not read .foreverignore file.
Forever documentation about .foreverignore

-w : 实时监听文件变化,进而自动重新加载(restart), 类似本地开发调试时自动重载的 node-devsupervisor模块。

安装过程还碰到如下的问题:

error: Forever detected script exited with code: 0 // 我出现的问题好像是命令敲错了?
Node.js and Forever “exited with code: 0”

此时如果你访问服务器得到一个 502 Bad Gateway, 那么请执行 setsebool -P httpd_can_network_connect 1 (谁知道这是什么鬼呢)

(13: Permission denied) while connecting to upstream:[nginx]

详情待补充,西湖的水啊!

Zepto源码解读二

前天我听到一个笑话一定要讲给你们听:

从军十二年,不知木兰是女郎。 因为木兰无长胸(兄)。

是不是很好笑。

言归正传,上回说到当你敲下 $() 的时候,内部创建了一个构造函数的实例并提供了 n + 2 个属性 (n = dom节点)。写完突然发现接下来不知道要表达什么,黑人问号脸.jpg,那就换一个言归正传吧。

言归正传,上回我们知道了执行 $() 后实质上是去获取一系列的dom节点并作为对象的属性存在。接下来就是要调用Zepto提供的一系列方法了。这里我们以css()方法为例。先来看看内部是如何定义css()方法的(关于原型的部分我打算放番外篇说明,或者后续必要的时候再说。划线表示也有可能不会写。)

在说css()方法的具体实现之前,有必要先说一下each()方法。 在Zepto的世界中存在两个 each 方法,分别是 $.each() 实例方法, $().each() 原型方法。

EXO me? 哈哈。

让我们回到Zepto的开头,重新看下$.each的定义(同样的,代码被我精简了)

var $
$ = function(){}
$.each = function(){}

我们知道在javascript的世界中,一切皆对象。构造函数也就一普通函数,只有使用new关键字调用的时候才会成为一个构造函数。

函数实际上是功能完整的对象。而对象具有属性和方法是它最基本的特征之一。所以你可以把$ = function() {}看成$ = {},然后我们给对象添加each()方法。所以这里很明显 $.each 就是调用 $ 对象(函数)上定义的 each 方法而已, 更通俗的说就是 调用了一个挂载在 $ 命名空间上的方法而已
但是当你调用了$()时,这时候经过内部的一系列调用,就变成了调用构造函数了。

下面是 $.each 解读时间,来看下它是干嘛的。

我们知道 css() 的作用,css('left') 是获取 left 的值, css('left', 'auto') / css({'left', 'auto'}) 是设置 left 的值。很明显我们需要对传递进来的值进行判断才能达到上述的用法。

css: function(property, value){
  // 如果参数只有一个
  if (arguments.length < 2) {
    // this[0] = 获取到的第一个dom节点
      // 来,this就是谁调用它就指向它
    var element = this[0]
    if (typeof property == 'string') {
      // 为什么放这里判断是否存在element 表示不太懂,不是在最上层直接判断就好了么,如果都不存在dom,后续判断(包括判断参数)的意义?
      if (!element) return
      // 首先去 elem.style 查找是否设置此属性,
        // 我们晓得页面最终的表现方式是 important > style > # > . / [] > tagName
        // 这里好像跳过了important ?
      // 否则去获取通过样式表定义的/浏览器提供的默认值(包含继承来的值)
        // 我们又晓得通过elem.style只能获取到定义在标签属性style上设置到的值,否则返回...
        //getComputedStyle(elem, null) 获取样式的元素
        //getPropertyValue('left') 
          // https://developer.mozilla.org/zh-CN/docs/Web/API/Window/getComputedStyle
      return element.style[camelize(property)] || getComputedStyle(element, '').getPropertyValue(property)
    // 好恐怖,我竟然不知道可以传递数组...
    } else if (isArray(property)) {
      if (!element) return
      var props = {}
      var computedStyle = getComputedStyle(element, '')
      // 请注意 $.each 和 this.each 的区别
      $.each(property, function(_, prop){
        props[prop] = (element.style[camelize(prop)] || computedStyle.getPropertyValue(prop))
      })
      return props
    }
  }
  // 上面的if看出点什么问题么? 那就是 $('div').css('left') 它只会取得 匹配到的dom节点第一个的值,不是全部哦。 
  // 想获取全部的div的left值需要自己调用 each() 方法哦,下面接着说 each() 方法。

  var css = ''
  if (type(property) == 'string') {
    if (!value && value !== 0)
      this.each(function(){ this.style.removeProperty(dasherize(property)) })
    else
      css = dasherize(property) + ":" + maybeAddPx(property, value)
  } else {
    for (key in property)
      if (!property[key] && property[key] !== 0)
        this.each(function(){ this.style.removeProperty(dasherize(key)) })
      else
        css += dasherize(key) + ':' + maybeAddPx(key, property[key]) + ';'
  }

  return this.each(function(){ this.style.cssText += ';' + css })
}

3c77c63b18cafd0f1d0706f332b88574_r
这是黑人问号脸.jpg

本篇未完待续,下篇待续...

React Native使用小结

路由

React Native 通过 React Navigation 组件控制页面的切换。

React Navigation 有三个比较重要的东西(因为我只用了这三个东西啊,摔),StackNavigatorTabNavigatorscreenProps,其中

TabNavigator 类似底部栏,用来区分模块

TabNavigator(RouteConfigs, TabNavigatorConfig)

// 此组件为渲染底部栏图标
class TabItem extends Component {
    render() {
        return (
            <Image 
                source={ this.props.focused ? this.props.selectedIcon : this.props.defaultIcon } 
                style={ {tintColor: this.props.tintColor, width: 20, height: 20 } } 
            />
        )
    }
}

const TAB = TabNavigator(
    // RouteConfigs
    {
        Home: {
            screen: Home,
            navigationOptions: {  // 也可以写在组件的static navigationOptions = {} 内
                header: null,
                tabBarLabel: '首页',
                tabBarIcon: ({focused, tintColor}) => (
                    // 提供 focused, 从而获取当前底部栏选中与否情况
                    <TabItem 
                        tintColor={ tintColor }
                        focused={ focused }
                        defaultIcon={ require('../pic/h.png') }
                        selectedIcon={ require('../pic/ha.png') }
                    />
                ),
            },
        },
        User: {
            // ...
        }
    },
    // TabNavigatorConfig
    // https://reactnavigation.org/docs/navigators/tab#TabNavigatorConfig
    {
        tabBarPosition: 'bottom',
        iconStyle: {}, // 图标样式,间隙太大,通过margin负值重拉伸
        labelStyle: {}, // 文字样式
        // ...
    }
)

StackNavigator 用来跳转页面和传递参数

StackNavigator(RouteConfigs, StackNavigatorConfig)

const STACK = StackNavigator(
    // RouteConfigs
    https://reactnavigation.org/docs/navigators/stack#RouteConfigs
    {
        // 载入底部栏
        Home: {
            screen: TAB,
            navigationOptions: {
                // [header](https://reactnavigation.org/docs/intro/headers) 
                // APP常见的返回按钮跟标题以及右侧功能按钮(分享,购物车等),没用,自己写的头部
                header: null
            }
        },
        // 其他页面
        Detail: {
            screen: Detail,
            navigationOptions: {
                header: null
            }
        }, 
        // 其他页面2...
    },
    // StackNavigatorConfig
    // https://reactnavigation.org/docs/navigators/stack#StackNavigatorConfig
    {
        mode: 'card', // 这里有个悬而未决的问题, 就是切换页面的模式问题
        // Andorid与IOS上效果永远都是 从下往上 显示页面,而不是APP更常见的左右滑动切换的效果... 
        // react-native 0.47.1, react-navigation 1.0.0-beta.11
    }
)

screenProps 用作换肤、语言切换等

稍候继续...

React Native 常用组件

... 意义重大的省略号,代表着你要会 react 的那一套东西

  • 关于 Flatlist 首次进入会加载两次,个人猜测是首次会触发 触底事件 (不足一屏)
  • 可通过 Platform 获取平台信息,好像文档没看到...
  • 选择图片: react-native-image-crop-picker IOS下请严格按照Post-install steps方式添加
  • 获取网络图片的宽高
// 这是一个异步操作哦
Image.getSize(uri, (w, h) => console.log(w, h, '图片宽高'))
  • 图片轮播: react-native-swiper 要等数据回来了才能渲染此组件哦,要不小圆点不正常工作。
constructor(props) {
    this.swiperDATA = []
}
getPic() {
    fetch('xxx/xxxx').then(res => res.json()).then(data => {
        this.swiperDATA = data
    })
}
render() {
    return (
        {this.swiperDATA.length > 0 ? 
            <Swiper height = { 100 }></Swiper>
            : <View style = {{height: 100}}></View>
        }
    )
}
// 最粗暴的方式,搜狗下换行按钮可以触发提交事件
<TextInput  
    autoFocus 
    underlineColorAndroid={ 'transparent' } 
    onChangeText={(text) => this.setState({text})} 
    value={this.state.text} 
    onSubmitEditing={ (text) => this.search() } 
/> 
  • IOS下正常情况下有 20 高度的顶部条,(也可以没有,xcode内禁用顶部条)
  • IOS下富文本组件 react-native-htmlview 图片渲染部分不成功,最好的解决方案: 给 img 标签 添加 width, height 属性, 具体的原因请查看该组件文件。

状态管理

常见错误

CentOS下安装Nodejs

正式版:工欲善其事必先利其器!
通俗版:装逼无止境!

  1. 在某个目录下载安装Nodejs
cd / // 回到根目录

mkdir soft && cd soft // 创建并进入目录

rmdir soft // 删除目录
  1. 下载Nodejs
 wget https://nodejs.org/dist/v6.10.3/node-v6.10.3-linux-x64.tar.xz 
  1. 解压
 tar xvf node-v6.10.3-linux-x64 
  1. 进入bin目录
cd node-v6.10.3-linux-x64/bin
  1. 测试node
./node -v  // 话说怎么测npm啊 
  1. 添加软连接(可跳过)
ln -s /soft/node-v6.10.3-linux-x64/bin/node /usr/local/bin/node

ln -s /soft/node-v6.10.3-linux-x64/bin/npm /usr/local/bin/npm
  1. 添加到全局环境变量

上述的软连接只是一个指向,不做全局的话会导致全局的express访问不到命令。

 export PATH=$PATH:/soft/node-v6.10.3-linux-x64/bin/
  1. 完成

更换npm源

 npm config set registry https://registry.npm.taobao.org

 npm info underscore // 查看是否更新了源 (最后的tarball属性值)

参考资料

Centos/Ubuntu下安装nodejs
淘宝npm镜像

CentOS安装Git服务器

  1. 安装Git
yum install git
  1. 创建用户
useradd git // 创建名为git用户
passwd git // 设置密码
// git123 这是密码
  1. 为用户生成SSH公钥

git服务器通过 SSH 公钥 进行认证,所有需要为用户生成一份。

cd ~

mkdir .ssh

ssh-keygen -t rsa

cd .ssh/

cat id_rsa.pub >> ~/.ssh/authorized_keys
  1. 创建Git代码仓库
cd /

mkdir git 

chown -R git:git git  // 让此用户具备读写文件夹权限
    // git:git  用户名:用户组(默认创建同名组)

cd git

mkdir git.git && cd git.git

git --bare init // 创建裸仓库   
    // git init 与 git --bare init 的区别请Google

    // 初始化空的 Git 版本库于 /git/git.git/
    // Initialized empty Git repository in /git/git.git/
  1. 客户端连接
git clone git@server:/git/git.git // 这里的地址就是上面创建 git --bare init 提示的路径
...
git push origin master
  1. 大功告成!

参考资料

在CentOS搭建Git服务器

移动端抓包

  1. 下载 Fiddler
  2. Tool -> Telerik Fiddler Options -> Connections
    1 勾选Allow remote computers to connect
  3. Tool -> Telerik Fiddler Options -> HTTPS
    g c4dj w 4u ixr 51h uw 如图勾选对应选项
  4. 手机连上同一网段的WIFI, 设置手机上的WIFI的HTTP代理为手动 :

服务器 => PC的IP地址, 通过 cmdipconfig 命令查看
端口 => 上图所填写的 8888

  1. 手机自带浏览器打开 ip:8888,
    174795334923495036 下载安装FiddlerRoot certificate
  2. 手机浏览器查看网页,能打开网页,表示设置成功,即可回到PC的 Fiddler 页面查看网络请求。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.