蘑菇小姐会开花


  • Home

  • Categories

  • About

  • Archives

  • Tags

  • Search
蘑菇小姐会开花

redux middleware

Posted on 2018-09-18 | In notes | | Visitors

wrapping dispatch() to log actions

logger 中间件
函数addLoggingToDispatch,接受一个store为参数,返回一个新的dispatch方法,将store.dispatch覆盖,并log出相对应的action和state信息。

the addLoggingToDispatch function takes the dispatch from the store and returns a new version of dispatch that logs every action and the state

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
const addLoggingToDispatch = (store) => {
const next = store.dispatch;
if(!console.group) {
return next
}
// 返回一个新的dispatch方法
// 在store.dispatch的基础上,log一些信息
return (action) => {
console.group(action.type);
console.log('%c prev state', 'color: gray', store.getState());
console.log('%c action', 'color: blue', action);
const returnValue = next(action);
console.log('%c next state', store.getState());
console.groupEnd(action.type);
return returnValue;
}
}

<!--引用logger中间件-->
const configureStore = () => {
const store = createStore(todoApp)

if(process.env.NODE_ENV !== 'production') {
store.dispatch = addLoggingToDispatch(store)
}

return store
}

wrapping dispatch() to recognize promise

promise中间件
redux 只能dispatch普通的对象,不能dispatch promise
函数addLoggingToDispatch,接受一个store为参数,返回一个新的能处理promise的dispatch方法,。

a function addPromiseSupport() that takes the store and returns a version of dispatch that supports promises.

Read more »
蘑菇小姐会开花

redux persisting the state to the local storage

Posted on 2018-09-12 | In notes | | Visitors

loadState()&saveState()

loadState():按照对应的key: state,从localStorage中取出对应的字符串,将字符串解析成对应的JSON
saveState():接受一个state,将其序列化为字符串,存入localStorage中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!--localStorage.js-->
export const loadState = () => {
try {
const serializedState = localStorage.getItem('state');
if(serializedState === null) {
return undefined;
}
return JSON.parse(serializedState);
} catch (err) {
return undefined;
}
}
export const saveState = (state) => {
try {
const serializedState = JSON.stringify(state);
localStorage.setItem('state', serializedState);
} catch (err) {
// Ignore write errors
}
}

Read more »
蘑菇小姐会开花

git合并多个commit

Posted on 2018-08-28 | In notes | | Visitors

首先我们初始化一个git仓库,进行多次提交。

1
2
3
4
5
6
7
$ mkdir test
$ cd test
$ git init
<!--重复进行commit操作-->
$ vim test.js
$ git add .
$ git commit -m 'commit +1'

之后我们可以看到使用git log命令,查看git的历史,如下:

1
2
3
* commit f40fd657 - (HEAD -> master)  commit +3
* commit 46c7ca3d - commit +2
* commit 220020c7 - commit +1

那么如何把f40fd657(commit +3)、46c7ca3d(commit +2)合并到一起,并且只保留46c7ca3d(commit +2)的git message呢?

Read more »
蘑菇小姐会开花

ajax 重定向跨域问题

Posted on 2018-08-23 | In bugs | | Visitors

最近遇到一个问题:一个页面发ajax请求到后端接口,这个后端接口返回302状态码,并重定向了另外一个域名的地址,此时出现跨域问题

ajax调用浏览器组件发起的请求和浏览器直接发起的请求有一定区别。
1.浏览器可以通过返回的http状态进行相应的操作,如访问一个页面,此页面重定向时,浏览器可以获取到重定向后的url然后进行转向。
2.对于ajax,ajax的目的就是无刷新的,所以对于服务器端进行了重定向时,ajax会获取到重定向状态值3xx和重定向url,然后再获取重定向的页面运行完后输出到客户端的html代码,并且返回200状态。

上面的场景:
1.如果是浏览器发送请求到后端接口,后端接口重定向的话是给浏览器一个302的标示,并且给一个url,浏览器拿到标示后会把地址栏的url换成后端返回的url,完成重定向动作。
2.如果是ajax的话,请求后端接口,后端返回302和一个url,那么ajax会根据htpp的code码做出相对应的动作。接受到的是302那么ajax会再次发起一个请求,去请求服务端302返回的url,那么此时就跨域了。

