前端框架Vue.js构建大型应用浅析

真正的模块化

前端模块化很早就开始了,无论是 require.js,browserify 进行模块化打包, 还是 Angular 进行依赖注入,我们都可以把JS代码分成一个个小的模块并组装起来。然后我们还会通过 less 或者 sass 来把CSS文件也拆成一个个小的模块来写,甚至我们在CSS代码中感受到了 封装,继承,多态 等面向对象的特性。

然而,在 webpack 出来之前,我们所谓的模块化根本不能算作模块化。为什么这么讲,因为我们存在一个重要的问题没有解决,就是JS模块对CSS模块的依赖。

比如我们有一个JS模块 modal 那么我们直接导入并调用它就能弹出一个对话框吗?如下图所示可以吗?

理论上应该是这样的,但实际上这个 modal其实还依赖一个对应的CSS模块 modal.less ,如果不导入这个模块我们是无法弹出一个正常的对话框的,而且,导入这个CSS模块竟然不是和导入JS模块写在同一个地方,而是写在另一个CSS文件中。也就是说,其实依赖关系是这样的:

为了使用一个模块,我们需要在两个文件中分别做一次引入操作。这其实是一件非常奇怪不合理的事!我们为什么要模块化?就是为了封装一个模块,可以做到导入它就能使用,而它是如何实现的,它有什么依赖关系完全是这个模块自己处理的,也就是上图中对 modal.css 的依赖应该是 modal.js 自己处理的。
但是我们写了N年的前端却一直这样写模块,不是因为他对,而是因为我们习惯了这种错误的方式。现在用Vue我们可以完全封装一个模块的全部依赖,无论是模板、CSS还是JS,我们都不需要再去关心,只要引入这个模块就可以使用,而模块的依赖是它自己进行处理的。

那么我们的依赖关系就变成了:

其中 modal.vue 包含了全部所需要的依赖,那么我们就不在需要自己去处理对应的 CSS 甚至 模板了。这才是模块化应该达到的效果。

创建 Vue 项目

Vue 提供了一个工具 vue-cli 可以创建一个项目模板: https://github.com/vuejs/vue-cli

这里我先尝试了一下另一个模板项目:https://github.com/vuejs-templates/webpack

然后我们就可以不用 纯JS来写模块了,而是借助 webpack 来把一个模块相关的所有内容全部写到一个文件中。以之前的 todo list 为例,其实上一章讲的只是component的用法所以那样写了。我们改成一个更好的写法如下:

List.vue:

<template>
 <ul>
 <li v-for='todo in list'>
  <label v-bind:class="{ done : todo.done }" >
  <input type="checkbox" v-model="todo.done"/>
  {{todo.title}}
  </label>
 </li>
 </ul>

</template>

<script>
export default {
 props: {
 initList: {
  type: Array
 }
 },
 data () {
 return {
  list: []
 }
 },
 events: {
 add (input) {
  if (!input) return false
  this.list.unshift({
  title: input,
  done: false
  })
 }
 }
}
</script>

<style lang="less" scoped>
ul {
 margin-left: 2rem;
 padding: 0;

 .done {
 text-decoration: line-through;
 }
}
</style>

Form.vue:

<template>
 <h1>{{username}}'s Todo List</h1>
 <form v-on:submit="add" v-on:submit.prevent>
 <input type="text" v-model="input"/>
 <input type="submit" value='add' />
 </form>
</template>

<script>
export default {
 props: {
 username: {
  type: String,
  default: 'Unnamed'
 }
 },

 data () {
 return {
  input: ''
 }
 },

 methods: {
 add () {
  this.$dispatch('add', this.input)
  this.input = ''
 }
 }
}
</script>

Todo.vue:

<template>

 <div id="todo">
 <todo-form username='Lily'></todo-form>
 <todo-list></todo-list>
 </div>

</template>

<script>
import Form from './Form.vue'
import List from './List.vue'

export default {
 components: {
 'todo-form': Form,
 'todo-list': List
 },

 events: {
 add (input) {
  this.$broadcast('add', input)
 }
 }
}

</script>

<style>
</style>

