Write the Code. Change the World.

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)的方式来使用,但都失败了。暂时还没找到原因。

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

阅读全文 >>

8月 13

经过前边的处理,用户登录,侧边栏渲染,路由跳转,登录信息展示,用户退出。这些功能最小化完成。如下图所示。

在线预览,可切换角色。新用户注册,有一个默认角色。只有测试账号有多角色。

https://www.zeipan.com/admin

用户登录

打开后台域名任意 url 。在路由全局守卫中。 如果用户已登录(存在 token),先判断用户信息是否初始化,如果没有,先请求用户信息(返回数据不仅有用户信息,还有该用户对应的后台权限【用户生产菜单】),处理存储用户信息,添加路由信息。再重定向。如果已初始化,就继续。如果用户没登录,先重定向到登录页面。

调用接口,请求登录。获取用户的 token。存储 token。

通过 token,请求用户信息(数据中包括用户的权限数据),存储用户信息以及权限数据。处理权限数据,生成菜单。

阅读全文 >>

8月 04

做了一些基础的配置。现在准备开始做布局了。这里只要两种布局,空白布局和后台布局。空白布局什么时候用呢,登录页面会用到。后台布局,就后台真正内容会用到。始终喜欢极简风格,所以方方面面都不要搞的太复杂。后台布局页面主要有左侧菜单栏,顶部信息栏,中间内如区域构成。

要做好这些,先温习一下 vue3 的 vue-router 以及 transition 还有 element plus 的 menu 组件。当然,loading 相关的也会考虑进去。

额外一点。左侧菜单的内容(和路由会一一映射),请求 api 的权限,全部有后端生成。前端不做权限的控制。也就是后端返回过来的菜单是什么样子,前端就渲染成什么样子。

https://router.vuejs.org/zh/

https://cn.vuejs.org/guide/built-ins/transition.html

https://element-plus.org/zh-CN/component/menu.html#collapse-%E6%8A%98%E5%8F%A0%E9%9D%A2%E6%9D%BF

基础布局

先看看构成后台的三部分。这里建立了一个 layout,拆分成了三部分。

src/views
├── HomeView.vue
├── layouts
│   ├── components
│   │   ├── AppMain
│   │   │   └── AppMain.vue
│   │   ├── NavBar
│   │   │   └── NavBar.vue
│   │   └── SideBar
│   │       └── SideBar.vue
│   └── index.vue
└── test.vue

路由是这样的。

import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
import Layout from '@/views/layouts/index.vue'

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/',
      name: 'home',
      component: HomeView
    }, 
    {
      path: '/test',
      name: 'test',
      component: Layout,
      children: [
        {
          path: '',
          name: 'test-child',
          component: () => import('@/views/test.vue')
        }
      ]
    }
  ]
})

export default router

这里只是初步尝试,没有做更细致的逻辑编写。

希望你的屏幕足够宽,希望一屏足够承载你的业务。如果不够,如果不可以。那么滚动条在所难免。那么滚动条怎么出现最好看呢。

一种方式如上图所示。还有一种,可以只在 content 区域左右上下滚动。个人觉得那种不好看,交互也不是很好。最好就是一屏足够承载吧。

side bar 和 nav bar 都没使用背景色。滑动中间区域会看到穿透。真正做时,会有背景色,z-index 也会高出一些。

白天以及暗黑主题安排上,侧边栏展开收缩也安排上。

还有移动端的布局(小程序、h5、app 等等),特别是小程序。有的公司为了一套代码,给很多企业或多项目用。底部 tabbar 采用非原生写法,滚动条从顶滚到底,不仅滚动条丑,底部切换还会闪动。体验特不好。有时候为了好的滚动条效果,加入了 scroll-view 组件去控制。

这里,如果左侧菜单足够多,也会出现滚动条。这个在 side bar 内部去处理就好了。

阅读全文 >>

8月 03

丰富的互联网资源,用 svg 文件作为 icon 已经很常见了。这里使用 iconify 来处理 icon。 iconify 可以理解为一个管理封装各个 icon 的工具。

https://iconify.design/

https://element-plus.org/zh-CN/component/icon.html

开始

# 安装
pnpm install unplugin-icons unplugin-vue-components -D

# 修改 vite.config.ts
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import Icons from "unplugin-icons/vite";
import IconsResolver from "unplugin-icons/resolver";

