干了很多,但是好像又没干啥,前端工作总结

disabled属性的作用

我们知道disabled只能作用在表单元素上面,主要作用是使元素将不可变、不能响应事件、不参与约束验证、不能被用户更新、不能聚焦或与表单一同提交,即用户不能与该控件或其后代控件进行交互。

这些元素支持 disabled 属性:<button><fieldset><optgroup><option><select><textarea><input>

如果所支持的元素上存在该属性,将匹配 :disabled 伪类。如果该属性未被包含,则将匹配 :enabled 伪类。如果该元素不支持 disabled 属性,该属性将没有任何作用,包括不会导致被 :disabled:enabled 伪类匹配。

所以如果想要在其他元素上面有disabled相同的效果,我们需要使用pointer-events: none;来实现。

css 复制代码
.disabled {
  color: rgba(0, 0, 0, 0.25);
  cursor: not-allowed;
  pointer-events: none;
}

如何选中闭合的shadowRoot

如果不了解原生的自定义组件开发,请看这里

我们知道dom.shadowRoot是一个 DOM 子树的根节点,它与文档的主 DOM 树分开渲染。所以我们如果想要获取到内部元素,我们就必须先获取到自定义元素的shadowRoot,就和iframe一样的。但是dom.shadowRoo只能选中开放的shadowDOM,即dom.attachShadow({ mode: "open" });。闭合的shadowDOM我们我们是不能进行获取的。但是如果你是做浏览器扩展插件开发的。我们是可以通过chrome.dom.openOrClosedShadowRoot(element)来获取。

如果我们想要方便选择给定的选择器元素,包括自定义组件中的元素的话,这里推荐一个库 query-selector-shadow-dom。以前也是基于这个库解决了项目中的bug,具体可以看这里

git如何移除已上传的文件

如果我们将不该上传的文件上传到git仓库中,我们如何把它删除呢?下面来介绍一下

在网上看有很多让使用git rm -r --cached .,然后向.gitignore中添加改文件即可,这个命令一执行,那么将会导致整个仓库文件都从git暂缓区移除。然后我们在提交,那么这些文件的提交记录都成了自己的了。

如果这样做了,那么我们应该如何回退呢。首先查看git log,使用git reset --hard commitid回退到删除文件之前的代码,然后我们将代码强制push(因为我们已经将全部代码push了,所以当前回退后和远程仓库有冲突,所以需要先pull,如果不想pull,那么就需要强制push)。即git push -f

正确的做法是我们只将要移除的文件从暂缓区中移除就可以了。git rm -r --cached 指定文件,然后在.gitignore中添加该文件路径即可。然后将记录push即可。

数组转树

一般在开发中,我们会根据后端返回回来的数据进行分析处理成我们想要的数据结构。其中一种就是如何将后端返回的数组结构转化为树形结构,例如生成我们的文档菜单等等。

一般给的数据都会包括父级元素的标识,例如parentId属性等。

  • 找出根节点的id,一般设置为""
  • 遍历数组,找到父级元素标识和当前迭代的标识一致的元素,那么该元素将是当前标识的子元素。
  • 每个元素都有作为根节点的机会。
  • 迭代加递归。
js 复制代码
const onlyRootFlatterData = [
  { id: 1, title: 'root1', parentId: "", childrenIds: [ 2, 4 ] },
  { id: 2, title: 'root1-parent1', parentId: 1, childrenIds: [ 3 ] },
  {
    id: 3,
    title: 'root1-parent1-child1',
    parentId: 2,
    childrenIds: []
  },
  {
    id: 4,
    title: 'root1-parent2',
    parentId: 1,
    childrenIds: [ 5, 6, 7 ]
  },
  {
    id: 5,
    title: 'root1-parent2-child1',
    parentId: 4,
    childrenIds: []
  },
  {
    id: 6,
    title: 'root1-parent2-child2',
    parentId: 4,
    childrenIds: []
  },
  {
    id: 7,
    title: 'root1-parent2-child3',
    parentId: 4,
    childrenIds: []
  }
]

// 根据parentId去和id比较,然后加入到对应的children
const result = [];

/**
 * 每个元素都会有一个作为根节点的机会
 * 
 * source 迭代数组
 * result 树形结构
 * parentId 当前根元素id
 */
