exponent

exponent 查看完整档案

杭州编辑  |  填写毕业院校  |  填写所在公司/组织编辑
编辑
_ | |__ _ _ __ _ | '_ \| | | |/ _` | | |_) | |_| | (_| | |_.__/ \__,_|\__, | |___/ 个人简介什么都没有

个人动态

exponent 赞了回答 · 2月26日

解决PC端项目如何适配不同的尺寸的电脑?

image.png

在调研部分网站之后,尤其是toB/toP类网站,网站均以安全区域(1200x/1190px)显示为主。而对于服务商提供的服务/产品/维护等相关前台/后台网站界面则全屏显示,通常以左侧菜单栏,右侧主体显示内容等形式

再回到题干,结合你实际页面展示内容情况,对于不同尺寸[分辨率]做适配,可考虑采取居中固定安全区域双边留白,尺寸结合实际适配尺寸可做适应调整,也可以做响应式布局,根据媒体查询来界定不同分辨率临界值和区段的显示方式,也可以使用vw/vh等单位,做动态变换

关注 3 回答 3

exponent 收藏了文章 · 2月3日

史上最清晰易懂的babel配置解析

标题党了哈哈哈~~~

原文地址

相信很多人和笔者从前一样,babel的配置都是从网上复制黏贴或者使用现成的脚手架,虽然这能够工作但还是希望大家能够知其所以然,因此本文将对babel(babel@7)的配置做一次较为完整的梳理。

语法和api

es6增加的内容可以分为语法和api两部分,搞清楚这点很重要,新语法比如箭头函数、解构等:

const fn = () => {}

const arr2 = [...arr1]

新的api比如Map、Promise等:

const m = new Map()

const p = new Promise(() => {})

@babel/core

@babel/core,看名字就知道这是babel的核心,没他不行,所以首先安装这个包

npm install @babel/core

它的作用就是根据我们的配置文件转换代码,配置文件通常为.babelrc(静态文件)或者babel.config.js(可编程),这里以.babelrc为例,在项目的根目录下创建一个空文件命名为.babelrc,然后创建一个js文件(test.js)测试用:

/* test.js */
const fn = () => {}

这里我们安装下@babel/cli以便能够在命令行使用babel

npm install @babel/cli

安装完成后执行babel编译,命令行输入

npx babel test.js --watch --out-file test-compiled.js

结果发现test-compiled.js的内容依然是es6的箭头函数,不用着急,我们的.babelrc还没有写配置呢

Plugins和Presets

Now, out of the box Babel doesn't do anything. It basically acts like const babel = code => code; by parsing the code and then generating the same code back out again. You will need to add plugins for Babel to do anything.

上面是babel官网的一段话,可以理解为babel是基于插件架构的,假如你什么插件也不提供,那么babel什么也不会做,即你输入什么输出的依然是什么。那么我们现在想要把剪头函数转换为es5函数只需要提供一个箭头函数插件就可以了:

/* .babelrc */
{
  "plugins": ["@babel/plugin-transform-arrow-functions"]    
}

转换后的test-compiled.js为:

/* test.js */
const fn = () => {}

/* test-compiled.js */
const fn = function () {}

那我想使用es6的解构语法怎么办?很简单,添加解构插件就行了:

/* .babelrc */
{
  "plugins": [
    "@babel/plugin-transform-arrow-functions",
    "@babel/plugin-transform-destructuring"
  ]    
}

问题是有那么多的语法需要转换,一个个的添加插件也太麻烦了,幸好babel提供了presets,他可以理解为插件的集合,省去了我们一个个引入插件的麻烦,官方提供了很多presets,比如preset-env(处理es6+规范语法的插件集合)、preset-stage(处理尚处在提案语法的插件集合)、preset-react(处理react语法的插件集合)等,这里我们主要介绍下preset-env

/* .babelrc */
{
  "presets": ["@babel/preset-env"]    
}

preset-env

@babel/preset-env is a smart preset that allows you to use the latest JavaScript without needing to micromanage which syntax transforms (and optionally, browser polyfills) are needed by your target environment(s).

以上是babel官网对preset-env的介绍,大致意思是说preset-env可以让你使用es6的语法去写代码,并且只转换需要转换的代码。默认情况下preset-env什么都不需要配置,此时他转换所有es6+的代码,然而我们可以提供一个targets配置项指定运行环境:

/* .babelrc */
{
  "presets": [
    ["@babel/preset-env", {
      "targets": "ie >= 8"
    }]
  ]    
}

