迷茫下是自我提升

长夜漫漫,无心睡眠。心中所想,心中所感,忧愁当前,就执笔而下,写下这篇文章。

回忆过往

回想当初为啥学前端,走前端这条路,学校要求嘛,兴趣爱好嘛,还是为了钱。 时间带着我的回忆,回到了21年,也是我人生得转折点,那时候大学分班,直白点就是选择路线,因为我们是软件工程专业,所以软件方面都学习过,软件设计模式,数据结构,算法,计算机网咯,数据库,web程序设计,计算机组成原理,项目管理,等等科目,甚至硬件我们也有实操,示波器,焊接,组装板块都玩了一下。可以说学的很杂,软件工程专业得学生其实学得更多得都是偏后端得科目,像前端这种可能不入大学老师得眼,所以前端是没有专门的课程得。当时黑马也来我们学校合作过,带着我们写项目,后端java,微服务。最让我们印象深刻得是,他们培训毕业班工资情况,当时很惊讶,月薪一万,两三万都有。但是现在仔细想想那些都是外包公司,包装了几年工作经验进去的。是啊,当时,java后面,很高薪啊,而且上限总体要比前端高啊。大数据那时候也很火啊,甚至人工智能python也火。挺迷茫得,不仅是我,还有我的室友嘛。每个人得人生仿佛都在那时候决择了。 我也问了很多身边出去工作的人,建议都是选人工智能,大数据,这些比较吃香。不过我们还是很理智得,人工智能选不得,没有个研究生身份,选它很难找到工作,而且我们学校不出名。其实当我们问别人得时候,心里已经有个不确定得而想选择得答案 。对于我来说,大数据,跟后端,我都能玩,只是感觉比较枯燥,相比于前端,页面直接能看到,更加得吸引我的注意力,后端上限是高,但又有几个能达到月薪五万呢,我们更多得是平凡人,不是大牛。这就是我走了前端路线得答案,没那么枯燥,可视化。

迷茫当下

也许很多人转行过来得学前端,是因为IT得高薪工作,为啥不转后端呢,因为相对于后端,前端更好学点。这个不得不承认,我做兼职得时候,就遇到好多都是转行过来得,然后花钱请教问题解决得。所以就造成了人员很多过来一起卷,大环境得不行,很多公司都在裁员,加上AI得出现。所以会搞得人心惶惶。工作几年了,到了涨薪得年纪,公司还降薪,很多人都都说大环境不好,能苟着就苟着,面试机会也少。 所以现在很多公司裁高低招,你不干自然有的是人干,造成行业内卷加剧。 金三银四,我也投了试一下,面了几家公司,有一家公司让我印象很深刻,深刻在什么地方呢,他问了我很底层,js底层,问我js怎么来的,如果不用它得已有api,让你去判断它是什么类型,你怎么判断。当时我回答上了引用数据类型,可以用原型连得方式去判断。但是基本数据类型我就懵了,像0,好像用不了__prototo__吧,不过它确实有个API可以进行获取到它得原型对象,一生万物,万物皆对象,确实都可以用原型链来判断。 他问了我几个比较难得问题,最后我问他,你们公司是要搭建自己得框架嘛,还是做要插件,组件库。一问啥都没有,都在计划中,听了他的业务描述,纯纯的切图崽就能完成得东西,干嘛问这种问题。我是有点想不通得。我也面了一家,本来说是人事面得,然后面试得时候又加技术面,一直在问我解决方案,然后我问他,我看你一直不满意我的方案,你是有更好得方案嘛,能介绍一下嘛,然后他说的跟我前面差不多,总感觉是套我方案得感觉,然后就没然后了。还是面试一些中大型公司比较好,我回答不好的时候,他能很清楚得解答给我听。虽然没过,但也让我收获不少。

提升自我