解决的方式是ajax在第一次得到相应处理后需要js做一次location.href跳转,目的是让浏览器去请求重定向的接口而不是ajax。

Read more »
蘑菇小姐会开花

redux源码解读

Posted on 2018-08-19 | In notes | | Visitors

redux是一个应用数据流框架,它对JavaScript应用而言是一个可预测状态的容器。redux的主要作用是应用状态的管理和数据流的处理。

源码结构

1
2
3
4
5
6
7
8
src
|------- utils #工具函数
|------- applyMiddleware.js
|------- bindActionCreators.js
|------- combineReducers.js
|------- compose.js
|------- createStore.js
------- index.js #入口文件

index.js

入口文件,export createStore、combineReducers、bindActionCreators、applyMiddleware、compose 这几个API

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
import createStore from './createStore'
import combineReducers from './combineReducers'
import bindActionCreators from './bindActionCreators'
import applyMiddleware from './applyMiddleware'
import compose from './compose'
import warning from './utils/warning'
import __DO_NOT_USE__ActionTypes from './utils/actionTypes'

function isCrushed() {}

if (
process.env.NODE_ENV !== 'production' &&
typeof isCrushed.name === 'string' &&
isCrushed.name !== 'isCrushed'
) {
warning(
'You are currently using minified code outside of NODE_ENV === "production". ' +
'This means that you are running a slower development build of Redux. ' +
'You can use loose-envify (https://github.com/zertosh/loose-envify) for browserify ' +
'or setting mode to production in webpack (https://webpack.js.org/concepts/mode/) ' +
'to ensure you have the correct code for your production build.'
)
}

export {
createStore,
combineReducers,
bindActionCreators,
applyMiddleware,
compose,
__DO_NOT_USE__ActionTypes
}

isCrushed这个函数是用来检查在非生产环境下,redux是否被压缩。(默认情况下isCrushed.name === ‘isCrushed’, 被压缩后isCrushed.name会被修改)

Read more »
蘑菇小姐会开花

react-redux

Posted on 2018-08-07 | In notes | | Visitors

Presentation Component UI组件

don’t specify any behaviors and only are concerned with how things are rendered(how they look).
只负责UI的呈现,不带有任何业务逻辑。

Container Component 容器组件

specify behavior and pass data.
负责管理数据和业务逻辑,不负责UI的呈现。

Provider

将store通过context传递给子组件。

render 方法 返回props.children。

context makes the store avaliable to any component that it renders.
通过组件树提供了一个传递数据的方法,从而避免了在每一个层级手动的传递props属性。

getChildContext 使用该方法将属性传递给子组件,并使用。可以覆盖,也可以增加。

childContextTypes provides child context (required in order for the child components to receive context).
声明需要传递给子组件的属性的数据类型。

contextTypes: specify the relevant context that we want to receive.
当需要在当前组件使用从上级组件传入的context的属性是,需要为用到的属性声明数据类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Provider extends Component {
getChildContext() {
return {
store: this.props.store // This corresponds to the `store` passed in as a prop
}
}
render() {
return this.props.children;
}
}

Provider.childContextTypes = {
store: PropTypes.object
}
// example
const App = () => (
<Provider store={store}>
<Comp />
</Provider>
)

connect

一个高阶函数?连接react组件和store,通过获取context的store,来和store中的数据进行链接。

Read more »
蘑菇小姐会开花

redux

Posted on 2018-08-06 | In notes | | Visitors

state&actions&reducer&subscriptions

  • state holds your js apps state.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    {
    todos: [{
    text: 'sleeping',
    completed: true
    }, {
    text: 'reading',
    completed: false
    }],
    visibilityFilter: 'SHOW_COMPLETED'
    }
  • actions are called by your app.

    1
    2
    3
    4
    {
    type: 'ADD_TODO',
    text: 'take some rest'
    }
  • reducers handle the transformations between actions & store.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    function todos(state = {}, action) {
    switch(action.type) {
    case 'ADD_TODO':
    return state.concat({
    text: action.text,
    completed: false
    })
    case 'TOGGLE_TODO':
    return state.map((todo, index) => action.index === index ? {...todo, completed: !todo.completed} : todo)
    default:
    return state
    }
    }
  • subscriptions listen for changes to the store.