此时只有ie8以上版本浏览器不支持的语法才会被转换,查看我们的test-compiled.js文件发现一切都很好:

/* test.js */
const fn = () => {}
const arr1 = [1, 2, 3]
const arr2 = [...arr1]


/* test-compiled.js */
var fn = function fn() {};
var arr1 = [1, 2, 3];
var arr2 = [].concat(arr1);

@babel/polyfill

现在我们稍微改一下test.js:

/* test.js */
const fn = () => {}
new Promise(() => {})


/* test-compiled.js */
var fn = function fn() {};
new Promise(function () {});

我们发现Promise并没有被转换,什么!ie8还支持Promise?那是不可能的...。还记得本文开头提到es6+规范增加的内容包括新的语法和新的api,新增的语法是可以用babel来transform的,但是新的api只能被polyfill,因此需要我们安装@babel/polyfill,再简单的修改下test.js如下:

/* test.js */
import '@babel/polyfill'

const fn = () => {}
new Promise(() => {})


/* test-compiled.js */
import '@babel/polyfill';

var fn = function fn() {};
new Promise(function () {});

现在代码可以完美的运行在ie8的环境了,但是还存在一个问题:@babel/polyfill这个包的体积太大了,我们只需要Promise就够了,假如能够按需polyfill就好了。真巧,preset-env刚好提供了这个功能:

/* .babelrc */
{
  "presets": [
    ["@babel/preset-env", {
      "modules": false,
      "useBuiltIns": "entry",
      "targets": "ie >= 8"
    }]
  ]    
}

我们只需给preset-env添加一个useBuiltIns配置项即可,值可以是entryusage,假如是entry,会在入口处把所有ie8以上浏览器不支持api的polyfill引入进来,如下:

/* test.js */
import '@babel/polyfill'

const fn = () => {}
new Promise(() => {})


/* test-compiled.js */
import "core-js/modules/es6.array.copy-within";
import "core-js/modules/es6.array.every";
import "core-js/modules/es6.array.fill";
...   //省略若干引入
import "core-js/modules/web.immediate";
import "core-js/modules/web.dom.iterable";
import "regenerator-runtime/runtime";

var fn = function fn() {};
new Promise(function () {});

细心的你会发现transform后,import '@babel/polyfill'消失了,反倒是多了一堆import 'core-js/...'的内容,事实上,@babel/polyfill这个包本身是没有内容的,它依赖于core-jsregenerator-runtime这两个包,这两个包提供了es6+规范的运行时环境。因此当我们不需要按需polyfill时直接引入@babel-polyfill就行了,它会把core-jsregenerator-runtime全部导入,当我们需要按需polyfill时只需配置下useBuiltIns就行了,它会根据目标环境自动按需引入core-jsregenerator-runtime

前面还提到useBuiltIns的值还可以是usage,其功能更为强大,它会扫描你的代码,只有你的代码用到了哪个新的api,它才会引入相应的polyfill:

/* .babelrc */
{
  "presets": [
    ["@babel/preset-env", {
      "modules": false,
      "useBuiltIns": "usage",
      "targets": "ie >= 8"
    }]
  ]    
}

transform后的test-compiled.js相应的会简化很多:

/* test.js */
const fn = () => {}
new Promise(() => {})

/* test-compiled.js */
import "core-js/modules/es6.promise";
import "core-js/modules/es6.object.to-string";

var fn = function fn() {};
new Promise(function () {});

遗憾的是这个功能还处于试验状态,谨慎使用。

事实上假如你是在写一个app的话,以上关于babel的配置差不多已经够了,你可能需要添加一些特定用途的PluginPreset,比如react项目你需要在presets添加@babel/preset-react,假如你想使用动态导入功能你需要在plugins添加@babel/plugin-syntax-dynamic-import等等,这些不在赘述。假如你是在写一个公共的库或者框架,下面提到的点可能还需要你注意下。

@babel/runtime

有时候语法的转换相对复杂,可能需要一些helper函数,如转换es6的class:

/* test.js */
class Test {}


/* test-compiled.js */
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var Test = function Test() {
  _classCallCheck(this, Test);
};

