本网站(662p.com)打包出售,且带程序代码数据,662p.com域名,程序内核采用TP框架开发,需要联系扣扣:2360248666 /wx:lianweikj
精品域名一口价出售:1y1m.com(350元) ,6b7b.com(400元) , 5k5j.com(380元) , yayj.com(1800元), jiongzhun.com(1000元) , niuzen.com(2800元) , zennei.com(5000元)
需要联系扣扣:2360248666 /wx:lianweikj
如何减少前端代码的改动
mycodes · 241浏览 · 发布于2021-09-03 +关注

耦合指模块间关联的程度。模块之间的关联越多,其耦合性越强,那么独立性也就越差了。高耦合的代码,会出现一处改,处处改的情况。高耦合的代码,模块之间的联系,就像一团乱码。

工作中,大家可能会碰到这样的情况:

  • 接口的返回值变了,要改一堆代码。

  • 升级了一个第三方库,要改一堆代码。

  • 某个组件的内部实现变了,要改一堆代码。

如何在遇到这种情况的时候,减少前端代码的改动呢?我分享给大家 2 个技巧:

  • 降低代码间的耦合。

  • 业务代码和依赖代码之间加适配层。

  • 下面我们具体来看~

降低代码间的耦合

耦合指模块间关联的程度。模块之间的关联越多,其耦合性越强,那么独立性也就越差了。

高耦合的代码,会出现一处改,处处改的情况。高耦合的代码,模块之间的联系,就像一团乱码。

解藕,就是避免对模块内部具体实现的依赖。

下面我们来看一些具体的耦合场景,以及对应的解藕方案。

耦合 DOM

直接操作 DOM,是耦合的 DOM 的。当 DOM 结构发生变化时,操作代码也要跟着变。下面是显示用户名的代码:

HTML:

用户名:

用户名:<div id="user-name"></div>

JavaScript:

const userName = ... 
document.querySelector('#user-name').textContent = userName

    当显示用户名的 id 变成其他时, JavaScript 也要变化。

    解藕方法

    Vue, React 之列的框架,声明了 数据 和 视图 的关系,不会耦合 DOM。

    用 Vue:

    <template> 
      用户名:<div>{{userName}}</div> 
    </template> 
    <script> 
    new Vue({ 
      ... 
      data: { 
        userName: ... 
      } 
    }) 
    </script>

    用 React:

    function App () { 
      const [userName, setUserName] = useState(...) 
    
      return ( 
        <div> 
          用户名:<div>{userName}</div> 
        </div> 
      ) 
    }

      耦合其他模块的方法或属性

      以组件为例,当父组件主动调用子组件方法,会造成耦合。例如,父组件要让子组件获得焦点。用 React 实现的代码如下:

      <button onClick={() => inputRef.focus()}>点我获得焦点</button> 
      // 子组件 
      <MyInput ref={inputRef}>

      如果子组件获得焦点的方法签名发生了变化,上面的代码就失效了。同样的,父组件获取子组件的内部属性,也会造成耦合的问题。

      解藕方法

      耦合方法的解决方案1

      子组件监听属性的变化,来响应父组件的主动调用。改写代码如下:

      const [controlFocus, setControlFocus] = useState(0); 
      return ( 
        <> 
          <button onClick={() => setControlFocus(Date.now())}>点我获得焦点</button> 
          <MyInput controlFocus={controlFocus}> 
        </> 
      )

        耦合方法的解决方案2

        用发布订阅模式。父组件需要主动调用子组件方法时,触发个自定义事件,子组建监听该自定义事件。

        耦合属性的解决方案1

        将耦合的属性放到父组件来维护,子组件改属性时,通知父组件。如:

        const [value, setValue] = useState(0); 
        return ( 
          <Comp value={value} onChange={setValue} /> 
        )

          耦合属性的解决方案2

          父组件要获得子组件的内部属性时,改变某个属性。子组件监听到该属性的变化后,执行父组件获取值的回调函数。

          const [value, setValue] = useState(0); 
          const [controlGetValue, setControlGetValue] = useState(0); 
          
          return ( 
            <Comp onChange={setValue} controlGetValue={controlGetValue} /> 
          )

            上面代码中,父组件要获取子组件内部的 value 值,只需改 controlGetValue 的值即可。

            业务代码和依赖代码之间加适配层

            如果业务代码中有多处代码直接调用了外部依赖,如果依赖项发生了变化,调用的地方也要改。比如:接口的请求和响应改了;升级的第三方库的 API 发生了变化。

            解决这个问题,可以在业务代码和依赖代码之间加适配层。当依赖项改后,只需要改适配层代码,不需要改业务代码。

            注意:增加适配层本身会增加代码的复杂度。因此,不要过度的加。一般在满足以下 2 个条件的情况下加:

            1. 代码中有多处代码直接调用了外部依赖。

            2. 外部依赖变动的可能性比较大。

            常见的外部依赖有:配置项,接口,第三方库,全局 API。我们一个个来看。

            分类配置项

            将配置从逻辑中分离出来,写成配置文件。如

            export const API_HOST = '/api' // 接口前缀 
            export const PAGE_LIMIT = 10 // 分页时,一页的条数

              适配接口的请求参数和响应结果

              一般会加个适配层来统一对接口的请求参数和响应。适配层在请求里加 token 之类的,在响应里处理通用报错。如:

              const request = (options) => { 
                // 添加请求拦截器 
                axios.interceptors.request.use(...) 
                // 添加响应拦截器 
                axios.interceptors.response.use(...) 
                return axios 
              }

                对具体接口做格式化请求参数和接口的返回。

                export const formatFromServer = res => ... 
                export const formatToServer = data => ...

                  适配第三方库

                  如果是第三方组件,可以用个组件代理第三库的组件。如:

                  import { Sortable } from "react-sortablejs" 
                  function Sort(props) { 
                    return ( 
                      <Sortable 
                        {...props} 
                        ... 
                      > 
                        ... 
                      </Sortable> 
                    ) 
                  }

                    如果是一个函数,可以用一个函数来代理。如:

                    import xxx from 'xxx' 
                    function myXxx(...args) { 
                      return xxx(...args) 
                    }

                      适配全局 API

                      如果我们大量代码用了浏览器的可能会被废弃的实验性的 API。可以做这样的配置:

                      const someAPI = () => { 
                        if(window.someAPI) { 
                          return someAPI 
                        } 
                        // 不支持的情况。 
                        return () => ... 
                      }

                        总结

                        外部变化后,要减少前端代码的改动,主要靠 降低代码的耦合 和 增加适配代码。但也不要过度使用哦~


                        相关推荐

                        RN开发环境的npm私库本地debug调试

                        manongba · 698浏览 · 2019-05-09 17:03:46
                        你不知道的浏览器渲染原理

                        追忆似水年华 · 1373浏览 · 2019-05-09 22:47:56
                        基于iview的router常用控制方式

                        追忆似水年华 · 999浏览 · 2019-06-03 10:39:21
                        编程小知识之 JavaScript 文件读取

                        manongba · 717浏览 · 2019-06-10 09:16:16
                        10个省时间的 PyCharm 技巧 赶快收藏!

                        · 703浏览 · 2019-06-10 09:32:01
                        加载中

                        0评论

                        评论
                        我从事编程工作,现在在一家网络公司上班,偶尔也是发布博客,逛论坛等,希望可以在这里交到志同道合的朋友。
                        分类专栏
                        小鸟云服务器
                        扫码进入手机网页