09Vue.js快速入门-Vue入门之Vuex实战
9.1. 引言
Vue组件化做的确实非常彻底,它独有的vue单文件组件也是做的非常有特色。组件化的同时带来的是:组件之间的数据共享和通信的难题。 尤其Vue组件设计的就是,父组件通过子组件的prop进行传递数据,而且数据传递是单向的。也就是说:父组件可以把数据传递给子组件,但是 反之则不同。如下图所示:

9.2. 单向数据流动
单方向的数据流动带来了非常简洁和清晰的数据流,纯展示性或者独立性较强的模块的开发确实非常方便和省事。 但是复杂的页面逻辑,组件之间的数据共享处理就会需要通过事件总线的方式解决或者使用Vue的Vuex框架了。
9.3. 子组件通知父组件数据更新:事件方式的实现
子组件可以在子组件内触发事件,然后在父容器中添加子组件时绑定父容器的方法为事件响应方法的方式.如下图所示:

- 使用 v-on 绑定自定义事件
每个 Vue 实例都实现了事件接口(Events interface),即:
使用 $on(eventName) 监听事件
使用 $emit(eventName) 触发事件
参考代码案例:
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Vue入门之event message</title>
  <!-- 新 Bootstrap 核心 CSS 文件 -->
  <link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/3.3.0/css/bootstrap.min.css">
  <!-- 可选的Bootstrap主题文件(一般不用引入) -->
  <link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/3.3.0/css/bootstrap-theme.min.css">
  <!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
  <script src="http://cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></script>
  <!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
  <script src="http://cdn.bootcss.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
  <script src="https://unpkg.com/vue/dist/vue.js"></script>
  <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
</head>
<body>
  <div id="app">
    <p>推荐次数:{{ voteCount }}</p>
    <hr>
    <!--绑定两个自定义事件,当组件内部触发了事件后,会自定调用父容器绑定的methods的方法,达到了子容器向父容器数据进行通信同步的方法-->
    <vote-btn v-on:vote="voteAction" v-on:sendmsg="sendMsgAction"></vote-btn>
    <hr>
    <ul class="list-group">
      <li v-for="o in msg" class="list-group-item">{{o}}</li>
    </ul>
  </div>
  <script>
    Vue.component('vote-btn', {
      template: `
        <div>
          <button class="btn btn-success" v-on:click="voteArticle">推荐</button>
          <hr/>
          <input type="text" v-model="txtMsg" />
          <button v-on:click="sendMsg" class="btn btn-success">发送消息</button>
        </div>
      `,
      data: function () {
        return {
          txtMsg: ""
        }
      },
      methods: {
        voteArticle: function () {
          // 触发事件,vote
          this.$emit('vote')
        },
        sendMsg: function () {
          // 触发事件,sendmsg,并
          this.$emit('sendmsg', this.txtMsg)
        }
      }
    })
    var app = new Vue({
      el: '#app',
      data: {
        voteCount: 0,
        msg: []
      },
      methods: {
        voteAction: function() {  // 事件触发后,会直接执行此方法
          this.voteCount += 1
        },
        sendMsgAction: function (item) {
          this.msg.push(item)
        }
      }
    });
  </script>
</body>
</html>
9.4. 事件总线方式解决非父子组件数据同步
如果非父子组件怎么通过事件进行同步数据,或者同步消息呢?Vue中的事件触发和监听都是跟一个具体的Vue实例挂钩。 所以在不同的Vue实例中想进行事件的统一跟踪和触发,那就需要一个公共的Vue实例,这个实例就是公共的事件对象。

参考下面做的一个购物车的案例的代码:
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Vue入门之event message</title>
  <!-- 新 Bootstrap 核心 CSS 文件 -->
  <link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/3.3.0/css/bootstrap.min.css">
  <!-- 可选的Bootstrap主题文件(一般不用引入) -->
  <link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/3.3.0/css/bootstrap-theme.min.css">
  <!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
  <script src="http://cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></script>
  <!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
  <script src="http://cdn.bootcss.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
  <script src="https://unpkg.com/vue/dist/vue.js"></script>
  <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