示例中es6的class需要一个_classCallCheck辅助函数,试想假如我们多个文件中都用到了es6的class,那么每个文件都需要定义一遍_classCallCheck函数,这也是一笔不小的浪费,假如将这些helper函数抽离到一个包中,由所有的文件共同引用则可以减少可观的代码量。而@babel/runtime做的正好是这件事,它提供了各种各样的helper函数,但是我们如何知道该引入哪一个helper函数呢?总不能自己手动引入吧,事实上babel提供了一个@babel/plugin-transform-runtime插件帮我们自动引入helper。我们首先安装@babel/runtime@babel/plugin-transform-runtime

npm install @babel/runtime @babel/plugin-transform-runtime

然后修改babel配置如下:

/* .babelrc */
{
  "presets": [
    ["@babel/preset-env", {
      "modules": false,
      "useBuiltIns": "usage",
      "targets": "ie >= 8"
    }]
  ],
  "plugins": [
    "@babel/plugin-transform-runtime"
  ]  
}

现在我们再来看test-compiled.js文件,里面的_classCallCheck辅助函数已经是从@babel/runtime引入的了:

/* test.js */
class Test {}


/* test-compiled.js */
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";

var Test = function Test() {
  _classCallCheck(this, Test);
};

看到这里你可能会说,这不扯淡嘛!几个helper函数能为我减少多少体积,我才懒得安装插件。事实上@babel/plugin-transform-runtime还有一个更重要的功能,它可以为你的代码创建一个sandboxed environment(沙箱环境),这在你编写一些类库等公共代码的时候尤其重要。

上文我们提到,对于Promise、Map等这些es6+规范的api我们是通过提供polyfill兼容低版本浏览器的,这样做会有一个副作用就是污染了全局变量,假如你是在写一个app还好,但如果你是在写一个公共的类库可能会导致一些问题,你的类库可能会把一些全局的api覆盖掉。幸好@babel/plugin-transform-runtime给我们提供了一个配置项corejs,它可以将这些变量隔离在局部作用域中:

/* .babelrc */

{
  "presets": [
    ["@babel/preset-env", {
      "modules": false,
      "targets": "ie >= 8"
    }]
  ],
  "plugins": [
    ["@babel/plugin-transform-runtime", {
      "corejs": 2
    }]
  ]  
}

注意:这里一定要配置corejs,同时安装@babel/runtime-corejs2,不配置的情况下@babel/plugin-transform-runtime默认是不引入这些polyfill的helper的。corejs的值现阶段一般指定为2,可以近似理解为是@babel/runtime的版本。我们现在再来看下test-compiled.js被转换成了什么:

/* test.js */
class Test {}
new Promise(() => {})


/* test-compiled.js */
import _Promise from "@babel/runtime-corejs2/core-js/promise";
import _classCallCheck from "@babel/runtime-corejs2/helpers/classCallCheck";

var Test = function Test() {
  _classCallCheck(this, Test);
};

new _Promise(function () {});

如我们所愿,已经为Promise的polyfill创建了一个沙箱环境。

最后我们再为test.js稍微添加点内容:

/*  test.js */
class Test {}
new Promise(() => {})

const b = [1, 2, 3].includes(1)


/* test-compiled.js */
import _Promise from "@babel/runtime-corejs2/core-js/promise";
import _classCallCheck from "@babel/runtime-corejs2/helpers/classCallCheck";

var Test = function Test() {
  _classCallCheck(this, Test);
};

new _Promise(function () {});
var b = [1, 2, 3].includes(1);

可以发现,includes方法并没有引入辅助函数,可这明明也是es6里面的api啊。这是因为includes是数组的实例方法,要想polyfill必须修改Array的原型,这样一来就污染了全局环境,因此@babel/plugin-transform-runtime是处理不了这些es6+规范的实例方法的。

tips

以上基本是本文的全部内容了,最后再来个总结和需要注意的地方:

  1. 本文没有提到preset-stage,事实上babel@7已经不推荐使用它了,假如你需要使用尚在提案的语法,请直接添加相应的plugin。
  2. 对于普通项目,可以直接使用preset-env配置polyfill
  3. 对于类库项目,推荐使用@babel/runtime,需要注意一些实例方法的使用
  4. 本文内容是基于babel@7,项目中遇到问题可以尝试更新下babel-loader的版本

...待补充


全文完

查看原文

exponent 回答了问题 · 2020-07-24

支付宝wap支付

notify_url必须是公网可访问的

内网地址和本地地址是没有用的,除非用内网穿透

关注 2 回答 1

exponent 回答了问题 · 2020-07-15

php项目里面 .tags 隐藏文件怎么来的,可以删除吗?

