[工作笔记] 2018年六月二十二日小计

今天是来杭州的第三个月后的十几天,正是的现在这份工作转正的日子。几天前转正面谈时 CTO 对于前几个月的工作给予了肯定,同时也提了几点建议。这也是这篇文章存在原因之一。

要养成一些好的习惯、好的方法、并学会分享。这些好的习惯以后会跟着你走。

来杭州三个月,也习惯了这里的生活。在新的公司做了两三个小项目,也研究了几个以前没有仔细研究的技术。小有收获。最近一周一直在忙两个项目,一是智能柜,二是景区。以下是我最近开发的一些心得和技巧:

在开发微信小程序时,我们可以将小程序中常用的基本配置统一抽离出来放在一个config.js中如下:

const SERVER_URL = 'http://www.xxx.com/api';
const TEST_SERVER_URL = 'http://test.xxx.com/api';
const CDN_URL = 'http://cdn,xxx.com';
const TEST_CDN_URL = 'http://tcdn.xxx.com';

export CONFIG_PRODUCT = {
    SERVER_URL,
    CDN_URL,
    DEBUG_FLAG:false,
    TEST_FLAG:false,
}

export CONFIG_TEST = {
    SERVER_URL:TEST_SERVER_URL,
    CDN_URL:TEST_CDN_URL,
    DEBUG_FLAG:true,
    TEST_FLAG:false,
}

然后按照开发需求引入这些配置信息(如 控制console.log),在后期方便配置的统一管理和维护。

对网络请求(wx.request)进行二次封装如下例:

import { CONFIG } from './config';
import MD5 from './md5'/**
* 定制功能的网络请求方法
* @param options object
* @property url string 请求的资源地址,在请求时会自动添加服务器地址。
* @property data object 请求所携带的参数
* @property header object 请求头
* @property success function 请求成功的回调
* @property fail function 请求失败的回调
* @property complete function 请求完成的回调
* 
* 功能简介:
* 传入与 wx.request 相同的参数,方法内部会对几个重要部分进行功能根据项目需求强化,如在 header 
* 中添加验证字段,对 POST 方法时将 header 的 content-type 改为对应参数。对特定的 状态码(400)
* ,进行处理。
* 
*/
export default (options) => {
  const { APP_CONFIG: { SERVER_URL, DEBUG_FLAG,SPEACAL_SERVER_URL } } =   CONFIG;
  if (DEBUG_FLAG) {
      console.group('网络请求');
      console.log(options);
  }
  if (!options.anotherFlag) {
      wx.showLoading({
           title: '正在加载'
      })
  }
  if (options.anotherFlag) {
     let String1 = ''
     const { data:{query,mainData} } = options
     query.time = Math.ceil(Date.now() / 1000);
     const dataKeyArray = Object.keys(query).sort();
     dataKeyArray.forEach((e, i) => {
                                      if (i === 0) {
                                           String1 += `${e}=${query[e]}`;
                                      } else {
                                           String1 += `&${e}=${query[e]}`;
                                      }
                                    })
     const String2 = `${String1}&secret=yoursalt`;
     const token = MD5(String2);
     options.url = `${SPEACAL_SERVER_URL}token=${token}`;
     options.header = modifyHeader(options.header);
     options.header['Content-Type'] = 'application/json';
     options.method = 'POST';
     options.data = mainData;
  } else {
     options.url = `${SERVER_URL}${(options.url) ? '/' + options.url : ''}`;
     options.header = modifyHeader(options.header);
     options.method = 'POST';
  }
   if (typeof options === 'object') {
      const success = options.success;
      const fail = options.fail;
      const complete = options.complete;
      options.success = success ? res => {
        if (DEBUG_FLAG) {
          console.log(res);
          console.groupEnd();
        }
        if (res.flag !== 0 && !options.anotherFlag) {
          fail ? fail(res) : '';
        } else {
          success(res);
        }
     } : null;

    options.fail = fail ? res => {
       if (DEBUG_FLAG) {
         console.log(res);
         console.groupEnd();
       }
         fail(res);
    } : null;

    options.complete = complete ? res => {
       if (DEBUG_FLAG) {
          console.groupEnd();
       }
       if (!options.anotherFlag) {
         wx.hideLoading();
       }
       complete(res);
    } : () => {
      if(!options.anotherFlag){
         wx.hideLoading();
      }
    };
  }
  wx.request(options);
}