// https://vitejs.dev/config/
export default defineConfig({
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  },
  css: {
    preprocessorOptions: {
      scss: {
        additionalData: `
          @use "@/assets/styles/element.scss";
          @use "@/assets/styles/element-dark.scss";
          @use "@/assets/styles/main.scss";
          @use "@/assets/styles/preflight.scss";
        `,
      },
    },
  },
  plugins: [
    vue(),
    AutoImport({
      resolvers: [ElementPlusResolver({
        importStyle: "sass",
        directives: true
      })],
    }),
    Components({
      dts: "./components.d.ts", 
      resolvers: [
        IconsResolver({
          prefix: "i", // 默认为i,设置为false则不显示前缀
          enabledCollections: ["ep"],
          alias: {
            'icon': "ep", //配置别名
          }
        }),
        ElementPlusResolver({
          importStyle: "sass",
          directives: true
        })
      ],
    }),
    Icons({
      autoInstall: true, // 是否自动安装对应的图标库,默认为true
      scale: 1, // 图标缩放,默认为1
      defaultStyle: "", // 图标style
      defaultClass: "", // 图标class
      compiler: 'vue3', // 编译方式,可选值:'vue2', 'vue3', 'jsx'
      jsx: "react", // jsx风格:'react' or 'preact'
    })
  ]
})

阅读全文 >>

8月 02

安装和使用 tailwindcss

https://blog.vini123.com/958

按照上边的链接的步骤,就可以安装好 tailwindcss 了。

只是在导入 scss 的时候,这里依旧写在 vite.config.ts 的配重中。

  css: {
    preprocessorOptions: {
      scss: {
        additionalData: `
          @use "@/assets/styles/element.scss";
          @use "@/assets/styles/element-dark.scss";
          @use "@/assets/styles/main.scss";
        `,
      },
    },
  },

并在 package.json 中增加配置。遵循使用 es 模块规范。

{
  …,
  "type": "module"
}

运行起来,发现 tailwindcss 的默认样式已经生效了。

再完善 homeveiw,使用上 tailwindcss 看看。仅修改以下代码。

  <div class="container mx-auto">
    <h1 class="mt-4">Custom theme example (on demand)</h1>

发现,整个大的容器 div 已经水平居中了。 有了 tailwindcss,就可以单独少写很多 css。直接在 div 中就可以实现样式的效果。而作为后台,又使用 element-plus,需要使用到定制化的样式已经比较少了。 tailwindcss 就刚好使用了一点点就能达到想要的效果。

可是,再仔细看页面,发现按钮的文字看不见了,其他样式也有缺陷。检查发现是 tailwindcss 的样式对 element-plus 的样式有影响。

解决 tailwindcss 和 element-plus 样式的影响问题

先修改 tailwind.config.js 文件,加入以下配置。

export default {
  corePlugins: {
    preflight: false,
  },
  …

再去下载 preflight.css 文件,下载地址 [https://unpkg.com/browse/tailwindcss@3.3.3/src/css/preflight.css]() 注意,和自己安装版本的对应。

还是一样,改名为 prefight.scss 后,配置引入它。并注释掉有冲突的样式。这里把对按钮这块的处理样式给注释掉了。

// button,
// [type='button'],
// [type='reset'],
// [type='submit'] {
//   -webkit-appearance: button; /* 1 */
//   background-color: transparent; /* 2 */
//   background-image: none; /* 2 */
// }

然后发现,按钮的样式回来了。

提交版本

git add .
git commit -m '安装和配置 tailwindcss'

阅读全文 >>

8月 02

前边一篇说了 element-plus 覆盖主题色的操作。这边就要做多主题的处理。也就是除了默认的主题,还得增加一个暗黑主题。

https://element-plus.org/zh-CN/guide/dark-mode.html

Do

思路还是一样,覆盖主题(颜色,间距等)。

# 创建
touch assets/styles/element-dark.scss

@forward 'element-plus/theme-chalk/src/dark/var.scss' with (
  $bg-color: (
    'page': #0a0a0a,
    '': #626aef,
    'overlay': #1d1e1f,
  ),
  $colors:(
    "primary": ("base": green),
  )
);

@use "element-plus/theme-chalk/src/dark/css-vars.scss" as *;

vite.config.ts 中引入。

    preprocessorOptions: {
      scss: {
        additionalData: `
          @use "@/assets/styles/element.scss";
          @use "@/assets/styles/element-dark.scss";
        `,
      },
    },

这样,样式就好了。可以手动在 html 节点加入 class="dark" 看看效果。发现背景颜色已经是黑色(#0a0a0a)了。

阅读全文 >>

8月 01

多主题,是一个站点的常规配置。至少白天主题和夜晚主题是必须要有的。 element-plus 提供了一个很好的实现多主题的方案。先从修改默认主题色开始。

https://element-plus.org/zh-CN/guide/theming.html

开始

先安装 sass

pnpm add -D sass

再创建覆盖默认主题颜色的 sass 文件

# 创建
touch assets/styles/element.scss

# 填充以下内容
@forward 'element-plus/theme-chalk/src/common/var.scss' with (
  $colors: (
    'primary': (
      'base': #003261,
    ),
    'success': (
      'base': #21ba45,
    ),
    'warning': (
      'base': #f2711c,
    ),
    'danger': (
      'base': #db2828,
    ),
    'error': (
      'base': #db2828,
    ),
    'info': (
      'base': #42b8dd,
    ),
  ),
  $button-padding-horizontal: (
    'default': 80px,
  )
);

阅读全文 >>