三原则

  1. the single immutable state tree.
  2. describing state changes with actions.
    state 只读,需要通过dispatch actions 来改变state。
  3. a pure function reducer describe state mutations.
    接受prevState 和 action,返回nextState。

pure and impure functions

纯函数 输入决定输出,不会改变输入的内容

1
2
3
function sliceArr(x) {
return x.slice(1,2);
}

非纯函数

1
2
3
function spliceArr(x) {
return x.splice(1, 1)
}

Store

  1. holds the current application state object.
    getState()
  2. allows you to dispatch actions.
    dispatch()
  3. when you create it, you need to specify the reducer that tells how state is updated with actions.
    subscribe()
    Read more »
蘑菇小姐会开花

新年快乐哇

Posted on 2018-02-11 | In diary | | Visitors

数一数上次更新博客已经是一个月以前了,当时还是待业在家的状态,到现在就已经入职近两周了。对于我这么懒的人,最后当然是考虑没几天就接了offer哈哈哈。
拼多多是我辞职以后面试的第一家公司,也很幸运的面试完就拿到了offer。其实后面我也还有面试过一两家公司,一个是南京的车300,还有一个是武汉的360,看我过年能不能抽时间回忆一下面试的大致情况哈~后来陆陆续续在boss上又收到了一些很感兴趣公司的邀请,有赞、网易、菜鸟什么的,但都没有下文了,只能希望下一次换工作的时候能有机会去这些公司了😳
入职到现在对新公司都还挺满意的,同项目的同事感觉都很厉害哈哈,刚来公司还在熟悉项目的阶段,也没体会到太多加班的滋味,但是看周围的同事还是可以感觉到晚上加班的人很多,加班力度很大…不过整体给我的感觉是大家都很热爱自己的工作而加班哈哈哈,也不知道是不是我自己歪歪了太多~对我司有兴趣的盆友欢迎私戳简历,可以内推哇😄
来上海以后就和男朋友异地了,也不知道是好是坏,不过身边的朋友都很看好我们就是了。到现在我和他认识快九年了,在一起也快两年了。昨天晚上一直在想又是情人节又快两周年的,要准备个什么礼物给他呢,想了一晚上也没得出结论😢。两年的时间,异地了半年,腻歪了一年半,现在又是异地。也许是半年,也许是一年,也许是接下来的好几年…有些话我不去说,他也不去说,可能谁都没仔细想过之后会遇到什么问题吧,但可想而知的是隔着手机总没有面对面的交流方便。可能我更希望的是,未来的半年、一年或者两三年的时间,生活能被工作占满,以至于我们都没有时间去生气去吵架吧。
记得大学毕业的时候和我群哭的像个傻子,真心里觉得以后是一年或者好些年才能见一次了吧。没想到的是机缘巧合我来了上海,我们又能像在学校的时候那样,时不时就见个面了。其实我也一直没想过会来上海工作,理想的工作城市是杭州,但还是留了下来😺
人生真奇妙啊,总有那么多的意想不到和意料之中。
祝新年快乐,万事胜意。

蘑菇小姐会开花

拼多多面试总结

Posted on 2018-01-12 | In notes | | Visitors

new操作符

  1. 创建一个关联其他对象的新对象
    首先,创建一个新的对象。
    然后,这个对象会被[[prototype]]连接。
    然后,这个新对象会被绑定到函数调用的this。
    最后,如果函数本身没有返回其他对象,那么new表达式中的函数调用会自动返回这个新对象。
  2. 首先,创建一个空对象,并且this变量引用该对象,同时还继承了该对象的原型。
    然后,属性和方法被加入到this引用的对象中。
    最后,新创建的对象由this引用,并且最后隐式的返回this。

关于这部分问题,可以查阅《你不知道的js》。