</head>
<body>
  <div id="app">
    <product-list :products="products" v-on:addpro="addToCarts"> </product-list>
    <hr>
    <cart :cart-products="carts"> </cart>
  </div>
  <script>
    var eventBus = new Vue()
    Vue.component('cart', {
      template: `
      <table class="table table-borderd table-striped table-hover">
      <thead>
        <tr>
          <th>商品编号</th>
          <th>商品名</th>
          <th>数量</th>
          <th>操作</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="item in cartProducts">
          <td>{{ item.id }}</td>
          <td>{{ item.name }}</td>
          <td>
            {{ item.count }}
          </td>
          <td>
            <button type="button" @click="removeCarts(item)" class="btn btn-success"><i class="glyphicon glyphicon-remove"></i></button>
          </td>
        </tr>
      </tbody>
    </table>
      `,
      data: function () {
        return {
        }
      },
      methods: {
        removeCarts: function (item) {
          eventBus.$emit('remo', item)
        }
      },
      props: ['cartProducts']
    })
    Vue.component('product-list', {
      template: `
      <table class="table table-borderd table-striped table-hover">
      <thead>
        <tr>
          <th>商品编号</th>
          <th>商品名</th>
          <th>操作</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="item in products">
          <td>{{ item.id }}</td>
          <td>{{ item.name }}</td>
          <td>
            <button type="button" v-on:click="addToCarts(item)" class="btn btn-success"><i class="glyphicon glyphicon-shopping-cart"></i></button>
          </td>
        </tr>
      </tbody>
    </table>
      `,
      data: function () {
        return {
        }
      },
      methods: {
        addToCarts: function (item) {
          this.$emit('addpro', item)
        }
      },
      props: ['products'],
    })
    var app = new Vue({
      el: '#app',
      data: {
        products: [
          { id: '1', name: '鳄鱼' },
          { id: '2', name: '蛇' },
          { id: '3', name: '兔子' },
          { id: '4', name: '驴' },
          { id: '5', name: '孔雀' }
        ],
        carts: []
      },
      methods: {
        addToCarts: function (item) {
          var isExist = false
          for(var i=0; i<this.carts.length; i++) {
            if( item.id === this.carts[i].id ) {
              item.count = this.carts[i].count + 1
              Vue.set(this.carts, i, item)
              isExist = true
            }
          }
          !isExist && (item.count = 1, this.carts.push(item))
        },
        removeCarts: function (item) {
          for(var i =0; i<this.carts.length; i++) {
            if( item.id === this.carts[i].id) {
              this.carts.splice(i,1)
            }
          }
        }
      },
      mounted: function () {
        self = this;
        eventBus.$on('remo', function (item) {
          self.removeCarts(item)
        })
      }
    });
  </script>
</body>
</html>
9.5. Vuex解决复杂单页面应用
上面的方式只能解决一些简单的页面中的组件的通信问题,但是如果是复杂的单页面应用就需要使用更强大的Vuex来帮我们进行状态的统一管理和同步。
当第一次接触Vuex的时候,眼前一亮,之前经过Redux之后,被它繁琐的使用令我痛苦不已,虽然思路很清晰,其实完全可以设计的更简单和高效。 当我接触到Vuex之后,发现这就是我想要的。的确简洁就是一种艺术。
其实本质上,Vuex就是一个大的EventBus对象的升级版本,相当于一个特定的仓库,所有数据都在统一的仓库中,进行统一的管理。
几个核心的概念:
- State: Vuex仓库中的数据。
- Getter: 类似于Vue实例中的计算属性,Getter就是普通的获取state包装函数。
- Mutations: Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutations 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。
- Action: action可以触发Mutations,不能直接改变state。
看下面一张图了解一下Vuex整体的数据流动:

9.6. Vuex实例demo
可能前面的图和概念都太多了,先看一个例子,简单了解一下Vuex中的仓库的数据 怎么整合到 Vue的实例中去。
创建Vuexdemo的项目
# 通过vue-cli创建vuexdemo的项目,注意首先cd到你的存放项目代码的目录
vue init webpack vuexdemo
# 过程中,会有几个选项你可以选择输入Y或者n来开启或者关闭某些选项。
# 创建完成后,就可以通过以下命令,进行初始化和安装相关的依赖项了。
cd vuexdemo
npm install
npm run dev
# 然后安装 vuex
npm i vuex -S
联系老马
对应视频地址:https://chuanke.baidu.com/s5508922.html
老马qq: 515154084
老马微信:请扫码

09Vue.js快速入门-Vue入门之Vuex实战的更多相关文章
- Vue+nodejs+npm完美结合入门==vue入门
		因为我的是win7系统 64位 只能下载低版本的nodjs: 传送门:https://nodejs.org/dist/v9.7.1/ 一.使用之前,我们先来掌握3个东西是用来干什么的. npm: No ... 
