DingMing

丁大铭的个人空间,用来分享一些前端小技巧,默默成长吧,哈哈

NUXT.JS原理简述

1.那服务器端渲染到底有什么好处呢?

主要的原因时SPA(单页应用)不利于搜索引擎的SEO操作,Nuxt.js适合作新闻、博客、电影、咨询这样的需要搜索引擎提供流量的项目。如果你要作移动端的项目,就没必要使用这个框架了。

2.什么是SSR?

SPA虽然给服务器减轻了压力,但是也是有缺点的:

Read More

Sentry的安装与部署

1.Sentry介绍

sentry是一个实时事件日志记录和汇集的平台。其专注于错误监控以及提取一切事后处理所需信息而不依赖于麻烦的用户反馈。它分为客户端和服务端,客户端(目前客户端有Python, PHP,C#, Ruby等多种语言)就嵌入在你的应用程序中间,程序出现异常就向服务端发送消息,服务端将消息记录到数据库中并提供一个web页方便查看。Sentry由python编写,源码开放,性能卓越,易于扩展,目前著名的用户有Disqus, Path, mozilla, Pinterest等。

2.服务器配置要求

  • Docker 17.05.0+
  • Compose 1.23.0+
  • 最小需要 2400MB RAM,为了后续拓展建议使用8G内存

    3.安装docker、docker-compose

docker-compose 常用命令

1
2
3
4
5
6
7
8
9
10
11
1.docker-compose的使用非常类似于docker命令的使用,但是需要注意的是大部分的compose命令都需要到docker-compose.yml文件所在的目录下才能执行。
2.【Linux命令】docker-compose up【命令解释】 命令聚合每个容器的输出,命令退出时,所有容器都将停止。
3.【Linux命令】docker-compose up -d【命令解释】 在后台启动容器并使它们保持运行。
4.【Linux命令】docker-compose logs -f【命令解释】 查看该容器的启动的日志打印(日志从头打印)。
5.【Linux命令】docker logs -f container_id【命令解释】 查看某一容器的启动的日志打印(日志从头打印)。
6.【Linux命令】docker logs -f --tail 数量词 container_id【命令解释】 查看某一容器的启动的日志打印(查看最后n条日志打印)。 例:docker logs -f --tail 50 44b
7.【Linux命令】docker-compose stop【命令解释】 停止compose服务。
8.【Linux命令】docker-compose restart【命令解释】 重启compose服务。
9.【Linux命令】docker-compose kill【命令解释】 kill compose服务。
10.【Linux命令】docker-compose ps【命令解释】查看compose服务状态。
11.【Linux命令】docker-compose rm【命令解释】删除compose服务。

Docker在2016年很早的时候就明确了将会在企业级方面重点跟进。而在短短的一年时间之内推出的1.12和1.13的版本在功能上确实是很大的进步。而在2017年的3月1号之后,Docker的版本命名开始发生变化,同时将CE版本和EE版本进行分开了,EE是企业版,CE是社区版,如果直接使用

1
2
yum install -y docker-engine 或者
yum install -y docker 安装的都是老版本docker

我们采用的是安装Docker CE版:

3.1卸载旧版本Docker

1
yum remove docker  docker-common  docker-selinux  docker-engine

3.2安装依赖

1、安装依赖包
1
yum install -y yum-utils device-mapper-persistent-data lvm2
2、添加稳定的源
1
yum-config-manager     --add-repo     https://download.docker.com/linux/centos/docker-ce.repo
3、可选操作:允许拓展最新的不稳定的repository
1
yum-config-manager --enable docker-ce-edge

3.3安装docker-ce

1、更新yum
1
yum install makecache fast
2、安装docker-ce
1
yum -y install docker-ce
3、启动docker
1
sudo  systemctl start docker
4、测试docker

查看docker版本,docker至少是17.05.0以上的版本,如果我没有指定版本默认安装最新的则肯定满足条件

docker --version
4、继续安装依赖,需要用到git,docker-compose,pip等组件
1
sudo yum install epel-releasesudo yum install -y python-pipsudo yum install docker-compose

5、docker-compose 的版本必须大于 1.23.0+

可以安装指定版本

1
2
sudo curl -L "https://github.com/docker/compose/releases/download/1.24.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

1.24.0

4. 安装sentry (当前sentry版本v10)

因为sentry本身就是开源的,代码在github上,可以上git直接拉取

github地址:https://github.com/getsentry/onpremise

完成之后,执行如下命令:

1
2
3
 
docker-compose build --pull --force-rm web
docker-compose build --force-rm

发现build成功

  • 生成秘钥

进入sentry文件夹,将默认的config.example.yml和sentry.conf.example.py重命名为config.yml和sentry.conf.py。执行如下命令

1
2
3
 
cp config.example.yml config.yml
cp sentry.conf.example.py sentry.conf.py

执行如下命令生成秘钥

1
docker-compose run --rm web config generate-secret-key

将生成的秘钥添加到config.yml的system.secret-key字段上

  • 进行 Web 服务迁移

执行如下命令开始服务迁移

1
docker-compose run --rm web upgrade

正常情况下是会出现输入账号密码的步骤的,如果不可以请详细查阅这个 https://github.com/getsentry/onpremise/issues/147

执行以下命令

1
docker-compose run --rm web createuser
  • 运行 sentry
1
docker-compose up -d
  • 注意:错误解决
    执行之后发现如下问题,判断可能是docker没有启动的问题

执行如下命令

1
2
service docker status  # 查看docker服务是否启动
systemctl start docker # 启动docker
  • 部署Sentry成功

打开浏览器输入ip:9000,如下图说明安装成功:

  • 修改邮箱设置

打开sentry/config.yml文件,编辑如下信息:

具体配置查看这里 https://docs.sentry.io/server/config/#mail

1
2
3
4
5
6
7
8
9
10
11
 mail.host: 'smtp.dc.17zuoye.net'
mail.port: 25
mail.username: 'no-reply@17zuoye.com' //不需要密码
mail.use-tls: false //关闭 TLS
mail.from: 'no-reply@17zuoye.com'
mail.list-namespace: 'zuoye.com'



注意要将服务器防火墙与服务器安全组的邮箱端口放开,
注意:如果使用Sentry10的话 使用tsl邮箱端口必须为567不然会报错
  • 重新执行以下命令
1
2
3
4
docker-compose build --pull --force-rm web
docker-compose build --force-rm
docker-compose run --rm web upgrade
docker-compose up -d // 若此步无响应可执行 docker-compose stop 在执行

可以看到邮箱信息已经修改掉了,下面我们发送一封测试邮件,点击下方的Test Settings

5.Sentry使用

React-hook用法

useState

useEffect

在页面每次渲染完之后都会执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import React,{ useState,useEffect } from 'react';

const LikeBut = () => {
const [like, setLike] = useState(0);
const [on, setOn] = useState(true);
useEffect(()=>{
document.title = `点击了${like}次`
})
return(
<div>
<button onClick={()=>{setLike(like+1)}}>
{like} @
</button>
<button onClick={()=>{setOn(!on)}}>
{on?'on':'off'}
</button>
</div>
)
}

export default LikeBut;

在document监听click事件会有问题,所以sueEffect提供了清除回调

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import React , {useState,useEffect} from 'react';

const Mouse = () => {
const [ positions, setPositions ] = useState({x: 0, y: 0});

useEffect(()=>{
const updateMouse = (event)=>{
console.log('inner')
setPositions({x:event.clientX,y:event.clientY})
}
console.log('add listener')
document.addEventListener('click',updateMouse);

return ()=>{
console.log('remove listener')
document.removeEventListener('click',updateMouse)
}
})

return(
<p>X:{positions.x},Y:{positions.y}</p>
)

}

export default Mouse;


// 打印顺数
初始化时 add listener

点击后
inner
remove listener
add listener

控制useEffect的执行

1
2
useEffect(()=>{},[])
第二个参数可以被设置成触发条件

自定义hook

自定义hook 胜于 HOC 高阶组件 更加清晰 便于阅读

Hook 规则

  • 只在最顶层使用Hook
  • 只在React函数中使用Hook

如何在iOS13的Safari中检测设备名称

Apple iOS 13之后,iPad iOS 13的Safari中的window.navigator.userAgent与MacOS相同。像这样:

1
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15
1
2
3
所以不能用之前方式来判断 是否是 ipad 了

/iPad|iPhone|iPod/.test(navigator.platform)

Read More

模拟圆规-内容输出

最近接到了一个需求,使用JS制作一个圆规课件

功能如下:

图1 图1
图2 图2

图1和图2 分析

最开始的想法是 使用斜率 k=tanα=(y1-y2)/(x1-x2) 来时时的计算倾斜角来控制圆规的三部分运动;

可是后来我发现,我想多了:

  • 圆规的三部分不是直线运动而是抛物线
  • 还有一个最关键的点就是,常规的数学坐标系是从左下方开始的,而前端的坐标系默认是从左上方开始的

所以我必须转换思路

机智的我想想到了一个极简的想法,不管他是曲线运动还是什么斜率,无非逃不出一个界定的范围,运动什么的都让代码自行事项吧。

  1. 首先是记录圆规的三部分的初始坐标和倾斜角
  2. 其次是利率圆规的三部分的最大范围的坐标和倾斜角
  3. 拉伸范围是固定的,我们可以计算出圆规被拖动的距离的比例
  4. 在拉伸的时候时时改变圆规的三部分的最大范围的坐标和倾斜角的比例

这样就完成了图1和图2的需求

效果如下:图3

图3 图3

接下来来到了画圆的环节了

效果如下:

图4 图4

首先是画圆

这个画圆可是让我选择了好久,我的方案有这么几种:

序号 方案 采用与否的原因
1 直接用 JS 生成 Dom元素 往页面里不断push就行 不可行 生成Dom太多了 不太好
2 使用css boder 滚动(类似圆形进度条) 可行 备选状态 但是它消耗页面性能
3 使用canvas 画圆 尝试 感觉不可行(使用style 动态改变画布宽高是 内部画出来的圆是椭圆形) 有明显锯齿 需要优化
4 使用svg 画圆 目前采用的是这个方案

!!! 但是使用 svg circle 画圆他默认是顺时针旋转的 这里我用了一个骚操作 使用 transform:scaleY(-1); 使svg 水平镜像翻转。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<svg id="svg" :style="svgCss">
<circle class="path"
stroke="hotpink" // 划线的颜色
fill="none" // 填充颜色
stroke-width="1%" // 划线的宽度 可以使用百分比这是太棒了
cx="50%" // 圆心X轴位置
cy="50%" // 圆心Y轴位置
r="49.5%" //圆的半径
/>
</svg>

stroke-dasharray: 360%; //展示比例
stroke-dashoffset: 360%; //绘画比例

后续还需使用 Math.atan2 来时时计算倾斜度 来进行拖动画圆

1px-Bug

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/**
* 本文件主要放各种sass的function或者mixin,可以直接在.vue中的sass使用
*/

/**
* 主要是给border为0.5的时候使用的,当只有一条border或者border需要全部设置的画建议使用下面几个方法
*/
@mixin border-hack($color: #e7e7e7, $d1: none, $d2: none, $d3: none, $d4: none) {
position: relative;
&::after{
content: '';
transform: scale(0.5);
position: absolute;
left: -50%;
right: -50%;
top: -50%;
bottom: -50%;
@if($d1 == 'left' or $d2 == 'left' or $d3 == 'left' or $d4 == 'left'){
border-left: 1PX solid $color;
}
@if ($d1 == 'right' or $d2 == 'right' or $d3 == 'right' or $d4 == 'right') {
border-right: 1PX solid $color;
}
@if ($d1 == 'top' or $d2 == 'top' or $d3 == 'top' or $d4 == 'top') {
border-top: 1PX solid $color;
}
@if ($d1 == 'bottom' or $d2 == 'bottom' or $d3 == 'bottom' or $d4 == 'bottom') {
border-bottom: 1PX solid $color;
}
}
}

@mixin border-hack-top($color: #e7e7e7) {
@include border-hack($color, top);
}
@mixin border-hack-right($color: #e7e7e7) {
@include border-hack($color, right);
}
@mixin border-hack-bottom($color: #e7e7e7) {
@include border-hack($color, bottom);
}
@mixin border-hack-left($color: #e7e7e7) {
@include border-hack($color, left);
}
@mixin border-hack-all($color: #e7e7e7) {
@include border-hack($color, left, right, top, bottom);
}


1
2
3
4
5
6
.test{
width: 100%;
background: yellow;
color: white;
@include border-hack-all(red);
}

Vue2.x双向数据绑定原理

  • vue.js是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动的时候发布消息给订阅者,出发相应的监听回调。
  • 第一步:需要observe的数据对象进行递归遍历,包括子属性的对象属性,都加上setter和getter。这样的话,给这个对象的某个值复制,就会触发setter,这样就能监听到数据变化;
  • 第二步:compile解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有改变,收到通知,更新视图;
  • 第三步:Watcher订阅者是Observer和Compile之间通信的桥梁,主要做的事情是:
    • 1、在自身实例化是往属性订阅器(dep)里面添加自己
    • 2、自身必须有一个update()方法
    • 3、待属性变动dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调,则功成身退
  • 第四步:MVVM作为数据绑定的入口,整合Observer、Compile和Watcher三者,通过Observer来监听自己的model数据变化,通过Complie来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化->师徒更新;视图交互变化(input)->数据model变更的双向绑定效果。

vue中computed和watch的区别

计算属性computed:

  1. 支持缓存,只有依赖的数据发声改变,才会重新进行计算
  2. 不支持异步
  3. computed属性值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的
  4. 如果computed属性值是函数,那他默认会走get方法,函数的返回值就是属性的属性值;在computed中的,属性都有一个get和一个set方法,当数据变化时,调用set方法。

监听属性watch:

  1. 不支持缓存,数据变,直接回触发对应操作;
  2. watch支持异步;
  3. 监听的函数接收两个参数,第一个是新值,第二个是之前的值;
  4. 当一个属性发声变化时,会执行对应操作,一对多;
  5. 监听数据必须是data 声明的或者props 中的数据

JWT学习

JSON Web Token

缩写JWT 一种目前比较流行的跨域认证解决方案

JWT的原来

原理就是:服务器认证以后,生成一个JSON对象,发回给用户,如下

1
2
3
4
5
{
"姓名": "张三",
"角色": "管理员",
"到期时间": "2018年7月1日0点0分"
}

以后,用户与服务端通信的时候,都要发回这个 JSON 对象。服务器完全只靠这个对象认定用户身份。为了防止用户篡改数据,服务器在生成这个对象的时候,会加上签名。

服务器就不保存任何 session 数据了,也就是说,服务器变成无状态了,从而比较容易实现扩展。

Read More