前端须要注意的要点

聊聊公司团队前端交互须要注意的一些要点。html

  1. 通常上 Tab 切换的页面都应该经过路由定义,切换选项卡即切换路由,并且要用 replace 而不是 push 切换。
  2. 页面分页、侧栏分类切换分类等会从新加载列表的操做都要经过路由进行切换。
  3. 连接必须使用 a 标签+设置 href 属性声明跳转,容许用户右键新选项卡打开,不要经过 click 事件进行跳转。
  4. 引入外部插件、添加 DOM 事件到 document/body 时,必定要销毁,不作很容易致使内存泄漏。
  5. 能用框架提供的接口/方法解决就用框架,不要本身另外实现一份。
  6. 页面/组件的每个状态都要处理。

组件状态处理

重点说一下这个,以页面路由组件为例子。前端

例如打开一个页面,状态大体能够分为数据加载中/加载完成/没有数据三种。框架

在写每个页面的时候,都须要针对这 3 种状态进行显示 Loading/骨架图、渲染、空数据提示的处理。异步

另外说一个例子,一个页面包含多个相互独立的业务组件(每个业务组件就能够看成子系统)。async

须要考虑到每个业务组件可能出现的状态:this

有一些组件比较简单,直接渲染 UI 就行了;插件

有一些组件较为复杂,有 Ajax 请求,那么要考虑到请求中、请求成功、失败、没有数据等等状态;code

有一些组件可能引入了很大的第三方库(如Echarts),这些第三方库必须异步加载,这时就须要考虑异步加载第三方库时的状态,好比显示 Loading 之类;htm

其余诸如屏幕适配也能够看成状态的一种,不过屏幕适配通常是在<App />中作,平时不须要太注意。接口

平时开发组件的时候必定要想好到底有多少种状态,哪些状态要处理,哪些状态没必要处理。

另外说下组件状态的理解

对比下下面几种写法的优劣势:

<template>
  <div>
    <skeleton v-if="aData.loading && bData.loading && cData.loading"></skeleton>
    <div v-else-if="aData.error || bData.error || cData.error">页面发生错误</div>
    <template v-else>
      <part-a :data="aData.list"></part-a>
      <part-b :data="bData.list"></part-b>
      <part-c :data="cData.list"></part-c>
    </template>
  </div>
</template>
<script>
export default {
  data() {
    return {
      aData: {
        loading: true,
        error: false,
        list: []
      },
      bData: {
        loading: true,
        error: false,
        list: []
      },
      cData: {
        loading: true,
        error: false,
        list: []
      }
    }
  },
  async created() {
    this.loadA();
    this.loadB();
    this.loadC();
  }
};
</script>
<template>
  <div>
    <skeleton v-if="loading"></skeleton>
    <div v-else-if="hasError">页面发生错误</div>
    <template v-else>
      <part-a :data="aData"></part-a>
      <part-b :data="bData"></part-b>
      <part-c :data="cData"></part-c>
    </template>
  </div>
</template>
<script>
export default {
  data() {
    return {
      loading: true,
      hasError: false,
      aData: [],
      bData: [],
      cData: []
    }
  },
  async created() {
    try {
      await Promise.all([this.loadA(), this.loadB(), this.loadC()]);
    }
    catch(err) {
      this.hasError = true;
    }
    finally {
      this.loading = true;
    }
  }
};
</script>
<template>
  <div>
    <skeleton v-if="loading"></skeleton>
    <div v-else-if="hasError">页面发生错误</div>
    <template v-else>
      <part-a :data="aData"></part-a>
      <part-b :data="bData"></part-b>
      <part-c :data="cData"></part-c>
    </template>
  </div>
</template>
<script>
export default {
  data() {
    return {
      aData: {
        loading: true,
        error: false,
        list: []
      },
      bData: {
        loading: true,
        error: false,
        list: []
      },
      cData: {
        loading: true,
        error: false,
        list: []
      }
    }
  },
  computed: {
    loading() {
      return aData.loading && bData.loading && cData.loading;
    },
    hasError() {
      return aData.error || bData.error || cData.error;
    }
  },
  async created() {
    this.loadA();
    this.loadB();
    this.loadC();
  }
};
</script>

其实一个组件能够看成一个有限状态机。

而后就能够把页面复杂的逻辑问题简化为几个状态机自身的状态转移问题,能够有效简化问题又不失灵活,以应对多变的需求。

相关文章
相关标签/搜索