App.vue:

<template>
 <todo></todo>
</template>

<script>
import Todo from './components/Todo.vue'

export default {
 components: {
 'todo': Todo
 }
}
</script>

<style>
</style>

这样我们就把之前的 Todo List 按照 模块化 重写了一遍。模块化是构建大型应用的基础之一,但是这一点还不够,我们还需要做到:
 •更好的状态管理,把不同组件共享的 State 独立出来管理
 •自动化测试
 •路由等

这里我们只做其中一个,就是把 State 独立成一个单独模块。很显然,对一个 Todo List 应用来说,保存 todo list 的数据结构就是不同组件共享的 State。
之前我们为什么需要进行事件广播,就是因为不同组件之间要操作的数据就保存在 List.vue 中,所以在 Form.vue 中想增加一条数据的时候需要通过事件的方式去通知 List.vue 来添加。
也就是其实这个数据不是 List.vue 私有的,应该至少是这两个组件公有的,现在被 List.vue 据为己有之后,Form.vue 没法修改它只好通过事件进行通知。
虽然事件的方式很优雅,但其实我们可以做的更好,就是把数据独立出来,这样 Form.vue 和 List.vue 都可以直接修改数据,而不用那么麻烦发通知。

这里我们增加一个 Store.js 文件:

export default {
 list: [
 ],

 add (title) {
 if (!title) return
 this.list.unshift({
  title: title,
  done: false
 })
 }
}

然后 我们可以把 List.vue 改成这样,这里只贴出JS部分的代码:

import Store from '../Store.js'

export default {
 props: {
 initList: {
  type: Array
 }
 },
 data () {
 return Store
 }
}

Form.vue 也不需要广播了,直接调用 Store.add 方法既可以添加:

import Store from '../Store.js'
export default {
 props: {
 username: {
  type: String,
  default: 'Unnamed'
 }
 },

 data () {
 return {
  input: ''
 }
 },

 methods: {
 add () {
  Store.add(this.input)
  this.input = ''
 }
 }
}

这样一改之后,整个逻辑会清晰很多,并且应用越是复杂,越是应该抽出公有的 Store ,不然会出现广播事件满天飞的情况。
另外用这个项目模板之后,hot-reload 爽的不要不要的,刷新操作都省了。