这段时间,我也陷入了迷茫,到底想活出怎样的人生。 我也问过同事,他是怎么说的,我相信我的价值还是比人工智能要强的,大不了去摆地摊。是啊,与其自我焦虑,不如,有空的时候提升自己。哪怕出去玩,都比精神内耗强,谁知道明天是怎样的呢。还不如,静下来提升自我。在思考一番后,我的灵感来了。最近一直没写作,也不是说摆烂了。而是没有一个idea,自己要干嘛。想要干嘛。 因为之前做了两个公司的项目,跟同事写了六七款日历组件,所以就想能不能写一个日历库,因为都是移动端的,Taro开发的,网上没找到一个模板,公司也在弄移动端组件库,刚好我也参与其中,所以我也能一边学习 ,一边弄个自己的作品。所以我就自己搭建一个。

总体设计

构想 搭建框架 => 构建总体目录 => 编写组件 => 组件测试 => 打包发布 => 网站展示 =>网站设计,网站展示,mark展示代码,代码高亮复制,例子渲染,锚点展示,接口文档,兼容打包发布 => 进行部署。 当时我的构思是这样的,当时组件的打包,跟网站还是不一样的。所以我就考虑从vite,webpack,rollup三个其中一个进行打包,因为rollup不是很熟悉,就打算用它来打包,也是抱着一个学习的心,。然后网站的打包就用taro自带配置的进行打包,当然内置的是webpack。 先上效果图,毕竟前端要最后呈现的东西为主。

使用技术:Taro + React + Ts +React-router-dom + rollup + webpack5

效果图

1.常用日历组件

2.带弹窗日历组件

3.滑动日历组件

4.简单日历组件

5.选项日历组件

6.星期日历组件

目前展示这几个组件。等有其它想法继续添加。

预览地址:地址

目录结构:

arduino 复制代码
wskCalendar
├─ config            //taro配置                      
│  ├─ dev.ts
│  ├─ index.ts
│  └─ prod.ts
├─ src
│  ├─ api
│  │  └─ test.ts
│  ├─ components   //日历组件
│  ├─ images   //日历组件图片
│  ├─ index.html
│  ├─ index.ts //日历组件打包入口
│  ├─ pages //测试展示入口
│  ├─ routes //配置测试路由
│  ├─ style //样式
│  │  ├─ common.scss
│  │  ├─ index.scss
│  │  └─ website.scss //网站全局样式
│  ├─ types
│  ├─ utils //工具函数
│  └─ website //网站架构
│     ├─ assets //网站资源
│     │  └─ images
│     ├─ components//展示组件编写
│     ├─ guide//指南
│     ├─ home//首页
│     ├─ index
│     ├─ layoutCom//部局组件
│     └─ routers//路由
│        ├─ demoRoutes.ts
│        ├─ index.ts
│        ├─ sidebarTabs.ts
│        ├─ topbarTabs.ts
│        └─ websiteRoutes.ts
├─ .editorconfig
├─ .eslintrc
├─ .gitignore
├─ babel.config.js
├─ buildJson.js //处理package.joson
├─ copy-rollup-postcss-inject-to-css.mjs//自己编写的插件处理scss
├─ jest.config.ts
├─ markdown-loader.js//自己编写插件处理md文件
├─ myRollupPlugin.mjs
├─ package.json
├─ project.config.json
├─ project.tt.json
├─ README.md
├─ rollup.config.mjs
├─ tsconfig.json
├─ types
├─ yarn.lock

插件编写

buildJson.js 处理打包package.json写入插件,type:'module'必须是这个配置在这里,不然Taro的Api没办法使用,这个问题我找了一天,这也是taro的一个坑。移除自己的插件避免下载依赖进行了套娃处理。