继承

  1. 构造继承

    1
    2
    3
    4
    5
    6
    7
    8
    function Animal() {
    this.species = "动物";
    }
    function Cat(name, color) {
    Animal.apply(this, arguments);
    this.name = name;
    this.color = color;
    }
  2. 原型继承

    1
    2
    Cat.prototype = new Animal();
    Cat.prototype.constructor = Cat;
  3. 实例继承

    1
    2
    3
    4
    5
    6
    7
    8
    function extend(Child, Parent) {
    var F = function() {}
    F.prototype = Parent.prototype;
    Child.prototype = new F();
    Child.prototype.constructor = Child;
    Child.uber = Parent.prototype; // 直接指向父对象的prototype属性
    }
    extend(Cat, Animal)
  4. 拷贝继承

    1
    2
    3
    4
    5
    6
    7
    8
    9
    function extend2(Child, Parent) {
    var p = Parent.prototype;
    var c = Child.prototype;
    for(var i in p) {
    c[i] = p[i];
    }
    c.uber = p;
    }
    extend2(Cat, Animal)

闭包

闭包就是能够读取其他函数内部变量的函数。由于在JS语言中,只有函数内部的子函数才能读取内部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”,通过另一个函数访问这个函数的局部变量,利用闭包可以突破作用链域,将函数内部的变量和方法传递到外部。闭包可以读取函数内部的变量,让这些变量始终保持在内存中,也可以封装对象的私有属性和私有方法。
闭包的特性:
1.函数内再嵌套函数
2.内部函数可以引用外层的参数和变量
3.参数和变量不会被垃圾回收机制回收

web storage 和 cookie

cookie 存储在用户本地终端上的数据,cookie数据不能超过4k,可设置失效事件,在所有同源窗口中共享。cookie每次都会携带在http头中,如果使用cookie保存过多数据会带来性能问题。
sessionStorage 针对一个session的数据存储,当用户关闭浏览器窗口后,数据会被删除;一般为5MB,仅在客户端(即浏览器)中保存,不参与和服务器的通信;即使是同一个页面,也不在不同浏览器中共享。
localStorage 没有时间限制的数据存储,除非被清除;一般为5MB,仅在客户端(即浏览器)中保存,不参与和服务器的通信;在所有同源窗口中共享。

一个页面从输入URL到页面加载显示完成,这个过程中都发生了什么?

详细版:
1、浏览器会开启一个线程来处理这个请求,对 URL 分析判断如果是 http 协议就按照 Web 方式来处理;
2、调用浏览器内核中的对应方法,比如 WebView 中的 loadUrl 方法;
3、通过DNS解析获取网址的IP地址,设置 UA 等信息发出第二个GET请求;
4、进行HTTP协议会话,客户端发送报头(请求报头);
5、进入到web服务器上的 Web Server,如 Apache、Tomcat、Node.JS 等服务器;
6、进入部署好的后端应用,如 PHP、Java、JavaScript、Python 等,找到对应的请求处理;
7、处理结束回馈报头,此处如果浏览器访问过,缓存上有对应资源,会与服务器最后修改时间对比,一致则返回304;
8、浏览器开始下载html文档(响应报头,状态码200),同时使用缓存;
9、文档树建立,根据标记请求所需指定MIME类型的文件(比如css、js),同时设置了cookie;
10、页面开始渲染DOM,JS根据DOM API操作DOM,执行事件绑定等,页面显示完成。

简洁版:
浏览器根据请求的URL交给DNS域名解析,找到真实IP,向服务器发起请求;
服务器交给后台处理完成后返回数据,浏览器接收文件(HTML、JS、CSS、图象等);
浏览器对加载到的资源(HTML、JS、CSS等)进行语法解析,建立相应的内部数据结构(如HTML的DOM);
载入解析到的资源文件,渲染页面,完成。

跨域

只要协议,域名,端口有任何一个不同,都被当作是不同的域。