const modifyHeader = header => {
    const token = wx.getStorageSync('token');
    if (token) {
       return { ...header, token: `${token}` };
    } else {
       return (header) ? header : {};
    }
};

当然也可以根据个人的开发习惯进行 promise 封装。这样封装的好处也显而易见,方便对所有的 request 进行监控,通用逻辑的修改,方便调试和开发。

在写些小程序的条件动画时,也可以十分方便如下:

// page.wxss
.css-a{
    transform:translate3d(-100%,0,0); // 将 css-a 元素上移全部高度
    transition:all .5s;
}

.css-a.show{
    transform:translage3d(0,0,0); // 将 css-a 元素动画回原位
}

// page.wxml

<view class='css-a {{showFlag ? "show":""}}'>动画DEMO</view>

// page.js

// 触发的动画事件
  onTrigger(){
     this.setData({showFlag:true});
  }

通过绑定点击、触摸事件,就能够实现很多简单的动画,提升人机交互的乐趣。

[踩坑指北] JavaScript Date 对象踩坑

最近的两个项目中对日期判断的需求较多。所以最近也踩了几个 JavaScript 中 Date 对象的坑。如下两种:

iOS 所有浏览器及 MAC OS 中的 Safari 浏览器中的 Date 属性不能处理 YYYY-M-DD 的值传入:

   /*Chrome MacOS*/
   const dateObj = new Date('2018-01-12');
   console.log(dateObj) // Fri Jan 12 2018 08:00:00 GMT+0800 (CST)

  /*Safari MacOS*/
  const dateObj = new Date('2018-01-12');
  console.log(dateObj) // Fri Jan 12 2018 08:00:00 GMT+0800 (CST)
  const dataObj2 = new Date('2018-1-12);
  console.log(dataObj2) // Invalid Date

至于国产浏览器,就不说了 。Date.prototype.toString() 完全不按规范来。哎

[nodeJs] express框架应用接入阿里云函数计算

由于业务需要接触阿里云函数计算,为保证已有的 nodejs 应用迁移至阿里云函数计算。经过两天的摸索之后得到一些 express.js 应用迁移至函数计算的一些方法。

涉及技术及框架:

  1. nodejs
  2. feathers.js
  3. 阿里云函数计算

主要流程:

  1. 对比函数计算 http 触发器 与 express 的相同点和不同点,对原先的应用进行兼容处理
  2. 解决函数计算触发器和 express 框架的数据传递问题
  3. 测试迁移之后的应用稳定性

(1)对比函数计算 http 触发器,与普通的基于 express 的应用的不同点

属性 函数计算 应用 普通 express 应用
触发方式 由 exports.XXX.handle 方法触发 通过监听指定端口的网络请求触发
接收到的参数 入口函数会得到(request,response,context) express 接收到(request<http.InComingMessage>,response<http.ServerResponse>)

由于原先的应用基与 express 开发,在迁移至函数计算之后将不能通过监听端口的网络请求触发 request 事件。那么根据 express 中 listen 的实现

app.listen = function listen() {
  var server = http.createServer(this);
  return server.listen.apply(server, arguments);
};

我们只需通过向 http.createServer 传入 express 对象,来创建一个 http.server 实例。当函数计算触发器被触发,再通过server.emit(‘request’, requset , response ) 来触发express 应用的工作流。

(2)函数计算入口函数的参数的兼容性改造

我们只能从函数计算入口函数拿到request,response,context。但是request、response 并非 http.InComingMessage 、http.ServerResponse 实例,如何通过 server.emit(‘request’, req , res ) 将入口函数传入的信息传入 express 工作流中。我们需要对 requset、response 进行改造

request  结构体:

headers:<map>, //存放来自 HTTP 客户端的键值对
path:<string>, //为 HTTP URL
queries:<map>, // 类型,存放来自 HTTP URL 中的 query 部分的 key - value 键值对, value 的类型可以为字符串或是数组
method:<string>, // 类型,HTTP 方法
clientIP:<string>, // 类型,client 的 IP 地址
url:<string>, // 类型,request 的 url

response 结构体:

response.setStatusCode(statusCode) : 设置 status code
param statusCode : (required, type integer)
response.setHeader(headerKey, headerValue) :设置 header
paramheaderKey : (required, type string)
paramheaderValue : (required, type string)
response.deleteHeader(headerKey) :删除 header
paramheaderKey: (required, type string)
response.send(body): 发送 body
parambody: (required, typeBuffer or a string or a stream.Readable )

http.InComingMessage 结构体:

参考 http://nodejs.cn/api/http.html#http_class_http_incomingmessage

http.ServerResponse 结构体:

参考http://nodejs.cn/api/http.html#http_class_http_serverresponse

其中 express 应用中的 req 和 res 实现了很多封装的方法,所以我们需要根据自己的需要来进行兼容性改造

const http = require('http');
const express = require('express');

const app = express()

const FCServer = http.createServer(app);

module.exports.handler = (request, response, context) => {
  try {
    // 通过 app.request 和 app.response 创建 inComimgMessage 和serverResponse
    const inComimgMessage = Object.create(app.request);
    const serverResponse = Object.create(app.response);

    // 将 request 的部分信息赋值给 inComimgMessage
    inComimgMessage.headers = request.headers;
    inComimgMessage.method = request.method;
    inComimgMessage.path = request.path;
    inComimgMessage.url = request.path;
    inComimgMessage.query = request.queries;

    // 使用 response 的方法替换掉 serverResponse 的一些方法
    serverResponse.setHeader = (key, value) => response.setHeader(key, value);
    serverResponse.end = (data, encoding, callback) => {
      response.send(data);
    };
    serverResponse.send = serverResponse.end;

    serverResponse.status = (code) => {
        response.setStatusCode(code);
    };

    serverResponse.writeHead = (code, message, headers) => {
      response.setStatusCode(code);
    };

    serverResponse.sendStatus = (code) => {
      response.setStatusCode(code);
      response.send(code);
    };

    serverResponse.json = (body) => {
      response.setHeader('content-type', 'application/json');
      if (typeof body === 'string') {
         response.send(body);
      } else {
         response.send(JSON.parse(body));
      }
    };
    
    FCServer.emit('request',inComimgMessage, serverResponse);
  } catch (e) {
    console.log(e);
    response.send(JSON.stringify({ request, response, context, e }));
  } 
};

结束!明天继续研究


二更,数据接入。

在函数计算中,获取 http 请求的 body 信息需要使用 getRawBody 方法,通过其回调函数我们可以得到 body 信息,因此我们需要在 getRawBody 来触发 request 事件。

    getRawBody(request, function (err, body) {
      if (request.method === 'POST') {
        inComimgMessage.body = JSON.parse(decodeURIComponent(body.toString()));
      }
      FCServer.emit('request', inComimgMessage, serverResponse);
    });

参考链接:

阿里云函数计算 HTTP 触发器

知其然的使用 vuex

博客停更了好一阵子,我又有写一些东西的必要了。

Vuex 是什么?

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

Vuex 该如何使用,详见文档:https://vuex.vuejs.org/zh-cn/intro.html

本文完。

对于一个 Vue 初学者而言状态管理是一个比较晦涩难懂的东西。

以下是我自己的对 Vuex 学习的一些见解。

  1. 什么是组件状态?
    在 Vue 的组件化开发中, 组件状态就是组件内部的数据,包括但不限于组件的 data,以及根据 data 动态响应而产生的 computed 值。
  2. 为什么要管理组件的状态?
    Vue 中父组件可以通过 props 向子组件传递包括自身状态在内的数据。这样一来子组件就能通过 props 获得父组件的状态,从而达到状态共享的效果。这样的开发方式在功能简单,没有拓展需要的情况下不会有多大的问题。但是在开发功能复杂,有拓展需求的时候弊端就会显现。props 只能满足父组件与子组件之间的状态共享, 但在兄弟组件,多重嵌套的组件之间基于 props 的状态共享就会状态不可追踪。组件状态的管就十分有必要了。
  3. 组件的状态如何管理?
    正如 Vuex 文档中所介绍的 “Vue 计数应用” 例子,他介绍了一个单向数据流的概念。同时也指出了这个单向数据流的缺点所在:①多个视图依赖于同一状态,②来自不同视图的行为需要变更同一状态。 会打破这个单项数据流的可靠性。
    为了解决这些问题:
    借鉴 Flux、Rudux 和 The Element Architecture的思想,将组件的共享状态抽取出来,以一个全局单例的模式来管理。在这种模式下,组件树构成了一个巨大的视图,不管在树的哪个位置,任何组件都能获取状态或者触发行为。另外通过定义和隔离状态中的各种盖帘并强制遵守一定的规则,我们的代码将变得更加结构化且易维护。结合 Vue.js 的的数据响应机制达到高效的状态更新效果。

知其然的使用 Vuex

我们可以将 Vuex 单例当做一个可以通过 this.$store (为什么这么用,请看这里)来访问统一管理的状态,触发改变状态的方法

store 的结构

{
  state:{}
  modules:{}
  mutations:{}
  actions:{}
  getters:{}
}

获取特定模块的state,this.$store.state.modulesName.key;

modules:用于区分各个模块的状态,方便不同页面(业务)的状态的管理。

提交一个改变 state 的同步方法(mutations)  this.$store.commit('functionName',args)纯函数相同的输入 state 的改变相同。

提交一个改变 state 的异步方法(actions)  this.$store.dispatch('functionName',args)一般用于做一些异步操作,如网络请求数据,在请求完成之后调用 mutation 方法实现对 state 的修改。

getters 用于对重复的 state 派生操作,做一个统一的处理。使用方法 this.$store.getters.getterName

本文完。

参考链接:

  1. Vuex 使用文档:https://vuex.vuejs.org/zh-cn/intro.html
  2. Vuex源码解析:https://zhuanlan.zhihu.com/p/30560457
  3. 纯函数:https://zh.wikipedia.org/wiki/%E7%BA%AF%E5%87%BD%E6%95%B0

Hello Dva

Hello Dva

dvajs github地址:Dvajs

刚接触 React 的时候接触过这个框架。那个时候听同事推荐蚂蚁金服的 Ant Design , 还尝试的做了一个基于 Ant Design 的博客后台,半成品。

一晃就是半年,最近公司有个需求需要用到 React 。我才有机会再次看看这方面的知识。之前也曾想过认认真真用 React 搞点事情,但是功能区块的设计,就让人够伤脑筋,所以迟迟没有什么动力。这个问题在七月初,有了转机。

为什么选择Dva?

Dva:基于 redux、redux-saga 和 react-router@2.x 的轻量级前端框架。

  1. 易学易用:仅有 6 个 api,对 redux 用户尤其友好
  2. elm 概念:通过 reducers, effectssubscriptions 组织 model
  3. 支持 mobile 和 react-native:跨平台 (react-native 例子)
  4. 支持 HMR:目前基于 babel-plugin-dva-hmr 支持 components、routes 和 models 的 HMR
  5. 动态加载 Model 和路由:按需加载加快访问速度 (例子)
  6. 插件机制:比如 dva-loading 可以自动处理 loading 状态,不用一遍遍地写 showLoading 和 hideLoading
  7. 完善的语法分析库 dva-astdva-cli 基于此实现了智能创建 model, router 等
  8. 支持 TypeScript:通过 d.ts (例子)

以上是 Dvajs 的 github 上的优点自述。其中1、2、4、5、7 是我选择Dva的原因。

然后我结合Dva 和 material ui 做了一个简单的界面。感觉不错。但是没有时间来完善。dva练手

就聊聊当下

就聊聊当下。从去年10月份开始,然后就是我的同学。他带我去参加各种校招,但是这个过程啦。说什么都没有得到,也不是没有,只是感觉我根本没有去用心去参加这个校照只是去走过场而已,并且当时我的能力参加一些公司的校招肯定是过不了啦。但是现在已经距离那个时候已经过去了半年去。具体应该有半年多。

这半年来都干了些什么

期间我在一间一家很小了,不知道干什么的公司干了半个月,最后。被开除了但从那开始的话我已经认识到了一个事情就是,除非你出个牛逼,不然的话让人任人宰割会是任人摆布的那种,而是必须了,也应该是步入社会应该要学那些东西。并且这次期间租房子这方面也被别人骗过很多钱,你就说现在仔细算的话。我现在工作这么几个月转了工资大概大概,有很大一部分都是交给房租了。好在我在被开除了不到一个星期的时间就找到二份工作丢份工作。第二份工作,待遇怎么说也比第一份好很多吧,比起我的那些同学还是算中等偏上一点点。

在新的公司这边学了很多东西。但是主要都是侧重后端的开发。这虽然与我当初离开学校的时候打算做一个前端的意愿有一点点偏差,但是其实也并没有偏差到哪里去,因为做PHP全全栈开发也是一种对自己的锻炼嘛。学更多的东西,才有更多的资本。技多不压身。现在我应该能凭自己的能力了。能做一些比较小的项目。在很多方面也可以独当一面。

最近又在忙些什么事情

当然是在忙毕业的事情,主要就是毕业论文其实辩论文这个内容还些东西都是比较好做的,因为这些毕竟我都懂嘛,然后实现一个东西,或是写一些内容的话还是很容易的,不过嘞,学校就是一个很变态的格式也不算是变态吧,这东西不是做不做的到,而是有些人都不知道自己在想什么,我把那个格式的标准一直在变来变去了,我现在都已经在工作了,然后他说我格式不通过让我去再去改。反正我是不能理解这种做法了。那种只求形式,而不务实的做法。我觉得这种做法,还不如把大家早点放了算了,何必呢?浪费大家的时间。不过以后拿了毕业证的话就能转正了,毕业之后转正,这一点还是比较好了,毕竟就生活就不用过了,那么近窘迫了。嗯,等转正的做,我想去换一个住的地方。

接下来的这半年准备做什么,怎么做

前端这方面的开发,就是刚出学校的时候,第一份工作,学的那些React的知识,现在可能忘了一点,但是现在如果说给我一点时间去捡起来的话,也是可以很快捡起来的,我现在想做的那个目标就是根据现在所学的那些前段和后段的知识能够做一个前后端分离的小系统。

现在还是以公司这边事情为主公司有什么需求的话哦尽自己最大的可能去完成。因为这个不仅是关系的做事态度,也为后期去挑战更多的任务。打下一个基础嗯,现在大概就是这个样子。我感觉后期的话还是有很多事情可以做的。至于出去外面的话还是年底以后再考虑这个事情。

本文章是由搜狗语音输入法完成的。😘

在 CentOS 7 上搭建 PHP 5.6 + MySQL 5.7 + Nginx 的 Web 环境

在 CentOS 7 上搭建 PHP 5.6 + MySQL 5.7 + Nginx 的 Web 环境

LNMP环境搭建

写在前面

这类教程文章在谷歌上一搜就有一大片,这大概就是我写这篇文章的目的。同时也总结在这一过程中所学到的一些方法和感悟。

1.服务器环境简述

在这里我所用的服务器环境大概如下:

Key Value
服务商 阿里云
服务器类型 ECS
CPU 1G
RAM 1G
带宽 1M
系统 CentOS 7.2

2.软件安装过程

CentOS 中安装软件当然要用到 yum 指令,我们在使用yum指令的过程有些问题必须要注意。以我为例,在我的主机上直接执行yum install mysql安装后的MySQL 版本为5.5,直接执行yum install php安装后的PHP版本为5.4.这显然不是我想要的。因此有必要切换最新的版本的源。

安装nginx

  1. 建立nginx仓库;
rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
  1. 下载并安装nginx;
yum install nginx
  1. 启动nginx;
systemctl start nginx.service
  1. 测试结果;
    通过浏览器访问服务器地址,可以看到nginx的欢迎页面

安装PHP

  1. 配置yum
rpm -Uvh http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
  1. remi 源默认并没有启用,可以通过修改 repo 文件来启用它。
vim /etc/yum.repos.d/remi.repo

[remi]
......
enabled=1
[remi-php56]
......
enabled=1
  1. 安装PHP以及php-fpm
yum install php
yum install php-fpm
  1. 检查PHP是否安装成功
php --version
  1. 配置PHP.ini
vim /etc/php.ini

按照实际需要来配置,我只简单的配置了时区。

  1. 配置php-fpm
vim /etc/php-fpm.d/www.conf

;修改以下内容
; 配置php所属用户
user = nginx
group = nginx

listen.owner = nginx
listen.group = nginx

// 注意此处需要和文件目录的用户相同

; 通过sock方式通信
listen = /var/run/php-fpm/php-fpm.sock 
;注意,在nginx的配置文件中需要将把php解析地址指向到上面的目录
  1. 启动PHP
systemctl start php-fpm

安装MySQL5.7

  1. 配置yum源
rpm -Uvh http://repo.mysql.com/mysql57-community-release-el7.rpm
  1. 安装MySQL
yum install mysql-community-server
  1. 启动MySQL
systemctl start mysql
  1. 登陆MySQL并修改密码

可以在MySQL的log文件中查找的初始密码,及时修改密码。

配置nginx的配置文件

server {
    listen 80;
    server_name blog.kuoruan.com;

    root /path;
    index index.html index.htm index.php;

    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
        # fastcgi_pass 127.0.0.1:9000;
        fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
        #以上路径指向php-fpm.sock路径
    }
}