bash 复制代码
const fs = require('fs')
const path = require('path')
const chalk = require('chalk')
const __dirnameNew = __dirname;
let rootPath = path.join(__dirnameNew, 'package.json');
let filePath = path.join(__dirnameNew, 'dist', 'wskCalendar', 'package.json');
// 创建持久化编译时间
const createPersistentCompilationTime = () => {
  // 1.判断是否存在文件
  try {
    getTimeFile();
  } catch (error) { }
};
// 2.获取时间文件
const getTimeFile = () => {
  try {
    fs.readFile(rootPath, "utf-8", (err, fileData) => {
      fileWriteContent(fileData);
    });
  } catch (error) {
  }
};
// 文件写入内容
const fileWriteContent = (data) => { //写入type:module
  try {
    // 解析 JSON 字符串为对象
    let jsonData = JSON.parse(data);
    // 新建对象
    let newJsonData = {};
    // 遍历旧对象的键
    for (let key in jsonData) {
      // 把每个键/值对添加到新对象
      newJsonData[key] = jsonData[key];
      // 在 description 后面添加新的键/值对
      if (key === "description") {
        newJsonData["type"] = "module";
      }
      if (key === "dependencies") {
         delete newJsonData["dependencies"]?.["wskcalendar"] //删除自己的依赖包防止下载套娃
      }
    }
    // 把对象转回 JSON 字符串,并保持原来的格式
    data = JSON.stringify(newJsonData, null, 2);
    fs.writeFile(filePath, Buffer.from(data, 'utf-8'), "utf-8", (err) => {
      if (err) {
        return console.warn(`🚀[developer 🌞🔥 (っ °Д °;)っ]🌈 ~ file: buildJson.js:31 ~ fs.writeFile ~ err: 写入文件失败`, err);
      } else {
        return console.warn(`🚀[developer 🌞🔥 (っ °Д °;)っ]🌈 ~ :
        \b ✅ json写入成功, 请进入目录 ${chalk.red("cd dist/wskCalendar")} 进行发布新版本:
        \b ${chalk.green("npm publish")}
        \b 返回:
        ${chalk.green("cd ../..")}
        \b ❌ 撤销版本请使用:
        \b ${chalk.yellow("npm unpublish wskCalendar@[指定版本号]")}
        \b 插件地址
        `);
      }
    });
  } catch (error) {
    console.warn(
      "🚀[ developer wsj ] ~ file: buildTime.ts:37 ~ fileWriteContent ~ error:",
      error
    );
  }
};
createPersistentCompilationTime();

markdown-loader.js 进行一个提取md,文件进行渲染,以及高亮处理.

bash 复制代码
const marked = require('marked');
const hljs = require('highlight.js');
module.exports = content => {
 const __jsx = content.match(/```jsx[\s\S]*```/g)?.[0]?.replaceAll(/```jsx|```/g, '') || 'export const Jsx = () => <></>;';
 const __html = marked.marked(content, {
   // 设置代码高亮
   highlight: function (code, lang) {
     const language = hljs.getLanguage(lang) ? lang : 'plaintext';
     return hljs.highlight(code, { language }).value;
   },
 });
 return `
   ${__jsx}
   export const __html = ` + '`' + __html + '`;' +
   'export const __code = `' + __jsx + '`;';
}

copy-rollup-postcss-inject-to-css.mjs 将CSS、SCSS或LESS样式从打包的JavaScript文件中截取并放入单独的CSS文件。这样做的好处是,可以避免将样式加载到JavaScript中,从而提高页面的加载速度。 因为样式文件默认是在浏览器解析和执行JavaScript代码之前加载的,所以,将样式文件独立出来可以尽快给用户展示页面的样式,同时避免JavaScript执行阻塞页面的显示。

bash 复制代码
import { createFilter } from '@rollup/pluginutils';

