Write the Code. Change the World.

9月 06

使用 goframe 遇到的一些情况

  • 因为 laravel 有 artisan,migrate 等工具。无论用 go 的哪个框架(目前至少了解过 gen 和 goframe),都没有类似比价好用的 cli 工具。 goframe 虽然有 gen,但还是没 laravel 的好用,并且没有数据库迁移,seeder。因为 laravel 熟,可以使用 laravel 来写数据迁移和 seeder。用 goframe 来写项目。在使用 gf gen dao 的时候很有用。 再说一下 gf gen dao 也是真好用。

  • 默认的 validate,错误直接以 200 状态码返回。无论什么返回,都会包上一层。这个有点不太好。一般项目,我只关心成功和失败。失败比如 401 无权限,403 拒绝请求,429 请求频率太高等等。有明确的状态吗,用户也好理解,也不用在返回实体部分包裹一层 code data 啥的。

  • 数据库表的认知。在 laravel 项目中,数据库表名都是复数的,个人也感觉复数更容易描述表的意义。 goframe 这边习惯用单数。还有时间字段。laravel 习惯用 created_at,updated_at。而 goframe 这边习惯 create_at 和 update_at。 这些习惯克服一下不是啥难事。

  • gf gen ctrl 的方式可以更方便的去处理路由(使得整个项目规范起来,命名,调用等等)。laravel 新建路由组,比如 api,比如 web,比如 console 等等。通过 gf gen ctrl 以及 goframe 的路由,也能方便轻松实现。

阅读全文 >>

9月 05

在 Go 1.5 及后续版本中,可以通过创建 internal 代码包让一些程序实体仅仅能被当前模块中的其他代码引用。这是第三种访问权限:模块级私有。

  • 导出路径包含internal关键字的包,只允许internal的父级目录及父级目录的子包导入,其它包无法导入。

阅读全文 >>

9月 05

https://github.com/danceyoung/paper-code/blob/master/package-oriented-design/packageorienteddesign.md

本篇内容主要讲解golang项目的面向包设计准则和基础的架构分层。

信息来自原文

内容进行翻译、加工、整合及结合个人的实践经验,并附有一个真实的例子来解释本篇内容。

当然你也可以直接阅读英文原文。

当然高手如云,只是懒得写罢了。

百年太久,只争朝夕,不负韶华,不枉少年,来日怎方长。

阅读全文 >>

8月 28

el-tooltip 和 el-popover 嵌套使用的时候,可能会遇到你意向不到的情况。怎么处理呢。

  • el-tooltip 嵌套 el-popover
  • 在嵌套 el-popover 的时候,加一层 div

仅此而已,就会出现你想看到的效果了。

<el-tooltip content="我不知道风是往哪一个方向吹" placement="top">
        <div>
              <el-popover placement="bottom-start" trigger="click">
              </el-popover>
        </div>
</el-tooltip>

就这样咯。

阅读全文 >>

8月 24

前端项目,打包后,运行起来就可能会出现一些提示。描述语是 Violation 。看着不舒服,还是要解决的。列举一下

[Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event.

出现报错的原因:

Chrome51 版本以后,Chrome 增加了新的事件捕获机制-Passive Event Listeners;

Passive Event Listeners:被动事件侦听器是 DOM 规范中的一项新功能,它使开发人员能够通过消除滚动来阻止触摸和滚轮事件侦听器来选择加入以获得更好的滚动性能。

开发人员可以使用 {passive: true} 来设置监听器后内部不会调用 preventDefault() 来阻止默认滑动行为,Chrome 浏览器称这类型的监听器为被动(passive)监听器。

Passive Event Listeners 就是告诉前页面内的事件监听器内部是否会调用 preventDefault 函数来阻止事件的默认行为,以便浏览器根据这个信息更好地做出决策来优化页面性能。

目前Chrome主要利用该特性来优化页面的滑动性能,所以Passive Event Listeners特性当前仅支持mousewheel/touch相关事件。

参考这篇课解决 https://juejin.cn/post/7230806990452588581

[Violation] Forced reflow while executing JavaScript

阅读全文 >>

8月 23

列举列举

interface HTMLElementTagNameMap {
    "a": HTMLAnchorElement;
    "abbr": HTMLElement;
    "address": HTMLElement;
    "applet": HTMLAppletElement;
    "area": HTMLAreaElement;
    "article": HTMLElement;
    "aside": HTMLElement;
    "audio": HTMLAudioElement;
    "b": HTMLElement;
    "base": HTMLBaseElement;
    "bdi": HTMLElement;
    "bdo": HTMLElement;
    "blockquote": HTMLQuoteElement;
    "body": HTMLBodyElement;
    "br": HTMLBRElement;
    "button": HTMLButtonElement;
    "canvas": HTMLCanvasElement;
    "caption": HTMLTableCaptionElement;
    "cite": HTMLElement;
    "code": HTMLElement;
    "col": HTMLTableColElement;
    "colgroup": HTMLTableColElement;
    "data": HTMLDataElement;
    "datalist": HTMLDataListElement;
    "dd": HTMLElement;
    "del": HTMLModElement;
    "details": HTMLDetailsElement;
    "dfn": HTMLElement;
    "dialog": HTMLDialogElement;
    "dir": HTMLDirectoryElement;
    "div": HTMLDivElement;
    "dl": HTMLDListElement;
    "dt": HTMLElement;
    "em": HTMLElement;
    "embed": HTMLEmbedElement;
    "fieldset": HTMLFieldSetElement;
    "figcaption": HTMLElement;
    "figure": HTMLElement;
    "font": HTMLFontElement;
    "footer": HTMLElement;
    "form": HTMLFormElement;
    "frame": HTMLFrameElement;
    "frameset": HTMLFrameSetElement;
    "h1": HTMLHeadingElement;
    "h2": HTMLHeadingElement;
    "h3": HTMLHeadingElement;
    "h4": HTMLHeadingElement;
    "h5": HTMLHeadingElement;
    "h6": HTMLHeadingElement;
    "head": HTMLHeadElement;
    "header": HTMLElement;
    "hgroup": HTMLElement;
    "hr": HTMLHRElement;
    "html": HTMLHtmlElement;
    "i": HTMLElement;
    "iframe": HTMLIFrameElement;
    "img": HTMLImageElement;
    "input": HTMLInputElement;
    "ins": HTMLModElement;
    "kbd": HTMLElement;
    "label": HTMLLabelElement;
    "legend": HTMLLegendElement;
    "li": HTMLLIElement;
    "link": HTMLLinkElement;
    "main": HTMLElement;
    "map": HTMLMapElement;
    "mark": HTMLElement;
    "marquee": HTMLMarqueeElement;
    "menu": HTMLMenuElement;
    "meta": HTMLMetaElement;
    "meter": HTMLMeterElement;
    "nav": HTMLElement;
    "noscript": HTMLElement;
    "object": HTMLObjectElement;
    "ol": HTMLOListElement;
    "optgroup": HTMLOptGroupElement;
    "option": HTMLOptionElement;
    "output": HTMLOutputElement;
    "p": HTMLParagraphElement;
    "param": HTMLParamElement;
    "picture": HTMLPictureElement;
    "pre": HTMLPreElement;
    "progress": HTMLProgressElement;
    "q": HTMLQuoteElement;
    "rp": HTMLElement;
    "rt": HTMLElement;
    "ruby": HTMLElement;
    "s": HTMLElement;
    "samp": HTMLElement;
    "script": HTMLScriptElement;
    "section": HTMLElement;
    "select": HTMLSelectElement;
    "slot": HTMLSlotElement;
    "small": HTMLElement;
    "source": HTMLSourceElement;
    "span": HTMLSpanElement;
    "strong": HTMLElement;
    "style": HTMLStyleElement;
    "sub": HTMLElement;
    "summary": HTMLElement;
    "sup": HTMLElement;
    "table": HTMLTableElement;
    "tbody": HTMLTableSectionElement;
    "td": HTMLTableDataCellElement;
    "template": HTMLTemplateElement;
    "textarea": HTMLTextAreaElement;
    "tfoot": HTMLTableSectionElement;
    "th": HTMLTableHeaderCellElement;
    "thead": HTMLTableSectionElement;
    "time": HTMLTimeElement;
    "title": HTMLTitleElement;
    "tr": HTMLTableRowElement;
    "track": HTMLTrackElement;
    "u": HTMLElement;
    "ul": HTMLUListElement;
    "var": HTMLElement;
    "video": HTMLVideoElement;
    "wbr": HTMLElement;
}

阅读全文 >>

8月 23

很多很多年前,网页端图片裁切都会想到 cropper.js 。到了当前, cropper.js 还是值得一选。这个是基于 js,ts 的插件,不局限你使用 vue 还是 使用 react 或其他的。反正,还是很好用。当下 2.0 版本更好用。

官网: https://fengyuanchen.github.io/cropperjs/v2/zh/

演练场:https://fengyuanchen.github.io/cropperjs/v2/zh/playground.html

这个插件越来越自由,也越来越集中。它只关注输入(img dom)和输出(canvas)[转换成 base64 可能会存在跨域问题]。大只分以下几个模块(每个模块都可以单独使用)。

Cropper

CropperCanvas

CropperImage

CropperSelection

CropperShade

CropperGrid

CropperViewer
# 等等

这些,都各自有各自的渲染职责。加上就有,配置就改变。不加则没有。想加就加,想减就减。是真的好用。 先看一个我做的一个 demo。是基于vue3 + ts 实现的。(不对。里边还加了一些 element-plus 的组件)

构建的时候,也很方便。使用其接口就可以。更好的是是基于组件的方式来处理。最终的目的是什么,是要渲染到 dom 中,让人看到。 组件不就是最直接的方式吗。这个时候,你可以很方便的使用 css 去美化你的产品。只需要少量关注一些配置就好。比如裁切比例,覆盖比列等。

阅读全文 >>

8月 17

有封装好的 useDark useToggle 这些插件,做项目就很方便。可是用的时候,会遇到一些问题。其实到最后,不是问题了。比如改变主题的时候,transition 失效了。因为没 transition,强行改变背景颜色等就会很生硬。transition 失效是因为 userColorMode 在处理改变的时候,先禁用 transition 再取消禁用导致的。在创建 useDark 的时候,options 的 disableTransition 可以控制该行为,只是不传值的时候,默认就是 true,就是禁用 trasition。那么默认传入 disableTransition 为 false 的值就可以搞定了。

https://github.com/vueuse/vueuse/blob/main/packages/core/useColorMode/index.ts#L122

const isDark = useDark({disableTransition: false})
 const toggleDark = useToggle(isDark)

只需上边这样实现即可。

阅读全文 >>

8月 15

type 和 interface 相关

https://juejin.cn/post/7063521133340917773

https://blog.csdn.net/qq_42345237/article/details/124895617

namespace 和 modules 相关

https://zhuanlan.zhihu.com/p/56583269

Pick、Omit、Extract、Exclude 等

https://juejin.cn/post/7202153645441892407
https://www.jianshu.com/p/cb8923a7a31b

泛型相关

https://zhuanlan.zhihu.com/p/149767010

https://zhuanlan.zhihu.com/p/149965449

文档

https://www.typescriptlang.org/zh/docs/

https://nodejs.cn/typescript/get-started/

额外

https://developer.mozilla.org/zh-CN/docs/Web

阅读全文 >>

8月 14

前端本地测试,mock 可以先用着。终究还是得和真实的服务环境对接。这个时候请求接口,往往就会遇到跨域的问题。对于 laravel框架,对于 laravel10,只需要建立一个中间件,在中间件中对请求进行处理就好。需要的时候,带上中间件,不需要的时候,去掉它就可以。还是很方便的。

Do

php artisan make:middleware EnableCrossRequestMiddleware

# 完整代码如下
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class EnableCrossRequestMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        $response = $next($request);
        $origin = $request->server('HTTP_ORIGIN') ? $request->server('HTTP_ORIGIN') : '';
        $allow_origin = [
            'http://localhost:5173',
        ];

        if (in_array($origin, $allow_origin)) {
            $IlluminateResponse = 'Illuminate\Http\Response';
            $SymfonyResopnse = 'Symfony\Component\HttpFoundation\Response';
            $headers = [
                'Access-Control-Allow-Origin' => $origin,
                'Access-Control-Allow-Methods' => 'POST,GET,OPTIONS,PUT,PATCH,DELETE',
                'Access-Control-Allow-Headers' => 'Accept,Content-Type,Referer,User-Agent,Origin,X-Requested-With,X-XSRF-TOKEN,X-CSRF-TOKEN,Authorization,Time'
            ];

            if ($response instanceof $IlluminateResponse) {
                foreach ($headers as $key => $value) {
                    $response->header($key, $value);
                }
                return $response;
            }

            if ($response instanceof $SymfonyResopnse) {
                foreach ($headers as $key => $value) {
                    $response->headers->set($key, $value);
                }
                return $response;
            }
        }
        return $response;
    }
}

然后,在 ./app/Http/Kernel.php 的 $middleware 中添加一个配置。

    protected $middleware = [
        …
        \App\Http\Middleware\EnableCrossRequestMiddleware::class,
    ];

这样就完事了。

本来是想将中间件放在中间件组里(middlewareGroups)或使用 alias (放在 $middlewareAliases)的方式来使用,但都失败了。暂时还没找到原因。

之所以想这样弄,是因为不是所有的请求都需要设置请求头。

阅读全文 >>