完成配置之后重启nginx,至此所有任务都已经完成。

总结

在安装的过程中,并非是一帆风顺,遇到了很多的问题,比如MySQL 的 mysql.sock 文件找不到导致的无法登陆数据库。nginx的配置文件错误导致的PHP文件没有被php-fpm解析。

因此我也学到了很多经验,比如通过查看log文件来分析问题出现的原因,使用Google查找解决问题的方法。

相关链接

Hello 2017

Hello 2017

2017 年已经到来,祝鸡年大吉。

总结2016

回首过去的一年,变化超级大。年初我定下一些年度目标:《站在2016的路口》,在年中的时候已经做了部分总结:《凌晨适合总结》。

当初定下的目标,有些在年中就已经完成了大半,有些在上半年还在跟进但是下半年却没有继续跟进了。还有些目标现在还在努力。

  • PHP 学习,上半年基础入门,但是下半年因为工作的原因暂缓了学习进度。不久之后又会因为工作原因继续学习PHP,为 web 全栈开发打下基础。
  • 前端学习,已经基本有现代前端开发的意识了。基本了解 ReactJs 的使用方法和原理,后期也会尽量将这部分知识用于实际开发中。
  • 驾照,GET
  • 体重控制在120斤左右 
  • 实习期间经济独立,不仅没有独立,还欠了一大笔债。 X
  • 实习期间攒钱买Macbook Pro,这个已经完成,这也是导致我欠了一屁股债的重要原因。  X

