开发记录 (Weex) - 日志: 开发流水账

191028

项目启动报错,关键信息:

Node Sass could not find a binding for your current environment: Windows 64-bit with Node.js 12.x
Found bindings for the following environments: - Windows 64-bit with Node.js 10.x

原因是项目中的 Node Sass 依赖组件的版本低,不支持新版 Node.js,经查后,升级即可:

npm i node-sass -D

升级后解决。

开发记录 (JS) - 备忘: 深拷贝和浅拷贝

Object.assign

只对对象的顶层属性做简单的直接赋值操作,不会对下一层属性及更深层属性进行深拷贝,适合用来样式合并。

JSON.parse(JSON.stringify(obj))

如果有属性是 Function 或 Undefiend 或 Null 这些 JSON 中不支持的类型,则该属性会被移除;Date 对象数据,则会无法还原。

开发记录 (Weex) - 经验: 在 Weex 开发中遇到的“大坑小坑”

这是“踩坑”记录,排序不分先后:

在 Weex 中

  • 主要布局方式是 Flex,不支持浮动,支持定位。定位中脱离文档流的模式如 absolute,是不参与 Flex 布局的,就是说 Flex 属性无法在添加这种模式的元素上生效。
  • 脱离文档流的元素,可以用 left: 0right: 0 来达到 width: 100% 的效果;height: 100% 同理。
  • 不支持对象语法绑定 class,需要使用数组语法,例如 :class="[isActive ? 'active' : '' ]"
  • 不支持使用嵌套语法编写样式。
  • 不支持 emrem 以及百分比等长度单位,只能使用 px
  • 使用 <image> 组件代替 <img> 标签,不支持本地图片,并需要指定宽高属性,否则无法显示。
  • 文本标签 <text> 对于“回车”比较敏感,会将其显示为一个空白字符,导致各种样式问题,格式化代码时要注意。

文字溢出截断并显示省略号

常规页面中,单行文字溢出后,截断并显示省略号的方法是,首先为目标元素设置宽度,然后设置以下样式:

1
2
3
4
5
6
/* 溢出隐藏*/
overflow: hidden;
/* 强制不换行 */
white-space: nowrap;
/* 溢出显示省略号 */
text-overflow: ellipsis;

在 Weex 中上面的样式行不通,为目标元素设置宽度后,设置样式为:

1
2
3
4
/* 溢出显示省略号 */
text-overflow: ellipsis;
/* 设置行数,超出这个值后截断 */
lines: 1;

开发记录 (Git) - 经验: 为同一设备配置多个 SSH key 以对应不同的 Git 服务器

现在一个人同时有好几个 Git 账号或服务的情况越来越多,例如自己的私有仓库和公司的项目仓库分别在不同的 Git 服务器上。但是要用自己的同一台设备,重新生成 SSH key 会将之前的覆盖掉, 如何生成和管理多个 SSH key 呢?

步骤

假设在 ~/.ssh 目录下已经生成过密钥:id_rsaid_rsa.pub

  1. 生成第二个 SSH key

    和生成第一个命令相同:

    ssh-keygen -t rsa -C "youremail@example.com"

    这里不要一路回车,到输入路径提示时,填写保存路径(可以新建目录分别存放):

    Generating public/private rsa key pair.

    Enter file in which to save the key (/c/Users/xxx/.ssh/id_rsa): /c/Users/xxx/.ssh/id_rsa_gitlab

    后面的两步则为设置密码,可以直接回车跳过。

    这里的 id_rsa_gitlab 是可以自定义的,只要区别于原有的密钥名即可。

    完成之后就可以看到目录下多了两个文件:id_rsa_githubid_rsa_gitlab.pub

  2. 打开 ssh-agent

    如果使用 GitHub 官方的 bash ,输入:

    ssh-agent -s

    如果是其他的,例如常用的 Git Bash,输入:

    eval $(ssh-agent -s)

    略过此步骤,下一步会有错误提示:Could not open a connection to your authentication agent.

  3. 添加私钥

    分别输入命令:

    ssh-add ~/.ssh/id_rsa

    ssh-add ~/.ssh/id_rsa_gitlab

    如果提示文件或目录不存在,就使用绝对地址。

  4. ~/.ssh 目录下创建名为 config 的文件,后缀名为空;

    用文本编辑器打开后,添加以下内容:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # github & gitlab
    # 注意:多个Host公用一个公钥时,对应的HostName和Port必须跟在Host后面
    # github
    Host coding1
    HostName github.com
    PreferredAuthentications publickey
    IdentityFile ~/.ssh/id_rsa

    # gitlab
    Host coding2
    HostName gitlab.ceair.com
    PreferredAuthentications publickey
    IdentityFile ~/.ssh/id_rsa_ceair
    User Git

    其中:Host 为主机名,可以自定义,但不能重复;HostName 主机的真实域名地址;PreferredAuthentications 是配置登录时使用的登录权限;IdentityFile 是私钥路径;User 是服务器账号名,不是自己的用户名,一般都是 Git;必要时,还需要添加 Port 属性,其默认值为 22。

    如果在 Linux 系统中有错误提示:Bad owner or permissions on /home/xxx/.ssh/config

    说明 config 权限过大,使用 chmod 命令调整:$ chmod 644 ~/.ssh/config

  5. 添加公钥

    在相应的 Git 服务页面中添加公钥,不赘述。

  6. 测试

    之前是直接输入 ssh -T git@github.com,现在则可以通过简称映射对应的域名和私钥,例如:

    ssh -T git@coding1

    而名为 coding2 的配置,设置了 User 属性,则可以简单输入 ssh -T coding2 完成测试。

    如果测试中收到错误提示:

    1
    2
    3
    The authenticity of host 'xxx (x.x.x.x)' can’t be established.
    RSA key fingerprint is SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
    Are you sure you want to continue connecting (yes/no/[fingerprint])?

    则是因为新增的主机未添加至 know_hosts 文件中,输入 yes 回车即可。

    如果错误提示是:PTY allocation request failed on channel 0,则是因为将 -T 写成了小写。