这个.tag目录应该是vim使用ctag插件生成的缓存目录,可以删掉

关注 2 回答 1

exponent 收藏了文章 · 2020-05-29

PHP的ImageMagick使用;

之前写了一个项目需要使用PHP的Imagick类进行图像的操作;个人感觉目前关于Imagick的文档虽然很多,但是比较乱。我会通过一个范例解释Imagick的简单的使用;


(1).创建一个新图片,宽500px,高300px,黑色,格式为png的图片

$img =new Imagick();
$img->newImage(500,300,'black','png')

图片描述

(2).图片的叠加;

假设我们选取范例1中的$img作为背景,这个时候我们把第二张图片叠加到图片上;
选一张马刺gdp组合;

知道图片二的路径假定为$imageSrc="/home/XXXX/spurs.png";

第一步我们实例化这个图片

$imgtwo = new Imagick($imageSrc);

因为是要叠加,就需要把两张图的大小设置一样;
首先要获取第一张图片的大小(ps:这里我们也可以指定大小).

$height=$img->getImageHeight();//获取图片1高度
$width=$img->getImageWidth();//获取图片1宽度

第二步,对图片进行大小调整

$imgtwo->resizeImage($width,$height,Imagick::FILTER_LANCZOS,1);

resizeImage参数说明

bool Imagick::resizeImage ( int $columns , int $rows , int $filter , float $blur [, bool $bestfit = false ] )

参数解释:

  • columns 图片的宽度
  • rows 图片高度
  • filter 过滤器,用于过滤图片,有高斯filte根据情况而定
  • blur blur=1 为虚化, blur =-1 为锐化

第三部,叠加图片

使用compositeImage();

bool Imagick::compositeImage ( Imagick $composite_object , int $composite , int $x , int $y [, int $channel = Imagick::CHANNEL_ALL ] )

参数说明:

  • composite_object :用于合并的图片的Imagick对象
  • composite:合并操作,定义操作常量。 具体请查看 合并操作常量列表
  • x:相对图像顶点左上位置(0,0)的横坐标
  • y:相对图像顶点左上位置(0,0)的纵坐标
  • channel:通过传入一个通道常量,来开启通道模式。为了支持多个通道,可以通过二进制运算的操作来合并多个通道常量。

ps:这里是把图片二覆盖到图片一上

$img->compositeImage($imgtwo,$image->getImageCompose(),0,0)

生成图片如下:
图片描述
最后

  • 1.我们可以直接在网页上查看图片,但是要加一个header信息;
header("Content-Type: image/png");
echo $img;
  • 2.可以把图片在指定目录中生成;
在当前目录下生成img.png
$file="./img.png";
$img->writeImage($file);
这样就会在当前目录下生成图片img.png;

(3).在图片上配置文字

需要使用 ImagickDraw类;

第一步实例化ImagickDraw类:

$draw=new ImagickDraw();

设置字体颜色

$draw->setFillColor(new ImagickPixel('white'));

设置字体大小

$draw->setFontSize('25');

设置字体

$draw->setFont("../fonts/Arial.ttf");

设置字体方向

$draw->setTextAlignment(Imagick::ALIGN_RIGHT);

ps:

  • Imagick::ALIGN_RIGHT 朝右边
  • Imagick::ALIGN_LEFT 左边
  • Imagick::ALIGN_CENTER 中间

设置字体编码格式

$draw->setTextEncoding("utf-8")

画出文字

$draw->annotation(200,200,'GDP');

在底板上画出;

$img->drawImage($draw);

图片描述
NBA历史上最伟大的组合GDP

(4).裁剪图片

这个夏天邓肯退役了,GDP组合解体。我们只能把邓肯去掉

$img->cropImage(300, 300, 0, 20);
  • 第一个参数是图片的宽度
  • 第二个是高度
  • 图片裁剪的x轴位置
  • 图片裁剪Y轴位置
  • 然后我们再把生成一个圆角
$img->roundCorners(60, 60);

就生成了少了邓肯现在马刺,外加一个伦纳德

ps:这里我重新写了文字,变成了GP;

图片描述

查看原文

exponent 回答了问题 · 2020-05-13

docker搭建了PHP和redis环境,但PHP在本机无法连接到redis。

如果php和redis都是容器,那在启动容器的时候可以加一个link参数
启动redis:docker run --name redis -p 6379:6379 -itd redis
启动php:docker run --name php --link redis:redis -itd php

然后在php容器中连接redis