1.跨域资源共享CORS(cross origin resource share) 允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
CORS请求需要浏览器和服务器同时支持。浏览器发现AJAX请求跨源,会自动添加一些附加的头信息等。因此,实现CORS通信的关键是服务器,只要服务器实现了CORS接口,就可以跨源通信。CORS背后的基本思想就是使用自定义的http头部让浏览器与服务器进行沟通,从而决定请求是响应成功还是失败。服务器对于CORS的支持,主要是通过设置Access-Control-Allow-Origin来进行的。如果浏览器检测到相应的设置,就可以允许AJAX进行跨域的访问。
2.通过jsonp跨域 以异步加载js文件的形式来调用jsonp的回调函数
jsonp由两部分组成:回调函数和数据。回调函数是当响应到来时应该在页面中调用的函数,而数据就是传入回调函数中的json数据
优点:兼容性好,不需要XMLHttpRequest或者ActiveX的支持,在请求完成后可以通过callback的方式回传结果
缺点:只支持get请求

对比:
1.jsonp只能实现get请求,而CORS支持所有类型的http请求
2.使用CORS,开发者可以使用普通的XMLHttpRequest发起请求和接收数据,比起jsonp有更好的错误处理

css圆环

外半径为40,内半径为20的圆环。

1
2
3
4
5
6
7
{
width: 40px;
height: 40px;
border: 20px solid red;
border-radius: 40px;
background: white;
}

数组去重

1
2
3
4
5
6
7
8
9
function uniqueArr(arr) {
let res = []
for(i=0; i<arr.length; i++) {
let tmp = arr[i]
if(res.indexOf(arr[i]) < 0) {
res.push(arr[i])
}
}
}
蘑菇小姐会开花

拼多多面试

Posted on 2018-01-11 | In notes | | Visitors

2017年12月15日,辞职离开了我毕业后的第一家公司。其实最开始有辞职的念头,大概是九月份的时候,觉得工作没什么意思,公司还每天强制加班很是厌烦,于是对公司提了离职,后来的结果是被挽留了。划水了三个月,在男盆友换工作后,终于决定了离职,裸辞离开了之前的公司。

距离面试已经过去两周了,终于想静下心来写一写了,时间过去的有点久了,很多东西都记得不是很清楚了,尽力而为。

我大概是在12月25日左右在boss上联系了拼多多,很快就收到了回复,本来想先电话面试,但hr说还是现场面试比较好,于是和hr约了12月28日过去面试。

去面试的时候感觉公司环境还可以,找前台说了自己是来面试的,就被带到小房间去填写面试信息了,大概就是一些学历家庭情况的表格,快写完的时候之前跟我联系的hr来了,说先带我去笔试,然后就被带到了里面的小房间去做题了。

笔试

笔试题不是很难,我大概还记得这些问题。
1.new操作符
2.继承
3.304缓存机制
4.css 做圆环
5.写一个function检查一个div是否在视窗内
6.判断一个变量的类型
7.写一个function数组去重
8.web Storage 和 cookie
9.css单位计算
10.rem
11.闭包
12.页面访问流程
13.跨域
其他的我就不太记得了…关于上面的几个问题第3、9、10我是几乎完全不知道怎么写…其他的好像都有一些思路的吧,很多问题在第一轮技术面的时候也被问到了,具体的解答我们之后再说。

hr面试

第一轮面试是hr面试,大概就介绍了一下自己的情况,问为什么从上一家公司离职,问了我了不了解他们公司,我说广告打的很多,家里有人用过,然后hr就给我夸了一下他们公司😂,后面给介绍了一下他们的工作情况,大概是朝11晚8,完全错开早晚上班高峰期,然后基本工资是14薪,年底会有绩效奖,一般周日会加班,加班工资另算,再就是包早中晚三餐。听起来公司福利应该还不错,但是加班应该很严重吧,hr说公司现在发展太快了,所以平时都很忙的。

第一轮技术面

面完hr大概等了20分钟开始技术面,面试官看起来就是程序员哈哈哈哈,人很温柔,也没有太难为我。
一开始就是问了一下在前一家公司做了什么工作,然后就着简历问了一下,具体记不太清楚了…然后就开始技术问题了。

Read more »
12…4
mogu

mogu

唯有热爱,能抵岁月漫长。

34 posts
6 categories
18 tags
GitHub Weibo
© 2017 - 2018 mogu
Powered by Hexo
Theme - NexT.Mist