Vue 组件设计思考

1,575 阅读2分钟

Vue 组件设计思考

我们知道, Vue 是基于 MVVM 设计的一个前端框架, 是数据驱动页面显示的架构. 同时, 它是 Html 的模板引擎, 是 Vue 模板通过翻译器翻译成 Hmtl 语言. 这个 Vue 模板, 也就是组件, 在 Vue 中, 一切皆是组件.

一、路由模块化

在我们分析某一个页面组件结构之前, 我们必须要从 main.js 入口 的 路由 开始. 原因是:

页面的跳转通常都是通过路由 页面的结构少不了 <router-view />

这里除非只用 Vue 做移动 APP, 不用路由做导航.

main.js

简化了不必要的东西

import Vue from 'vue';
import App from './App.vue';
import router from './router';

new Vue({
  router,
  render: h => h(App)
}).$mount('#app');

router.js

这里简化了, 可以看到里面路由分模块了, 里面引入 user 模块, user 作为 Home 的子路由.

import Vue from 'vue';
import Router from 'vue-router';

Vue.use(Router);

const App = () => import('@/App');
const Home = () => import('@/modules/Home');

// 导入模块
import user from './modules/user';

/**
 * 主页路由表,主页下面子路由放在这
 */
const homeRouter = [
  {
    path: '/',
    component: App,
    redirect: '/home'
  },
  {
    path: '/home',
    component: Home,
    name: 'Home',
    meta: {
      title: 'common.breadCrumb.Home'
    },
    children: [ // 主页子路由
      ...user // 用户中心
    ]
  }
];

export default router;

user.js

这里是用户模块, 里面可以放登录,注删,用户相关的页面导航 在 User 下面, 还有一个子导航 Login. 作跳转时, 只要加入<router-view /> 就可以做跳转.

const User = () => import('@/modules/user');
const Login = () => import('@/modules/login');
const Doing = () => import('@/modules/user/Doing');

export default [
  {
    path: '/user',
    name: '用户中心',
    component: User,
    meta: {
      title: 'common.breadCrumb.UserSet'
    },
    children: [
      {
        path: '/user/login',
        name: 'UserLogin',
        component: Login,
        meta: {
          title: 'common.breadCrumb.Login'
        }
      }
    ]
  }
];

为什么路由要这样设计, 先看看 Home 页面组成, 我们拿百度页面来分析

1.jpg

图中 页脚组件, 如果是每一个页面都要显示. 那么我们是不是可以封装成 <Footer /> 组件放在最下面. 那么每一页都会出现.

<template>
  <div id="app">
    <div class="app-main">
        <router-view />
    </div>
    <ATUFooter />
  </div>
</template>

<script>
const Footer = () => import('modules/common/Footer');

export default {
  name: 'App',
  components: { Footer },
};
</script>

在比较, 我们跳传到用户模块里面, 如果有二个以上的页面有相同的组件, 是不是可以直接放到页面里面去. 通过子导航去页面 <router-view /> 跳转. 当然, 如果我们用不上导航, 也可以直接在页面作组件切换的刷新, 只是这样. 当页面多到一定数量时, 就不好管理.

二、页面的组件化

1、什么时候抽离成独立组件

我们拿百度首页来分析, 这里面有 5 个内容体, 分别是是页头的导航, 页脚信息等, 还要主要内容搜素, 新闻, 热搜. 这是一个简单的页面结构. 如果我们不做组件拆分, 只有一个人独立开发, 那么其实可以全部代码都写在 template 里面 一个功能一个功能慢慢的去实现.

<template>
    <div id="home">
        <div class="nav">
        </div>
        <div class="search">
        </div>
        <div class="news">
        </div>
        <div class="hot">
        </div>
    </div>
</template>

但是我们通常都是多人合作开发, 在这个页面里面多少人去写入代码这样真的好吗?

所以, 我们对这个页面作 4 个组件的拆分, 然后通过 Home 页合并到一起. 开发人员商量好共同的交互与数据, 然后独立的开发各自的组件.

<template>
    <div id="home">
        <Nav class="nav" />
        <Search class="search" />
        <News class="news" />
        <Hot class="hot" />
    </div>
</template>

组件的拆分一定要按实际情况出发, 不要为组件而组件, 把问题搞复杂化了.

比如一个下载按钮

  • 如果这个下载只是简单的得到 Url 下载地址下载.那么就没有必要去封装成组件.
  • 但是如果这个下载, 里面要做大量的业务逻辑处理, 去别的模块取值做计算等, 里面大量复杂代码会影响主组件的简洁, 那么抽取出来做独立处理更好一点.

2、组件之间的数据交互

组件之间的数据的交互方式官网上说的很清楚了, 我就简单说一点, 通常是以下三种情况:

a. 父组件与子组件交互

父组件传到子组件可以通过 props, 反过来, 子组件传到父组件用 this.$emit() 传出去.

b. 兄弟组件交互

可以通过父组件传交互, 但是实际用起来,有时会传不到. 这时也可以通过 store 做中传.

c. 祖组件与孙组件交互

祖组件到孙组件, 一层层传下去. 反过来, 官网也有方法, 但是用起来好像有问题, 建议还是通过 store 处理.

3、组件的网络请求与数据业务逻辑应该放在那里.

按实现情况出发吧

  • 如果这个组件是多个模块共用, 数据来源不一样, 那么最好是数据是从外面,也就是父组件转进来. 这样能最大限度保持它的通用性.
  • 如果这个组件是多个模块共用, 但是数据来源是一样, 那么最好的是把数据请求, 业务逻辑等一起封装在里面. 这样好处是保护父组件的简洁性.
  • 如果这个组件是独立的, 那么最好是把数据请求, 业务逻辑等一起封装在里面.

3. 最后

我个人建议是, 组件数据请求、业务逻辑等代码能写在里面最好写在里面, 独立封装, 这样能够分化父组件的代码. 不用全部代码写在一起. 当然, 如果这个组件是公用组件, 那么又是另外一回事. 数据必须是外面传进来.

如果封装在里面了, 数据传出去, 就按上面数据交互来做, 但是通常, 都是网络清求数据, 在网络发送出去. 只有少数据情况下才会用到里面页面传递.

大部分的开发都是多人开发, 所以做好模块化或者说组件化的开发是很重要的.

以上只是个人见解, 如果有说的不对的地方, 欢迎指正讨论, 谢谢.