最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 一个巧合,我把文档写进了代码里

    正文概述 掘金(二银)   2021-02-22   517

    最近因为公司业务的调整,项目需要开发大量的业务组件、高复用逻辑提供给客户使用。当各类组件、代码多了以后,加上团队内几个成员书写习惯、开发思想的不同,出现了好多问题。尤其两个问题最严重:

    1. 大量的业务组件/业务逻辑需要通过查源代码的方式,或者问写组件的人,才能知道组件是否有自己需要的属性/钩子方法
    2. 有些组件因为产品需求 + 口头沟通 + 需求妥协,只能应用于某一个特定的情况下,其他人看设计图或者逻辑差不多相似就直接拿过来用,结果发现用不了/各种问题

    为了解决这两个问题,就开始要求组员在开发业务组件的同时,必须写对应的开发文档/代码注释。一开始还好,中后期开发文档的更新明显跟不上组件的迭代,逐渐地又回到了靠嘴问的情况,第2个问题也是随着时间推移又回到了起点。

    某天通过VS Code调试代码的时候忽然发现,用鼠标在原生语法和react的方法上悬浮几秒钟,就会出现一个提示框,里面有一些节点/组件/方法的简单介绍,参数等。

    对,这就是我想要的效果!

    原生语法 (如document.getElementById):

    一个巧合,我把文档写进了代码里

    react的方法(如useState):

    一个巧合,我把文档写进了代码里

    通过ctrl + 鼠标左键点开类型定义,发现提示框里的内容其实是相关代码上方的注释。

    一个巧合,我把文档写进了代码里

    按照类型定义里面的注释,我在代码里输入/**的时候出现了如下图的提示。

    一个巧合,我把文档写进了代码里

    拿着关键词我去VS Code的官网搜索了一番,在官网搜到了答案(点击此处)。

    JSDoc的语法也非常简单,只需要保证注释的开头是/**即可,其他与多行注释没有什么差别。(更多语法:点击此处)

    /** 这样便创建了一个代码提醒 */
    function remind() {}
    

    上手写个组件试试效果!

    import React, { useEffect, useState } from 'react'
    
    interface KeywordInterface {
      /**
       * 关键词
       */
      keyword?: string;
      /**
       * 高亮显示的颜色,支持hex、hsl、rgba、keywords
       */
      color?: string;
      children?: string;
    }
    
    /**
     * 关键词高亮组件
     * 
     * @example <LightKeyword keyword="hello">Hello World</LightKeyword>
     * 
     * @param { string } keyword - 关键词
     * @param { string } color - 高亮显示的颜色
     */
    const LightKeyword: React.FC<KeywordInterface> = ({
      color = '',
      keyword = '',
      children = ''
    }) => {
    
      const [ context, setContext ] = useState('')
    
      useEffect(() => {
        // 当关键词为空时,无需对内容做高亮显示
        if( !keyword ) { 
          return setContext(children)
        }
    
        const pattern = new RegExp(keyword, 'gi')
        // 通过正则把关键词过滤出来并增加HTML节点
        const allword = (children as string).replace(pattern, (word) => `<i class="light-keyword-item" ${ color && `style="color: ${ color }"` }>${ word }</i>`)
    
        setContext(allword)
      }, [ keyword, color, children ])
    
      return (
        <span className="light-keyword" dangerouslySetInnerHTML={{ __html: context }}></span>
      )
    }
    
    export default LightKeyword
    

    效果展示:

    当鼠标悬浮在组件上时:

    一个巧合,我把文档写进了代码里

    当数据悬浮在组件属性上时:

    一个巧合,我把文档写进了代码里

    完美!这样只要按格式写好注释,就可以不用那么麻烦地去查文档了。(前提是得写)

    那如果是业务逻辑呢?因此我写了一段基于业务封装的异步请求代码。

    
    
    import qs from 'qs'
    import { message } from 'antd'
    import axios, { AxiosRequestConfig } from 'axios'
    
    interface configInterface {
      /**
       * 请求地址
       */
      url: string;
      /**
       * 请求方式
       */
      method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
      /**
       * 请求参数
       */
      data?: any;
      /**
       * 其他配置参数
       * 
       * @param { Object }  headers 请求头配置
       * @param { boolean } errorMessage 是否启用错误提醒
       * @param { string }  responseType 请求类型,默认为json
       * @param { boolean } withCredentials 是否携带跨域凭证
       */
      options?: {
        /**
         * 请求头配置
         */
        headers?: any;
        /**
         * 是否启用错误提醒
         */
        errorMessage?: boolean;
        /**
         * 请求类型,默认为json
         */
        responseType?: 'json' | 'arraybuffer' | 'blob' | 'document' | 'text' | 'stream';
        /**
         * 是否携带跨域凭证
         */
        withCredentials?: boolean
      }
    }
    
    // axios全局配置
    const $axios = axios.create({
    
      // 请求接口地址
      baseURL: 'https://demo.com',
      // 超时时间
      timeout: 60 * 1000
    })
    
    /**
     * 异步请求
     * 
     * @description 基于现有业务封装,自动处理GET请求序列化/错误码处理反馈/跨域配置等操作
     * @example useRequest<T>({ url: 'api/weather', method: 'GET', data: { date: '2021-02-30' }, options: {} })
     * @typedef requestConfig 请求参数
     * @param   { string } requestConfig.url 请求地址
     * @param   { string } requestConfig.method 请求方式
     * @param   { any }    requestConfig.data 请求参数
     * @param   { object } requestConfig.options 其他配置参数
     */
    const useRequest = async <T>(requestConfig: configInterface): Promise<T> => {
    
      const requestOptions = requestConfig.options || {}
    
      const axiosConfig: AxiosRequestConfig = {
    
        url: requestConfig.url,
        method: requestConfig.method || 'GET',
        headers: requestOptions.headers || {},
        responseType: requestOptions.responseType || 'json',
        withCredentials: requestOptions.withCredentials !== false
      }
    
      // 请求方式为GET时,对参数进行序列化处理
      if( axiosConfig.method === 'GET' ) {
    
        axiosConfig.params = requestConfig.data || {}
        axiosConfig.paramsSerializer = (params) => qs.stringify(params, { arrayFormat: 'brackets' })
    
      } else {
    
        axiosConfig.data = requestConfig.data || {}
      }
    
      try {
    
        const { data: response } = await $axios(axiosConfig)
    
        // 如后端返回错误码,将错误推入catch句柄执行
        if( response.code !== 0 ) {
    
          // 错误提醒
          if( requestOptions.errorMessage !== false ) {
    
            message.error(response.message || '未知错误')
          }
          
          return Promise.reject(response)
        }
    
        return Promise.resolve(response)
    
      } catch(e) {
    
        // 错误提醒
        if( requestOptions.errorMessage !== false ) {
    
          message.error('请求错误,请稍后重试')
        }
    
        return Promise.reject(e)
      }
    }
    
    export default useRequest
    

    实际效果:

    一个巧合,我把文档写进了代码里

    (基本用法及参数提醒)

    一个巧合,我把文档写进了代码里

    (额外配置提醒)

    配合Typescript,几乎就是把文档写进了代码里!!!

    然而当我兴致勃勃地搭建vue 3的开发环境,想尝试一下vue的智能提示。经过多轮测试,JSDoc的智能提示只支持在js/ts/tsx这几类的文件,并不支持.vue格式的文件。

    一个巧合,我把文档写进了代码里

    vue文件不支持jsdoc的智能提示)

    如果希望在vue文件中也有类似的智能提示,可以通过VS Code安装vetur插件,然后在项目根目录下创建名为vetur的文件夹,并新建tags.jsonattributes.json两个文件,然后在package.json中引入两者的路径 。

    // package.json
    {
      "name": "demo",
      "version": "0.1.0",
      "vetur": {
        "tags": "./vetur/tags.json",
        "attributes": "./vetur/attributes.json"
      }
    }
    
    // vetur/tags.json
    {
      "light-keyword": {
        "attributes": ["keyword", "content", "color"],
        "description": "关键词高亮组件"
      }
    }
    
    // vetur/attributes.json
    {
      "color": {
        "type": "string",
        "description": "高亮显示的颜色,支持hex、hsl、rgba、keywords"
      },
      "content": {
        "type": "string",
        "description": "文本内容"
      },
      "keyword": {
        "type": "string",
        "description": "关键词"
      }
    }
    

    最后的实现效果

    一个巧合,我把文档写进了代码里

    (组件智能提示)

    一个巧合,我把文档写进了代码里

    (组件描述)

    一个巧合,我把文档写进了代码里

    (属性描述)

    好处是不受vue版本的限制,2和3都可以用;坏处是json文件的限制,没有办法像JSDoc一样显示丰富的格式和代码片段,希望vetur能够加强这方面的优化吧。


    起源地下载网 » 一个巧合,我把文档写进了代码里

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元