Write the Code. Change the World.

4月 24

之所以总结是因为最近也是在看css方面,让我迷惑的是有很多文章 关于布局名词都没有听说过,工作中也很少用。但是我们要与时俱进,叫的多了,它就成为正式名词了。比如 ‘双飞翼 ‘圣杯’??并且我还发现我几乎看了好多文章,他们在从大的角度总结时候,几乎很少有相同,分类角度不尽相同。其实这也没关系,本来就没有一个统一标准,但是还是希望有个相对能够理解 概括角度看css布局。

我们从css发展到现在大类可以归纳为以下几种,你了解的实现方法可能就是以下方式中的具体实现:

  • 静态布局
  • 自适应布局
  • 流式布局(又别名 百分比布局 %)
  • 响应式布局:媒体查询
  • 弹性布局 (rem/em flex布局)
    继续阅读
4月 23

用 ant design pro, 就逃不开 umi,现在更是到 umi3 了。

Umi 2 发布已经是一年半之前的事了,在这段时间里,我们发现之前的架构正逐渐不能满足业务飞速发展的需要,于是我们重写了一遍 Umi。经过几个月的 “007 ” 研发,Umi 3 在今天正式和大家见面了,并调整 slogan 为“插件化的企业级前端应用框架”。

Umi 是什么?

有些朋友可能还不太了解 Umi。

Umi 是蚂蚁金服的底层前端框架,已直接或间接地服务了 3000+ 应用,包括 java、node、H5 无线、离线(Hybrid)应用、纯前端 assets 应用、CMS 应用等。他已经很好地服务了我们的内部用户,同时希望他也能服务好外部用户。

它包含以下特性:

  • 🎉 可扩展,完整的生命周期,插件化,支持插件和插件集
  • 📦 开箱即用,内置路由、构建、部署、测试等,仅需一个依赖即可上手
  • 🐠 企业级,经蚂蚁内部 3000+ 项目以及阿里、优酷、网易、飞猪、口碑等公司项目的验证
  • 🚀 大量自研,微前端、组件打包、文档工具、请求库、hooks 库、数据流等
  • 🌴 完备路由,支持配置式路由和约定式路由,同时保持功能的完备性
  • 🚄 面向未来,一直在尝试新技术的探索,dll 提速、modern mode、webpack@5、自动化化 external、bundler less 等
    继续阅读
4月 16

在项目开发迭代中,会经常建立 git 分支。用完分支经常会删掉。可是删掉的分支,还是会显示在

git branch -r git branch -a 下,这样很难受。怎么办呢。这样干。

# 删除本地分支
git branch -d xxxx

# 查看remote地址,远程分支,还有本地分支与之相对应关系等信息
# 会提示哪些分支已经删除了,需要处理的命令 git remote prune
git remote show origin

# 清理
git remote prune origin 

git remote prune 命令可以删除本地版本库上那些失效的远程追踪分支,具体用法是,假如你的远程版本库名是 origin,则使用如下命令先查看哪些分支需要清理:

git remote prune origin --dry-run

可以看到, origin/xxx 的远程分支已经失效了,将会被清理。再执行 git remote prune origin 就可以清理掉已经失效的远程分支了。

参考

https://www.jianshu.com/p/884ff6252be5

4月 13

npm start 的时候,可能会遇到 Something is already running on port 8000. 这样的问题。要不关掉占用 8080 端口的进程,要不使用别的端口来运行 npm server 。

win 下关闭 8080 端口,可以直接使用任务管理器。建议还是用其他端口比较好,可能 8080 端口的进程刚好是自己需要的。

# 使用 8090 端口来启动进程
port=8090 npm start
4月 10

官网文档:https://pro.ant.design/docs/i18n-cn

使用

  1. 先配置。
可以配置在 src/locales/ 中,也可以配置在各自的组件目录中。
比如,新建了一个模块 TestForm, locales 就可以放在这里边。个人觉得,各个模块的 locales 放在各自的目录下表好。包括 model service 这些。

# locales/zh-CN.ts
export default {
    'login.formlogin.login': '登录',
    'login.formlogin.register': '注册',
    'login.formlogin.account': '账号',
    'login.formlogin.account-placeholder': '请输入账号',
}  
# locales/zh-TW.ts
export default {
    'login.formlogin.login': '登錄',
    'login.formlogin.register': '註冊',
    'login.formlogin.account': '賬號',
    'login.formlogin.account-placeholder': '请输入賬號',
}
  1. 再使用。
# 使用 FormattedMessage 或 使用 formatMessage 

import { FormattedMessage, formatMessage } from "umi";

<Form.Item label={<FormattedMessage 
id="login.formlogin.account" />} 
rules={[{ required: true, message: formatMessage({id:'login.formlogin.account-placeholder'}) }]}>
    <Input placeholder={formatMessage({id:'login.formlogin.account-placeholde'})}/>
</Form.Item>