上述的源码在这里:https://github.com/lihongxun945/vue-webpack-todo-list

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 前端框架学习总结之Angular、React与Vue的比较详解

    近几年前端的技术发展很快,细分下来,主要可以分成四个方面: 1.开发语言技术,主要是ES6&7,coffeescript,typescript等: 2.开发框架,如Angular,React,Vue.js,Angular2等: 3.开发工具的丰富和前端工程化,像Grunt,Gulp,Webpack,npm,eslint,mocha这些技术: 4.前端开发范围的扩展,如服务端的nodejs,express,koa,meteor,GraphQL;移动端和跨平台的PhoneGap,ionic,Reac

  • 第一次接触神奇的前端框架vue.js

    前言 入手2016最火前端框架之一vue.js.大概从网上找了些资料看了下vue.js,从网上的资料来看只能惊叹其发展速度太快,让我意外的是其作者是华人的前提下作品这么受欢迎. 网上的博客和教程各种组合.以至于我都有些感觉out.各种vue+webpack.vue+react.vue+es6+npm等等.琳琅满目.真是三天不学习赶不上刘少奇. 开篇主要是初次了解下vue.js,包括v-model.v-if.v-else.v-show.v-for(2.0对$index和$key舍弃,2.0要用in

  • Vue.js 2.0 和 React、Augular等其他前端框架大比拼

    React React 和 Vue 有许多相似之处,它们都有: 使用 Virtual DOM 提供了响应式(Reactive)和组件化(Composable)的视图组件. 保持注意力集中在核心库,伴随于此,有配套的路由和负责处理全局状态管理的库. 相似的作用域,我们会用更多的时间来讲这一块的比较.不仅我们要保持技术的准确性,同时兼顾平衡.我们指出React比Vue更好的地方,例如,他们的生态系统和丰富的自定义渲染器. React社区在这里非常积极地帮助我们实现这一平衡,特别感谢来自 React

  • 基于Vuejs框架实现翻页组件

    翻页功能对前端后端都是个难题啊!今天终于给踩了!哈哈!整理下方法,我是基于vueJs写的,同样适用于angular哈! 封装下载地址:vue.js翻页组件 效果截图: 整体实现逻辑,当用户点击页码时,ajax从后端获取数据,包括:records(当前页查询到的记录),totalRecords: 121(所有记录),currentPage(当前页码),totalPage(总页码),size(当前页显示数量),之后用我封装的算法assemblePageTurnerParams,算出页面展示哪些页码.

  • vue.js中mint-ui框架的使用方法

    本文为大家分享了vue.js中mint-ui框架的使用方法,具体内容如下 1.安装vue2.0的mint-ui框架 npm install mint-ui -save 2.引用和使用框架,我用的是全部组件,也可以按需选择加载相应的组件,不过要使用babel-plugin-component import Mint from 'mint-ui'; Vue.use(Mint); 3.创建一个header.vue组件,里面写入mint-ui的头部组件 <template> <mt-header

  • Vue2.0 UI框架ElementUI使用方法详解

    今天来介绍一下ElementUI的使用,在Vue2.0更新之后,很多UI框架也应运而生,这个框架是饿了么团队开发的一款适用于PC的一个UI框架,体验之后给我的个人感觉确实是有助于快速开发的一款UI框架,在饿了么GitHub中我下载了一个团队开发的官方Demo(GitHub链接为:https://github.com/taylorchen709/vue-admin)感觉可以应对初期团队项目为管理系统的开发这一类的网站,下面我就来仔细讲解下如何让官方的Demo运行起来 首先我们使用windows件+

  • vue,angular,avalon这三种MVVM框架优缺点

    本文的主要内容是参考官方文档说明总结而来: Vue.js Vue.js @尤雨溪 老师写的一个用于创建 web 交互界面的库,是一个精简的 MVVM.从技术角度讲,Vue.js 专注于 MVVM 模型的 ViewModel 层.它通过双向数据绑定把 View 层和 Model 层连接了起来.实际的 DOM 封装和输出格式都被抽象为了Directives 和 Filters.Vue.js和其他库相比是一个小而美的库,作者的主要目的是通过一个尽量简单的 API 产生可反映的数据绑定和可组合的视图组件

  • 前端框架Vue.js中Directive知识详解

    Directive 看上去虽然和Angular中的定义类似,Directive 都是对DOM功能的一种拓展,但是 Vue 的 Directive 要弱的多.因为 Vue Component 其实本来就会包含对DOM的操作,所以大多数时候我们写一个通用组件都是一个Component 而不是一个 Directive,而 在 Angular 我们写一个通用的组件一般都是一个 Directive . 所以我说 Vue 的 Directive 相比于 Angular 要弱的多,也可以说纯粹的多,他就是对

  • 利用VUE框架,实现列表分页功能示例代码

    先来看一下效果图: 功能描述: 1. 点击页面序号跳转到相应页面: 2. 点击单左/单右,向后/向前跳转一个页面: 3. 点击双左/双右,直接跳转到最后一页/第一页: 4. 一次显示当前页面的前三个与后三个页面: 5. 始终显示最后一个页面: HTML: <!-- 分页开始 --> <div class="u-pages" style="margin-bottom:20px; margin-top:10px;"> <ul> <

  • 前端主流框架vue学习笔记第二篇

    接上篇,在本篇中,我们将要实现如下,功能,编辑和查询,我们当前的todolist程序,和线上其它的demo程序不同,我们会对其进行增删改查的基本操作,之后进行进一步的完善,按照常规的系统使用经验,一般我们新增和编辑都是在模态框中处理,这里我们不会去构建复杂的模态框,只用一个简单的div层来代替,后期接下来的文章中我们会重复造轮子,构建我们自己的轻量级框架(UI库). 首先,我们对我们的页面结构进行一下简单的调整,加入bootstrap只是为了让页面不那么赤裸裸,对其它不会有任何影响 <!DOCT

随机推荐