const solve = (source, result, parentId) => {
    for (let item of source) {
      // 当前元素parentId是否和根节点id相同
      if (item.parentId === parentId) {
        let childrenItem = { 
          id: item.id, 
          title: item.title, 
          parentId: item.parentId, 
          children: [] 
        }
        result.push(childrenItem);
        // 递归调用。将找到位置的元素作为根节点递归。
        solve(source, childrenItem.children, item.id);
      }
    }
};

solve(onlyRootFlatterData, result, ""); // 顶层id为0,""

console.log("result", result)

树转数组

其实在日常开发中后端返回的数据为树形结构比较少,暂时没遇见过后台自己想要返回树形结构数据的。

  • 可能树结构有多个根,我们遍历数组树结构。
  • 递归函数内部,我们需要先将当前根元素加入到数组返回值中,然后再进行是否有children属性判断来决定是否处理到当前树的叶子元素。
js 复制代码
const rootData = [
  {
    id: 1,
    title: 'root1',
    parentId: '',
    children: [
      {
        id: 2,
        title: 'root1-parent1',
        parentId: 1,
        children: [
          {
            id: 3,
            title: 'root1-parent1-child1',
            parentId: 2,
            children: []
          }
        ]
      },
      {
        id: 4,
        title: 'root1-parent2',
        parentId: 1,
        children: [
          {
            id: 5,
            title: 'root1-parent2-child1',
            parentId: 4,
            children: []
          },
          {
            id: 6,
            title: 'root1-parent2-child2',
            parentId: 4,
            children: []
          },
          {
            id: 7,
            title: 'root1-parent2-child3',
            parentId: 4,
            children: []
          }
        ]
      }
    ]
  }
]

const result = []
function solve(result, root) {
  result.push({
    id: root.id,
    title: root.title,
    childrenIds: root?.children?.map(item => item.id) || []
  })
  if(root?.children?.length > 0) {
    // 循环,将当前内容加入到数组,然后递归
    root?.children.forEach(item => {
      solve(result, item)
    })
  }
}

for(let item of rootData) { // 多个根
  solve(result, item)
}

console.log("result", result)

巧用Promise

因为有回调函数的存在,我们在开发中可能会造成回调地狱,导致代码看起来非常臃肿且不易维护。例如我们在开发chromev2插件时,由于chrome插件内部的api大多都是回调函数的形式返回结果。所以我们就需要使用Promise对其进行封装。

js 复制代码
cb2Async<Params extends any[] = any[], Data = any>(fn: Function) {
    // 返回一个函数
    return (...params: Params): Promise<Data> => {
      // 返回一个promise,让我们可以使用await进行同步写法。resolve直接作为传入api的回调函数。
      return new Promise((resolve) => {
        fn(...params, resolve);
      });
    };
}
js 复制代码
// 获取当前窗口
const tabsQuery = cb2Async(chrome.tabs.query);
const tabs = await tabsQuery({ active: true, currentWindow: true });
window.currentTab = tabs && tabs[0]

往期年度总结

往期文章

专栏文章

结语

本篇文章到此就结束了,欢迎在评论区交流。

🔥如果此文对你有帮助的话,欢迎💗关注 、👍点赞 、⭐收藏✍️评论, 支持一下博主~

相关推荐
敲啊敲95273 分钟前
5.npm包
前端·npm·node.js
贵州晓智信息科技9 分钟前
如何优化求职简历从模板选择到面试准备
面试·职场和发展
CodeClimb13 分钟前
【华为OD-E卷-木板 100分(python、java、c++、js、c)】
java·javascript·c++·python·华为od
咸鱼翻面儿17 分钟前
Javascript异步,这次我真弄懂了!!!
javascript
brrdg_sefg18 分钟前
Rust 在前端基建中的使用
前端·rust·状态模式
m0_7482309442 分钟前
Rust赋能前端: 纯血前端将 Table 导出 Excel
前端·rust·excel
qq_589568101 小时前
Echarts的高级使用,动画,交互api
前端·javascript·echarts
黑客老陈2 小时前
新手小白如何挖掘cnvd通用漏洞之存储xss漏洞(利用xss钓鱼)
运维·服务器·前端·网络·安全·web3·xss
正小安2 小时前
Vite系列课程 | 11. Vite 配置文件中 CSS 配置(Modules 模块化篇)
前端·vite