function inlineToExtract (options = {}) {
 const filter = createFilter(options.include, options.exclude);

 return {
   name: 'inline-to-extract',
   transform (_, id) {
     if (!filter(id)) return null
   },
   generateBundle (_, bundle) {
     const resolveCss = [];
     Object.keys(bundle).forEach(name => {
       const bundleItem = bundle[name];
       bundleItem.imports?.forEach((item, index) => {
         if (/(scss|less|css)\.js/.test(item)) {
           let code;
           code = /"[\s\S^"]*"/igm.exec(bundle[item].code);
           if (code?.[0]) {
             code = code[0].replace(/\\n/g, '').replace(/\\"/g, '"').replace(/\\\\/g, '\\');
             if (!resolveCss.includes(item)) {
               Object.assign(bundle[item], {
                 fileName: item.replace(/\.(scss|less|css)\.js/, '.css'),
                 code: code.slice(1, code.length - 1),
                 importedBindings: null,
                 imports: []
               });
               resolveCss.push(item);
             }
           }
           delete bundleItem.importedBindings[item];
           bundleItem.importedBindings[item.replace(/\.(scss|less|css)\.js/, '.css')] = [];
           bundleItem.imports[index] = bundleItem.imports[index].replace(/\.(scss|less|css)\.js/, '.css');
           bundleItem.code = bundleItem.code.replace(/\.(scss|less|css)\.js/, '.css');
         }
       });
     });
   }
 }
}

export default inlineToExtract;

myRollupPlugin.mjs伟大而不现实的构想插件,个人构想,就是进行插件把Taro相关的组件转换为HTML元素,这样就不用基于taro框架去运行起来了,在任何的一个react框架上都可以用了,其它的方案都是两套代码,我懒得写,但是组件做到了转换,忘记了Taro Api,唉,阿康能力有限还是处理不了taro api的转换。尝试了将taro.js打包进去了还是不行。

bash 复制代码
import { createFilter } from 'rollup-pluginutils';
import * as parser from '@babel/parser';
import traverse from '@babel/traverse';
import generate from '@babel/generator';
import * as t from '@babel/types';

export default function replaceTagsAndRemoveNonExistentProps() {
  const filter = createFilter('**/*.tsx', 'node_modules/**');

  return {
    name: 'replace-tags-and-remove-non-existent-props',

    transform(code, id) {
      if (!filter(id)) return;

      const ast = parser.parse(code, {
        sourceType: 'module',
        plugins: ['jsx', 'typescript'],
      });

      traverse.default(ast, {
        JSXOpeningElement(path) {
          if (['View', 'Text', 'Image', 'ScrollView'].includes(path.node.name.name)) {
            if (path.node.name.name === 'View') path.node.name.name = 'div';
            if (path.node.name.name === 'Text') path.node.name.name = 'span';
            if (path.node.name.name === 'Image') path.node.name.name = 'img';
            if (path.node.name.name === 'ScrollView') path.node.name.name = 'div';
            // 过滤并替换属性
            path.node.attributes = path.node.attributes.filter(attr => {
              if (!attr.name) return false;
              let propName = attr.name.name;
              if (propName === 'catchMove') return false; // 移除 'catchMove';
              if(propName === 'scrollIntoView') return false;
              if(propName === 'scrollX') return false;
              attr.value && replaceITouchEvent(attr.value);
              return true;
            });
          }
        },
        JSXClosingElement(path) {
          if (['View', 'Text', 'Image', 'ScrollView'].includes(path.node.name.name)) {
            if (path.node.name.name === 'View') path.node.name.name = 'div';
            if (path.node.name.name === 'Text') path.node.name.name = 'span';
            if (path.node.name.name === 'Image') path.node.name.name = 'img';
            if (path.node.name.name === 'ScrollView') path.node.name.name = 'div';
          }
        },
        CallExpression(path) {
          if (t.isIdentifier(path.node.callee) && ['onTouchMove', 'onTouchStart', 'onTouchEnd'].includes(path.node.callee.name)) {
            path.node.arguments = path.node.arguments.map(arg => replaceITouchEvent(arg));
          }
        },
        TSTypeReference(path) {
          path.replaceWith(replaceITouchEvent(path.node));
        },
        ArrowFunctionExpression(path) {
          path.node.params.forEach(param => {
            if (
              t.isTSTypeAnnotation(param.typeAnnotation) &&
              t.isTSTypeReference(param.typeAnnotation.typeAnnotation)
            ) {
              param.typeAnnotation.typeAnnotation = replaceITouchEvent(param.typeAnnotation.typeAnnotation);
            }
          });
        },
      });

      const output = generate.default(ast, {}, code);

      return {
        code: output.code,
        map: { mappings: '' }
      };
    },
  };
}