不过,使用 formatMessage 的时候,会报下边的警告。

Warning: Using this API will cause automatic refresh when switching languages, please use useIntl or injectIntl.

使用此 api 会造成切换语言的时候无法自动刷新,请使用 useIntl 或 injectIntl。

可是对 placeholder 如果不使用 formatMessage 又不行。真为难。

下边一个简单的 login 的列子

不喜欢官方的登录注册页,不仅繁琐,还不好看。

index.tsx

import { connect } from 'umi';
import { ConnectState } from '@/models/connect';

import FormLogin from './FormLogin';

const Login = () => {
    const onLoginSubmit = (value:any) => {
        console.log(value);
    }

    return (
        <FormLogin onLoginSubmit={onLoginSubmit} ></FormLogin>
    );
};


export default connect(({ login, loading }: ConnectState) => ({
    userLogin: login,
    submitting: loading.effects['login/login'],
}))(Login);

locales/zh-CN.ts

export default {
    'login.formlogin.login': '登录',
    'login.formlogin.register': '注册',
    'login.formlogin.account': '账号',
    'login.formlogin.account-placeholder': '请输入账号',
    'login.formlogin.account-rule': '请输入正确的账号格式(手机号码)',
    'login.formlogin.password': '密码',
    'login.formlogin.password-placeholder': '请输入密码',
    'login.formlogin.password-rule': '密码不能为空',
    'login.formlogin.remember-password': '记住密码',
    'login.formlogin.forget-password': '忘记密码',
    'login.formlogin.none-account': '如果没有账号,请',
}

FormLogin/index.tsx

import React from "react";
import styles from "./index.less";
import { FormattedMessage, formatMessage } from "umi";
import { Card, Form, Input, Button, Checkbox } from "antd";

const itemLayout = {
  labelCol: {
    xs: { span: 24 },
    sm: { span: 6 },
  },
  wrapperCol: {
    xs: { span: 24 },
    sm: { span: 12 },
  },
};

const tailLayout = {
  wrapperCol: {
    xs: { span: 24 },
    sm: { offset:6, span: 12 }
  },
};

const NormalLoginForm = (props:any) => {
  return (
    <Card bordered={false} title={<FormattedMessage id='login.formlogin.login' />} style={{ width: 720 }}>
      <Form
        {...itemLayout}
        initialValues={{ remember: true }}
        onFinish={props.onLoginSubmit}
      >
        <Form.Item name="account" label={<FormattedMessage id='login.formlogin.account' />} rules={[{ required: true, pattern: /^1[3456789]\d{9}$/ , message: <FormattedMessage id='login.formlogin.account-rule' /> }]}>
          <Input placeholder={ formatMessage({ id: 'login.formlogin.account-placeholder' })} />
        </Form.Item>

        <Form.Item name="password" label={<FormattedMessage id="login.formlogin.password" />} rules={[{ required: true, message: <FormattedMessage id='login.formlogin.password-rule' /> }]}>
          <Input.Password placeholder={formatMessage({ id: 'login.formlogin.password-placeholder' })} />
        </Form.Item>

        <Form.Item {...tailLayout} name="remember" valuePropName="checked">
          <Checkbox>
            <FormattedMessage id="login.formlogin.remember-password" />
          </Checkbox>
        </Form.Item>

        <Form.Item {...tailLayout}>
          <Button type="primary" htmlType="submit">
            <FormattedMessage id='login.formlogin.login' />
          </Button>

          <Button type="link" href="https://baidu.com" target="_blank">
            <FormattedMessage id='login.formlogin.forget-password' />
          </Button>
        </Form.Item>

        <Form.Item {...tailLayout} className="other-way">
            <span><FormattedMessage id='login.formlogin.none-account' /></span>
            <Button type="link" href="https://baidu.com" size="small">
              <FormattedMessage id='login.formlogin.register' />
            </Button>
        </Form.Item>
      </Form>
    </Card>
  );
};

export default (props:any) => (
  <div className={styles.container}>
    <div id="form-login">
      <NormalLoginForm onLoginSubmit={props.onLoginSubmit} />
    </div>
  </div>
);

FormLogin/index.less

.container {
  height: 100%;

  :global {
    #form-login {
      display: flex;
      flex-direction: row;
      justify-content: center;
      align-items: center;
      width: 100%;
      height: 100%;
      background-color: rgba(255,0,0,0.1);

      .login-form {
        width: 100%;
        max-width: 720px;
      }
    }

    .other-way {
      margin-top: 20px;
      margin-bottom: 0;
    }
  }
}

到目前为止,service,model 都是空的。要实现登录注册的功能,就得完善它们。

4月 06

nginx 新增模块缺失,

nginx: [emerg] unknown directive “more_clear_headers”

https://blog.csdn.net/chunyuan314/article/details/81737303

安装

https://github.com/openresty/headers-more-nginx-module

cd /usr/local/src

wget https://github.com/openresty/headers-more-nginx-module/archive/v0.33.tar.gz