- Vue.js+vue-element搭建属于自己的后台管理模板:Vue.js快速入门(二)
		Vue.js+vue-element搭建属于自己的后台管理模板:Vue.js快速入门(二) 前言 上篇文章对Vue.js有了初步理解,接下来我们把Vue.js基础语法快速的过一遍,先混个脸熟留个印象就 ... 
- 07Vue.js快速入门-Vue路由详解
		对于前端来说,其实浏览器配合超级连接就很好的实现了路由功能.但是对于单页面应用来说,浏览器和超级连接的跳转方式已经不能适用, 所以各大框架纷纷给出了单页面应用的解决路由跳转的方案. Vue框架的兼容性 ... 
- 06Vue.js快速入门-Vue组件化开发
		组件其实就是一个拥有样式.动画.js逻辑.HTML结构的综合块.前端组件化确实让大的前端团队更高效的开发前端项目.而作为前端比较流行的框架之一,Vue的组件和也做的非常彻底,而且有自己的特色.尤其是她 ... 
- Vue.js—快速入门
		Vue.js是什么 Vue.js 是一套构建用户界面的渐进式框架.与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计.Vue 的核心库只关注视图层,它不仅易于上手,还便于与第三方库或既有项目 ... 
- Vue.js—快速入门及实现用户信息的增删
		Vue.js是什么 Vue.js 是一套构建用户界面的渐进式框架.与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计.Vue 的核心库只关注视图层,它不仅易于上手,还便于与第三方库或既有项目 ... 
- Vue 入门指南  JS
		Vue 入门指南 章节导航 英文:http://vuejs.org/guide/index.html 介绍 vue.js 是用来构建web应用接口的一个库 技术上,Vue.js 重点集中在MVVM模式 ... 
- python 全栈开发,Day88(csrf_exempt,ES6 快速入门,Vue)
		BBS项目内容回顾 1. 登陆页面 1. 验证码 1. PIL(Pillow) 2. io 2. ORM 1. 增删改查 3. AJAX $.ajax({ url: '', type: '', dat ... 
- Vue 入门之 Vuex 实战
		Vue 入门之 Vuex 实战 引言 Vue 组件化做的确实非常彻底,它独有的 vue 单文件组件也是做的非常有特色.组件化的同时带来的是:组件之间的数据共享和通信的难题. 尤其 Vue 组件设计的就 ... 
随机推荐
- 详解PV、UV、VV、IP及其关系与计算
			一.什么是PV? PV即Page View,网站浏览量,指页面浏览的次数,用以衡量网站用户访问的网页数量.用户每次打开一个页面便记录1次PV,多次打开同一页面则浏览量累计.一般来说,PV与来访者的数量 ... 
- ant执行jar包中的main方法
			<project name= "myproject" basedir= "." default="main"> <p ... 
- Ubuntu14.04安装CMake3.5.1(转)
			1.下载cmake-3.5.1.tar.gz:https://cmake.org/download/ 2.把 cmake-3.5.1.tar.gz放到任意临时目录(因为Cmake的安装路径默认在:/u ... 
- 【C语言】练习1-20
			题目来源:<The C programming language>中的习题 练习1-20:编写程序detab,将输入中的制表符替换成适当数目的空格,使空格充满到下一个制表符终止的地方. 思 ... 
- 日志收集之--将Kafka数据导入elasticsearch
			最近需要搭建一套日志监控平台,结合系统本身的特性总结一句话也就是:需要将Kafka中的数据导入到elasticsearch中.那么如何将Kafka中的数据导入到elasticsearch中去呢,总结起 ... 
- golang学习笔记 ---数组与切片
			数组: golang数组包含的每个数据称为数组元素(element),数组包含的元素个数被称为数组长度(length). golang数组的长度在定义后不可更改,并且在声明时可以是一个常量或常量表达式 ... 
- linux文件系统 - 初始化(三)
			执行init程序 一.目的 内核加载完initrd文件后,为挂载磁盘文件系统做好了必要的准备工作,包括挂载了sysfs.proc文件系统,加载了磁盘驱动程序驱动程序等.接下来,内核跳转到用户空间的in ... 
- C# 获取接口数据(xml格式)转为json格式
			using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net ... 
- 转: 基于elk 实现nginx日志收集与数据分析
			原文链接:https://www.cnblogs.com/wenchengxiaopenyou/p/9034213.html 一.背景 前端web服务器为nginx,采用filebeat + logs ... 
- A标签href属性详解--记录八
			1.去掉<a>标签的下划线 <ul style=" list-style-type:none; margin:0;color:Gray; font-size:11px;ma ... 