$redis = new Redis();
// 就用redis这个字符串,和--link时设置的字符串一致
$redis->connect('redis', 6379);
$count = $redis->get('count');

--link参数其实就是在php容器的/etc/hosts加了一个redis容器的ip:host映射

关注 1 回答 1

exponent 回答了问题 · 2020-04-24

php 使用crypt和mysql库验证用户名是否已存在时,为什么一直显示“用户名存在”?

??你自己都说了

输入的明明是已经存在的user...

那得到的结果一直显示”用户名存在“不是很正常吗

关注 2 回答 1

exponent 回答了问题 · 2020-04-24

ThinkPHP命令行运行报错PHP Warning: require(./thinkphp/console.php)

报错的意思是没有./thinkphp/console.php这个文件的权限,你需要更改一下这个文件的拥有者或者直接粗暴的改文件权限

直接改文件权限

chmod 777 ./thinkphp/console.php

改文件拥有者

chown root:root ./thinkphp/console.php

关注 2 回答 1

exponent 回答了问题 · 2020-03-31

使用TP5上传超过30M的文件就报错?

错误信息显示你执行了一个null变量的validate方法,并不是文件大小超过限制

关注 3 回答 2

exponent 关注了标签 · 2020-03-20

java

Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的 Java 程序设计语言和 Java 平台(即 JavaSE, JavaEE, JavaME)的总称。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

Java编程语言的风格十分接近 C++ 语言。继承了 C++ 语言面向对象技术的核心,Java舍弃了 C++ 语言中容易引起错误的指針,改以引用取代,同时卸载原 C++ 与原来运算符重载,也卸载多重继承特性,改用接口取代,增加垃圾回收器功能。在 Java SE 1.5 版本中引入了泛型编程、类型安全的枚举、不定长参数和自动装/拆箱特性。太阳微系统对 Java 语言的解释是:“Java编程语言是个简单、面向对象、分布式、解释性、健壮、安全与系统无关、可移植、高性能、多线程和动态的语言”。

版本历史

重要版本号版本代号发布日期
JDK 1.01996 年 1 月 23 日
JDK 1.11997 年 2 月 19 日
J2SE 1.2Playground1998 年 12 月 8 日
J2SE 1.3Kestrel2000 年 5 月 8 日
J2SE 1.4Merlin2002 年 2 月 6 日
J2SE 5.0 (1.5.0)Tiger2004 年 9 月 30 日
Java SE 6Mustang2006 年 11 月 11 日
Java SE 7Dolphin2011 年 7 月 28 日
Java SE 8JSR 3372014 年 3 月 18 日
最新发布的稳定版本:
Java Standard Edition 8 Update 11 (1.8.0_11) - (July 15, 2014)
Java Standard Edition 7 Update 65 (1.7.0_65) - (July 15, 2014)

更详细的版本更新查看 J2SE Code NamesJava version history 维基页面

新手帮助

不知道如何开始写你的第一个 Java 程序?查看 Oracle 的 Java 上手文档

在你遇到问题提问之前,可以先在站内搜索一下关键词,看是否已经存在你想提问的内容。

命名规范

Java 程序应遵循以下的 命名规则,以增加可读性,同时降低偶然误差的概率。遵循这些命名规范,可以让别人更容易理解你的代码。

  • 类型名(类,接口,枚举等)应以大写字母开始,同时大写化后续每个单词的首字母。例如:StringThreadLocaland NullPointerException。这就是著名的帕斯卡命名法。
  • 方法名 应该是驼峰式,即以小写字母开头,同时大写化后续每个单词的首字母。例如:indexOfprintStackTraceinterrupt
  • 字段名 同样是驼峰式,和方法名一样。
  • 常量表达式的名称static final 不可变对象)应该全大写,同时用下划线分隔每个单词。例如:YELLOWDO_NOTHING_ON_CLOSE。这个规范也适用于一个枚举类的值。然而,static final 引用的非不可变对象应该是驼峰式。

Hello World

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

编译并调用:

javac -d . HelloWorld.java
java -cp . HelloWorld

Java 的源代码会被编译成可被 Java 命令执行的中间形式(用于 Java 虚拟机的字节代码指令)。

可用的 IDE

学习资源

常见的问题

下面是一些 SegmentFault 上在 Java 方面经常被人问到的问题:

(待补充)

关注 139161

认证与成就

  • 获得 57 次点赞
  • 获得 9 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 9 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2017-01-15
个人主页被 929 人浏览