tar -xzvf v0.33.tar.gz

cd headers-more-nginx-module-0.33

新增模块

# 先准备曾经的配置,找到 configure arguments 后边的配置。

nginx -V

# 找到曾经的包文件
cd /usr /local/src/nginx 

# 再配置后追加 add-module 指向headers-more-nginx-module-0.33

./configure --user=nginx --group=nginx --prefix=/alidata/service/nginx --pid-path=/alidata/service/nginx/run/nginx.pid --with-http_stub_status_module --with-threads --with-file-aio --with-pcre-jit --with-http_ssl_module --with-http_v2_module --with-http_gzip_static_module --with-http_sub_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_realip_module --with-http_addition_module --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --with-stream_realip_module --with-http_slice_module --with-pcre --with-openssl=/usr/local/src/base/1-openssl/openssl-1.1.1f --with-openssl-opt=enable-tls1_3 --add-module=/opt/ngx_brotli/ --add-module=/usr/local/src/nginx/headers-more-nginx-module-0.33

# 再make (千万不要 make install)

make

# 然后复制 nginx 文件覆盖之前安装包里的 nginx 文件,覆盖安装之前 ,先备份一个
nginx stop

cp /alidata/service/nginx/sbin/nginx  /alidata/service/nginx/sbin/nginx.back
cp -r objs/nginx /alidata/service/nginx/sbin/nginx

# 启动
/alidata/service/nginx/sbin/nginx

参考

https://segmentfault.com/a/1190000018418253?utm_source=coffeephp.com

4月 06

官网: https://redis.io/

可参考:
https://blog.vini123.com/107

###

wget http://download.redis.io/releases/redis-5.0.8.tar.gz

tar -xzvf  redis-5.0.8.tar.gz

cd redis-5.0.8

# 安装依赖
yum install tcl

# 继续

make

make test

# 没有问题就安装
make install PREFIX=/alidata/service/redis 

# 配置并启动redis
mkdir /alidata/service/redis/etc/

cp  /usr/local/src/redis/redis-5.0.8/redis.conf /alidata/service/redis/etc/

vim /alidata/service/redis/etc/redis.conf   #编辑redis.conf

daemonize yes   #将此行对应的no改成yes。

# 启动
/alidata/service/redis/bin/redis-server /alidata/service/redis/etc/redis.conf

# 连接 redis
/alidata/service/redis/bin/redis-cli

配置开机自启动

# 开机自启动

cp /usr/local/src/redis/redis-5.0.8/utils/redis_init_script /etc/init.d/redis

vim /etc/init.d/redis

# 然后修改EXEC、REDIS_CLI、CONF对应的值。分别对应服务端位置、客户端位置、配置文件位置。保存,退出。修改后的脚本如下;
# 修改

#!/bin/sh
#
# Simple Redis init.d script conceived to work on Linux systems
# as it does use of the /proc filesystem.

### BEGIN INIT INFO
# Provides:     redis_6379
# Default-Start:        2 3 4 5
# Default-Stop:         0 1 6
# Short-Description:    Redis data structure server
# Description:          Redis data structure server. See https://redis.io
### END INIT INFO

REDISPORT=6379
EXEC=/alidata/service/redis/bin/redis-server
CLIEXEC=/alidata/service/redis/bin/redis-cli

PIDFILE=/var/run/redis_${REDISPORT}.pid
CONF=/alidata/service/redis/etc/redis.conf

case "$1" in
    start)
        if [ -f $PIDFILE ]
        then
                echo "$PIDFILE exists, process is already running or crashed"
        else
                echo "Starting Redis server..."
                $EXEC $CONF
        fi
        ;;
    stop)
        if [ ! -f $PIDFILE ]
        then
                echo "$PIDFILE does not exist, process is not running"
        else
                PID=$(cat $PIDFILE)
                echo "Stopping ..."
                $CLIEXEC -p $REDISPORT shutdown
                while [ -x /proc/${PID} ]
                do
                    echo "Waiting for Redis to shutdown ..."
                    sleep 1
                done
                echo "Redis stopped"
        fi
        ;;
    *)
        echo "Please use start or stop as first argument"
        ;;
esac

执行权限,并开启服务重启自启动

chmod +x /etc/init.d/redis   #执行权限
chkconfig redis on   #系统服务中启动redis服务
chkconfig --list   #系统服务启动列表
/etc/init.d/redis start   #启动redis

安装 php redis 扩展

cd /usr/local/src

mkdir php-redis

cd php-redis

wget http://pecl.php.net/get/redis-5.2.1.tgz

tar -xizvf redis-5.2.1.tgz

cd redis-5.2.1 

# 编译安装
phpize

./configure 

make && make install

# 配置
vim /alidata/service/php/etc/php.ini

在末尾加上 extension=redis.so 保存。

# 重启
/etc/init.d/php-fpm restart

# 查看
php -m | grep redis