function replaceITouchEvent(node) {
  if (t.isTSTypeReference(node)) {
    if (node.typeName && t.isIdentifier(node.typeName) && node.typeName.name === 'ITouchEvent') {
      // 创建一个新的类型引用,使用 `React.TouchEvent` 作为类型名,并设置类型参数为 `HTMLDivElement`
      return t.tsTypeReference(
        t.identifier('React.TouchEvent'),
        t.tsTypeParameterInstantiation([
          t.tsTypeReference(t.identifier('HTMLDivElement'))
        ])
      );
    }
  }
  return node;
}

对于项目的介绍就暂时那么多,具体的请看项目,后附上github地址,但是还有一个坑,也是taro的prebundle 为 true 时,Taro 会对所有 npm 包和本地 npm 包进行预编译(pre-bundling)。对于一些 npm 包来说,有时候你可能直接把它们作为 @tarojs/components 或其他库的附属品导入到你的项目中,而这些包在进行模块导入时可能会存在一些问题,比如使用了一些关键字或者语法结构等。这时,把 prebundle 设置为 true 就会对这些包做一次预编译,旨在避免可能的编译错误,增强模块的兼容性。

不然打包出来的网站使用taro的api有问题。

最后吐槽:taro这个框架说句心理实话,坑挺多的, 也不能说是坑,只能说开发心智负担有点重。

仓库地址:github

这个插件可以为你提供一个是编写自己的移动端插件,跟组件库的思路,缺点,像mark暂时只能支持js的jsx展示示例代码,跟局限于react,taro上。如果觉得不错,可以给点个star。

以上就是我的一个灵感实现的的过程。也许比较拉跨,但也是一次自我的提升。后面也会尝试着去学习一下AI大模型

做技术的学的技术一定要顺应时代的发展,社会需要什么黑科技,就要花时间去钻研。我知道现在不努力积累自己的专业知识,未来只会如逆水行舟,一步步将我推回起点。疫情三年真的是大浪淘沙,淘汰只会是那些不脚踏实地学习和工作的人,出来混迟早要还的。只有现在奋力前行,未来才有更多的选择机会。

最后

谁的青春不迷茫,迷茫下只能是顺势而为,不断提升自己。迷茫中不忘初心,坚持心中得所想,不断进步。当然特别迷茫得时候,去吹吹海风,去看看路上得风景,说不定哪一天风告诉了你答案,你一瞬间就明白了自己想要什么样得人生。最近宫崎骏,新出了一部动漫《你想活出怎样得人生》看看别人得人生,说不定也有你想有得答案。每个人想法都是不一样得,想要得人生也不一样。有点鸡汤了哈,言而总之,迷茫下还是要提升自我,不管是前端,还是其它得都好。

相关推荐
lemon_sjdk9 分钟前
Java飞机大战小游戏(升级版)
java·前端·python
G等你下课10 分钟前
如何用 useReducer + useContext 构建全局状态管理
前端·react.js
欧阳天羲12 分钟前
AI 增强大前端数据加密与隐私保护:技术实现与合规遵
前端·人工智能·状态模式
慧一居士12 分钟前
Axios 和Express 区别对比
前端
I'mxx21 分钟前
【html常见页面布局】
前端·css·html
万少26 分钟前
云测试提前定位和解决问题 萤火故事屋 上架流程
前端·harmonyos·客户端
qianmoQ40 分钟前
GitHub 趋势日报 (2025年07月13日)
github
brzhang1 小时前
OpenAI 7周发布Codex,我们的数据库迁移为何要花一年?
前端·后端·架构
军军君011 小时前
基于Springboot+UniApp+Ai实现模拟面试小工具三:后端项目基础框架搭建上
前端·vue.js·spring boot·面试·elementui·微信小程序·uni-app
布丁05231 小时前
DOM编程实例(不重要,可忽略)
前端·javascript·html