调试

如果测试不成功,可以使用调试命令 --debug,例如测试 coding1:ssh -vT git@github.com`

命令 -v 是输出编译信息,然后根据信息可以排查编译中发生的错误。

使用

配置好多个 SSH key后,拉取代码时,需要将 SSH 地址做细微修改,才能用正确的用户去登陆验证。就是将对应域名(IP)换成 config 文件里配置的 Host 属性值即可。

例如原本的 SSH 地址为 `git@git.coding.net:master/DemoForSSH.git,需要修改为git@coding1:master/DemoForSSH.git再拉取即可。如果配置了User属性,SSH 地址可以简写为coding2:master/DemoForSSH.git`

拾遗

  1. 关于用户名

    如果之前设置了全局用户名和邮箱的话,需要取消一下:

    git config --global --unset user.name

    git config --global --unset user.email

    然后在不同的仓库下设置局部的用户名和邮箱,比如在公司的 repository 下:

    git config user.name "yourname"

    git config user.email "youremail"

    最后在自己的仓库重新执行刚刚的命令即可,这样就可以在不同的仓库,以不同的账号登录。

  2. 关于提交记录

    通过 SSH 拉取的代码,如果之前在 ~/.gitconfig 文件里配置过 user 信息,而又不想用全局的 user 信息,可以在当前工程里的 .git/config 文件里配置 user 信息,以便查看commit记录等,例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    [core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
    ignorecase = true
    precomposeunicode = true
    [user]
    name = yourname
    email = youremail@example.com
    [remote "origin"]
    url = xxx
    fetch = xxx
    [branch "master"]
    remote = origin
    merge = refs/heads/master
  1. 关于 TortoiseGit 中输错密码的处理:

    在控制面板中的“用户账户”设置中,找到“windows凭证管理”,在普通凭证中,删掉输错的对应项即可。

参考

参考1:https://zyoung.me/多账号SSH配置/

参考2:https://www.jianshu.com/p/f7f4142a1556

前端系统课程 - 41. 会动的简历

特效原理

  • 效果页面

  • 使用循环定时器 setInterval() 方法,结合字符串截取方法如 substring()split(),在相同的间隔时间,改变页面显示的文字,就有逐个打字的效果。

  • 使用 <pre> 标签(preview),可以保留文字原始的格式。

  • 页面中写入代码的同时,将代码也写入到相应的标签中,这些代码就会生效。

代码高亮

  • 将代码写入页面上后,用替换的方式,将关键字换成用带有特殊类名或行内样式的标签包裹的字符串。例如:

    1
    2
    3
    htmlBox.innerHTML = str.slice(0, round);
    htmlBox.innerHTML = htmlBox.innerHTML.replace('html', '<span style="color: #f00;">html</span>');
    // 下面这行代码成功执行的条件是页面中需要有目标字符;当页面中完整出现目标字符,证明这段字符在CSS中已经写完了,所以不会影响样式
  • 使用专门的库来实现更加完整的代码高亮功能,例如:Prism.js。

支持 Markdown

  • 可以使用 marked.js 等相关的库。
  • 将替换完成的 <div> 标签使用 replaceWith() 方法将原来的 <pre> 标签替换掉;但这是一个比较新的替换 DOM 元素的方法,可能有兼容性问题

灵活使用回调函数

  • 右侧的 markdown 写完之后,左侧提示转换为 HTML,再进行转换,然后左侧再进行提示;这些流程都需要通过回调函数来衔接,例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    left('', str1, () => {
    right(str0, () => {
    left(str1, str2, () => {
    mark(str0, () => {
    left(str1 + str2, str3);
    });
    });
    });
    });
  • 要理清代码执行的思路,主要是要想清楚代码的执行顺序(操作符的优先级),例如:

    1
    cssBox.innerHTML = str1 + str2.slice(0, round);

    上面的代码中是从右往左赋值,要先得到最右面的 str2.slice(0, round) 的值,再用这个值和 str1 拼接,最后赋值给 cssBox.innerHTML

前端系统课程 - 39. 面向对象编程

如何理解面向对象编程

老师如是说:就是以对象为主编程,它不是一个概念,而是一种经验,主要就是为了最大程度的代码复用;装逼的说法叫“OO编程,Object-Oriented Programing”。

相关术语

  • 命名空间 Namespace;允许开发者在一个独特的、名字与应用相关的名称下捆绑所有功能的容器。

  • 类 Class;定义对象的特征,它是对象的属性和方法的模板定义。

  • 对象 Object;类的一个实例。

  • 属性 Property;对象的特征,比如颜色。

  • 方法 Method;对象的能力,比如行走。

  • 构造函数 Constructor;对象初始化的瞬间被调用的方法,通常它的名字与包含它的类一致。

  • 继承 Inheritance;一个类可以继承另一个类的特征。

  • 封装 Encapsulation;一种把数据和相关的方法绑定在一起使用的方法。

  • 抽象 Abstraction;结合复杂的继承、方法、属性的对象能够模拟现实的模型。

  • 多态 Polymorphism;顾名思义为“许多形态”,指不同的类也可以定义相同的方法或属性。

全局命名空间

  • 通过或运算符 || 来避免你初始化的全局命名空间与可能存在的同名属性相冲突;这种方式又叫“兜底操作”,如果原先有这个变量,那就把已有的数据重新赋值一次(虽然这是一个多余操作);如果原先没有这个变量,那就赋值为新的数据。例如:let nameSpace = nameSpace || {},这种方式也经常用在函数的参数判断中。

  • 或运算返回第一个 truthy 值,与运算则返回第一个 falsy 值。

解决重复代码

在代码分层的过程中会发现,MVC 这三层代码在实现功能时,都会有一些必要而又重复的代码,例如初始化 init() 等属性或方法,那么要想使代码最大化的复用,就需要对这些分层代码进行分类。

再谈 this

  • 事件触发的回调函数中的 this 通常是指向触发事件并调用函数的元素,事件委托同理。例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    obj.onclick = function () {
    console.log(this); // obj对象;
    }

    btn.addEventListener('click', function () {
    console.log(this); // btn对象;
    });

    $('ul').on('click', 'li', function () {
    console.log(this); // li对象
    });
  • 要记住 thiscall() 的第一个参数;而有时候判断就要靠查询和记忆了,另外就是要捋清楚,谁调用了函数,谁就是 this

new 操作符干了什么

  • 如果我们要创建多个具有相同引用类型属性(如方法)的对象,直接多次重复创建相同对象后再赋予这些对象某些不同的属性是可以解决问题,但是很多相同属性无法复用,特别是引用类型属性,这将造成很大的资源浪费。

  • 通过原型可以解决前面的问题,将共有属性都放在一个原型对象里,然后想办法将新建对象的原型指向这个原型对象,新建对象们就共享了原型对象中的属性,节省了资源。

  • 那么又如何优雅的实现上一条中的功能呢?当然要用构造函数(工厂函数)了。

  • 当在构造函数前使用 new 操作符时,函数内部会隐性的创建一个临时对象,然后将这个对象设置为 this ,这样临时对象便获得了函数里的作用域;然后构造函数将自己的原型对象中的 constructor 属性设置为构造函数本身,这样新的对象就知道自己是由谁创建的。再然后构造函数将临时对象的原型指向了构造函数的原型对象(共有属性,这一步实际就是进行 newObj.__proto__ === Obj.prototype),并进行一系列的属性(自有属性)构造后,最后将这个对象 return 出去。除了构造函数内部的显性的属性构造,其余操作都是隐性的。

  • 对象创建后,如果给原型对象添加或更改属性,新创建的对象也会拥有这些新添加或更改的属性。

  • 以此看来,new 操作符可以帮你省下很多操作,所以,它是一个语法糖。