biuge / blog Goto Github PK
View Code? Open in Web Editor NEW自产的歪瓜裂枣
自产的歪瓜裂枣
程序员常开的玩笑,没有对象?那就new 一个对象。 Javascript里最重要或者说最基础的概念就是对象, 但是Javascript不像Java那样靠Class 去生成一个新的对象 PS:虽然在es6等高版本中已经有了Class的关键字 但其实只是一个语法糖
我们以最常用的function 函数对象为例子 有一个Man函数 在他的原型对象上 添加两个属性sex和eat
我们可以在Chrome控制台里打印就能看到相关信息
function Man(){
this.name="xx"
}
Man.prototype.sex="男"
Man.prototype.eat=function(){
console.log("wochi")
}
我们可以看到constructor的prototype 又是{sex: "n", eat: ƒ, constructor: ƒ}
不明白的同学会一直点下去发现怎么你中有我 我中有你的 无限循环
因为构造器(constructor) 本质就是一个function对象。
虽然有点绕,可以「简单」的理解为我以自己为模板构造了自己,所以我的模板(原型)就是我自己。虽然是一句废话...
我们还是用图片来讲解比较方便 易于理解
需要注意的是这里prototype 是一个对象 他是一个独立的对象 我这里的独立是指 他不是挂靠在man函数下的 如果你 var a=new Man() 然后把Man.prototype={...} 给修改了 其实a函数 还是指向的这里的object 但要注意的是如果你像在实例a里修改原型方法 比如a.proto.constructor.prototype=xxxx 那就会改动所有man函数衍生的实例切记 没搞明白别乱改
还有一些基础类型 比如字符啊 数字 布尔值 是不能改的 不提供set 只有get 简单的就讲到这里 没懂的旁友 还是自己去看书吧!
function Man(name){
console.log(name)
}
var b = Man
var Man = function (a){
console.log(1)
}
Man(2) // 1
b(3) // 3
猜测 因为 b的指针还是指向了老的Man函数体
我们都知道 变量的声明 都会提前 但是函数表达式更特殊点 他是整个函数提前 这里直接执行不会报错 就是�因为这个原因 具体可以看链接1
b = c;
b();
console.log(a); //1
console.log(b); //2
console.log(c); //3
function c() {
a = 1, b = 2, c = 3;
};
为什么c会�报错 因为函数名在其范围内以及它的父级范围内可见
废话我们可以理解为函数名的c 压制了 变量 c 导致他的值只有函数体内可见 所以到了外部报错
b = function c() {
a = 1, b = 2, c = 3, d = c;
};
b();
console.log(a); //1
console.log(b); //2
console.log(d); //ƒ c() {
// a = 1, b = 2, c = 3, d = c
// }
console.log(c); //Uncaught ReferenceError: c is not defined
这里 b = function c(){} 的操作 我们一般是匿名函数赋值给b 这里变成了�命名�函数表达式 这个名字只在新定义的函数作用域内有效,因为规范规定了标示符不能在外围的作用域内有效:
var f = function foo(){
return typeof foo; // foo是在内部作用域内有效
};
// foo在外部是不可见的
typeof foo; // "undefined"
f(); // "function"
看到这里 应该能明白 问题1了
function Man(name){
console.log(name)
}
var b = Man
相当于
var b = function Man(name){
console.log(name)
}
可以理解为b的函数赋值其实和下面 Man函数修改没有了关系
�回到问题本身 为什么要这样写 有人会说这样不是多此一举
function Man(name){
console.log(name)
}
var b = Man
var Man = function (a){
console.log(1)
}
让我们来看下 monkey-patching的实践 还是�很有用的吧 有兴趣同学可以自行搜索关键字 这里就不展开了
var biugeLog = console.log;
console.log = function() {
//在调用函数前干些什么 比如做点数据打点或者类似的 我这里就简单的alert下
alert('改!');
//像正常调用这个函数一样来进行调用:
biugeLog.apply(this,arguments);
//在这里做一些调用之后的事情。
}
console.log(1) // 打出了1 和改
参考链接
公司老jenkins服务器在奔跑了4年之后,五一节后崩盘。
问题就在于因公司安全考虑只允许数据中心的机器访问外网或内网,(老jenkins机器因历史原因是一台pc机),新jenkins机器我们需要的在线编译功能被安全打回,在和运维以及安全组商议后 同意以搭建一台npm私服的形式来满足需求。
- npm私服机器(linux) 私服拉外网包 用于被jenkins机器消费
- jenkins机器(windows) npm registry指向npm私服 同时配置ssh和服务器连接 进行ssh推送
大概过程请看官方教程
1.注意bindingHost一定要注释掉 不然外网访问不到
2.数据库相关要跑起来 并且和config/index.js中的mysql配置相同
可以使用 node test/init_db来进行初始化
3.在远程ssh登录机器时记得 nohup 命令去执行cnpm项目 不然断开ssh 服务就会暂停 再进一步可以做守护进程 防止进程被关闭
大概过程请看官网教程或谷歌 下面讲几个容易出现的问题
1.置jenkis执行脚本命令 报错 xxx不存在 是外部没装对应的环境就安装 如果外部有 那就是执行变量没有设置
jenkins->系统管理->系统设置->添加环境变量
2.配置npm registry 指向到我们之前搭建的私服 xxx:7001
3.安装publish over ssh 插件 具体如图(网上找的) 配置完成进行test config
如果报错 - jenkins.plugins.publish_over.BapPublisherException: Failed to add SSH key. Message [invalid privatekey: TheKey]
这个错误 请使用PuttyGen 转换 具体请看 overflow的解答
在这里你需要把公钥给运维,让他帮你添加到发布服务器下。 如何生成公私钥请自行搜索
exec command 可以是具体的代码或者脚本
到这里应该就可以发布代码了,后续可能根据不同需求还有预发、 生产不同环境的发布,但操作差不多就不多介绍了。
在业务开发中,根据ui提供的设计图现有的antd-cascader组件不能满足。
以此为契机,我深入antd源码,颇有收获。
同时深感大部分前端无感,抵触,无力分析 动辄上万行的大型库 故写此文写下我的一些心得和分析方法
为什么不能抛开antd 完全去重新做一个组件。因为那会有非常多纰漏是无法想到的 后续观察antd源码的结果也验证了我的顾虑
1.弹出菜单是如何定位
步骤1-分析antd-cascader
antd下有一个ts文件和编译后的js文件 我从js文件入手 在render里return的是 input 和 RcCascader
很明显具体的核心代码在RcCascader ps:rc-xxx 是react-component的简写 antd 所有的核心都在这一级
var input = children || React.createElement(
'span',
{ style: style, className: pickerCls },
React.createElement(
'span',
{ className: prefixCls + '-picker-label' },
this.getLabel()
),
React.createElement(Input, _extends({}, .....)),
clearIcon,
React.createElement(Icon, { type: 'down', className: arrowCls })
);
return React.createElement(
RcCascader,//核心代码
_extends({}, props, { options: options, value: value, ....}),
input //包含了input 展示value和真实value 等巧妙的切换操作
);
步骤2-分析rc-cascader
rc-cascader里有一个menus.js和cascader.js 通过文件名能猜到menus可能是默认的菜单展示component
进去略微修改就编译就发现确实如此 因此我目标1 关联修改的就是这块内容 但是我们要先探究如何定位 就先略过。
回到cascader.js 在render里return了rcTrigger 当时看名字能猜到是事件的交互的一个包装组件 所以我们继续升入rcTrigger.js
return _react2["default"].createElement(
_rcTrigger2["default"],
_extends({
ref: 'trigger'
}, restProps, {
....
popup: menus // 顾名思义 menus是作为属性传给rcTrigger的
}),
(0, _react.cloneElement)(children, {
onKeyDown: this.handleKeyDown,
tabIndex: disabled ? undefined : 0
})
);
步骤3-分析rc-trigger
进入rc-trigger 就看到一个mixins混合类 当时很开心以为找到了包装层,仔细一看没有left,top
就进入了误区以为是在_getContainerRenderMixin2里 结果进去看了半天发现是销毁外层container的一些逻辑
才发现虽然是包装层 但只是最外层的用于绝对定位的定位层,具体的left top逻辑不在此处。
mixins: [(0, _getContainerRenderMixin2['default'])({
autoMount: false,
isVisible: function isVisible(instance) {
return instance.state.popupVisible;
},
getContainer: function getContainer(instance) {
var props = instance.props;
var popupContainer = document.createElement('div');
// Make sure default popup container will never cause scrollbar appearing
// https://github.com/react-component/trigger/issues/41
popupContainer.style.position = 'absolute';
popupContainer.style.top = '0';
popupContainer.style.left = '0';
popupContainer.style.width = '100%';
var mountNode = props.getPopupContainer ? props.getPopupContainer((0, _reactDom.findDOMNode)(instance)) : props.getDocument().body;
mountNode.appendChild(popupContainer);
return popupContainer;
}
})],
步骤4-分析rc-trigger -> index.js
回到index 继续看render里只是返回了children就是祖传的input 没有找到关键代码 线索到这里就断了?
所以我就仔细的一个个方法看下来 发现一个getComponent函数
还使用了props.popup这个属性(步骤2的menus) 作为子节点被包装在_Popup2['default']里 还有一些很敏感的属性 align等等 看着就有线索可寻
先看getComponent 被谁用了 很奇怪在函数内部没有找到调用的钩子 回过头来发现mixins
果然在mixins里发现调用了getComponent 所以 _Popup2['default']里有我们想要的东西
题外话 这里涉及到react组件的抽象方式 从mixins 到hoc 到render props 再到hooks 的演进
而且我看的是编译后的代码 有很多可以学习的地方 有兴趣的可以看下来就能知道babel的一些做法
getComponent: function getComponent() {
var props = this.props,
return _react2['default'].createElement(
_Popup2['default'],
(0, _extends3['default'])({
action: props.action,
align: this.getPopupAlign(),
onAlign: props.onPopupAlign,
animation: props.popupAnimation,
getClassNameFromAlign: this.getPopupClassNameFromAlign
},
.....),
typeof props.popup === 'function' ? props.popup() : props.popup
);
},
步骤5-分析rc-trigger -> popup.js -> rc-align
老规矩先看render 有this.getPopupElement() 进函数内一看return了一个rc-align包装的组件
再进去看rc-align 根据区域判断 发现alignElement函数
if (element) {
result = alignElement(source, element, align);
} else if (point) {
result = alignPoint(source, point, align);
}
步骤6-分析 rc-align -> alignElement -> dom-align -> align/alignElement.js
alignElement.js 依赖 align.js 和 getRegion.js
getRegion 返回一个 refNodeRegion
offset = {
left: _utils2['default'].getWindowScrollLeft(win),
top: _utils2['default'].getWindowScrollTop(win)
};
并且把这个对象 一并返回给 align 去计算
function alignElement(el, refNode, align) {
var target = align.target || refNode;
var refNodeRegion = (0, _getRegion2['default'])(target);
var isTargetNotOutOfVisible = !isOutOfVisibleRect(target);
return (0, _align2['default'])(el, refNodeRegion, align, isTargetNotOutOfVisible);
}
在align.js 中 doAlign 计算获取 这里就是最后的left和top 我尽然发现他用的还是kissy的核心代码
_utils2['default'].offset(source, { //
// https://github.com/kissyteam/kissy/issues/190
left: newElRegion.left,
top: newElRegion.top
}, {
useCssRight: align.useCssRight,
useCssBottom: align.useCssBottom,
useCssTransform: align.useCssTransform,
ignoreShake: align.ignoreShake
});
这一路走下来让我们找到了 位置计算这个核心功能的出处 而且发现是用的kissy的代码 很多新人前端估计都不知道这个库了。这是在我12年刚入行时候淘宝出的代替jquery和YUI的库。在这么多年后,又在新时代的弄潮儿react中使用了。当初看到这里真是百感交集,后续的文章会讲述我如何编写这个新的地址组件。
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.