从2016年6月10日到今天的这一段时间,起起落落的过的也十分精彩。首先是有惊无险的拿到了驾照。开学之后还辗转于光谷和学校之间参加各种校园招聘,在线笔试,虽然最终都没有结果。网上到处投简历,然后意料之中的找到了一些机会。有那么几天甚至还纠结去哪工作,最后得到了一个结论,有时候你以为你有很多选择,其实你根本没得选。在十一月中旬,在定下了工作地点之后然后搬出学校,十二月初却被开除。在租的房子里迷糊了一个星期之后幸运的又找到了现在的工作。唯一的不同是,十二月的下半月每天早上挤公交出门,晚上挤公交回来。有好几次回家之后就累的不行。时不时地还能骑车上下班锻炼锻炼,生活也过的充实了很多。

谈谈现状

现在每天白天都有事做,晚上回到租房地也没有精力做别的事情。在做完手头的项目之后,公司打算让我继续向全栈更加的深入的学习。PHP 学习再次提上我的学习日程。这段时间和 Lazy Boy 时常也有一些交流,交流中学到了很多新的东西,也巩固了之前的知识。还有一个学长对我的帮助也很大。在此要感谢他们的帮助。

再定一些小目标

  • 坚持锻炼,坚持早睡早起。
  • 学习 PHP 。
  • 巩固前端。
  • 学会说话,学习做人。
  • 经济独立,
  • 多读书。

学习是人生的主旋律,2017更上一层楼!

 

 

 

开始了新的生活

开始了新的生活

十一月十六号正式上班,同时开启了我的一段新的生活轨迹。之前的一切找工作的努力都没有白费,毕竟凭借自己的能力找到了我意向的工作。人们都说能以自己喜欢的事情做为自己的工作是一件很棒的事情。

一个人在武汉开始了“汉飘”,在这边生活的事情什么都要考虑,我这个新手面对生活的琐事非常的措手不及。我比较幸运,不用很早起床堵早高峰,也不用堵晚高峰。因此我有更多的时间睡觉吃饭“学习”。

生活不易,时刻珍惜!