Vue组件通信应用实践总结

简介: Vue组件通信应用实践总结

【1】 组件通信的5种方式

props
vue的自定义事件
pubsub第三方库
slot
vuex

① props

父子组件间通信的基本方式
属性值的2大类型: 
 一般: 父组件-->子组件
 函数: 子组件-->父组件
隔层组件间传递: 必须逐层传递(麻烦)
兄弟组件间: 必须借助父组件(麻烦)

② vue自定义事件

子组件与父组件的通信方式
用来取代function props
不适合隔层组件和兄弟组件间的通信

③ pubsub第三方库(消息订阅与发布)

适合于任何关系的组件间通信

④ slot

通信是带数据的标签,注意: 标签是在父组件中解析。

⑤ vuex

多组件共享状态(数据的管理),组件间的关系也没有限制。功能比pubsub强大, 更适用于vue项目。

【2】组件引入与组件传值

① 父页面

<template>
  <div class="todo-container">
    <div class="todo-wrap">
    <!-- 给子组件绑定方法 -->
      <TodoList :todos="todos"/>
    <!-- 给子组件绑定方法并传值 -->      
      <TodoFooter :todos="todos" :deleteCompleteTodos="deleteCompleteTodos" :selectAll="selectAll"/>
    </div>
  </div>
</template>

② 脚本

父页面需要引入并声明组件:

<script>
//import引入组件
  import TodoHeader from './components/TodoHeader.vue'
  import TodoList from './components/TodoList.vue'
  import TodoFooter from './components/TodoFooter.vue'
  import storageUtils from './utils/storageUtils'
  export default {
  //声明组件
    components: {
      TodoHeader,
      TodoList,
      TodoFooter
    }
    //数据
    data () {
      return {
        todos: storageUtils.readTodos()
      }
    },
    methods: {
      addTodo (todo) {
        this.todos.unshift(todo)
      },
      deleteTodo (index) {
        this.todos.splice(index, 1)
      },
      // 删除所有已完成的
      deleteCompleteTodos () {
        this.todos = this.todos.filter(todo => !todo.complete)
      },
      // 全选/全不选
      selectAll (isSelectAll) {
        this.todos.forEach(todo => {
          todo.complete = isSelectAll
        })
      }
    }
  }
</script>


export 用来导出模块,Vue 的单文件组件通常需要导出一个对象,这个对象是 Vue 实例的选项对象,以便于在其它地方可以使用 import 引入。而 new Vue() 相当于一个构造函数,在入口文件 main.js 构造根组件的同时,如果根组件还包含其它子组件,那么 Vue 会通过引入的选项对象构造其对应的 Vue 实例,最终形成一棵组件树。


使用export default命令,为模块指定默认输出,这样就不需要知道所要加载模块的变量名。


default只能有一个值,所以一个文件内不能有多个export defaul。


export default输出一个叫做default的变量,然后系统允许你为它取任意名字。所以可以为import的模块起任何变量名,且不需要用大括号包含export default写法顺序

name
components
props
data
created
methods
mounted
computed
watch

③ 子页面

子页面通过props接受父组件的传值:

<template>
  <div class="todo-footer">
    <label>
      <input type="checkbox" v-model="checkAll"/>
    </label>
    <span>
          <span>已完成{{completeSize}}</span> / 全部{{todos.length}}
        </span>
    <button class="btn btn-danger" v-show="completeSize" @click="deleteAllCompleted">清除已完成任务</button>
  </div>
</template>
<script>
  export default {
  //接收父组件的值传递与方法传递
    props: {
      todos: Array,
      deleteCompleteTodos: Function,
      selectAll: Function
    },
    computed: {
      completeSize () {
        return this.todos.reduce((preTotal, todo) => preTotal + (todo.complete?1:0) ,0)
      },
      checkAll: {
        get () { // 决定是否勾选
          return this.completeSize===this.todos.length && this.completeSize>0
        },
        set (value) {// 点击了全选checkbox  value是当前checkbox的选中状态(true/false)
          this.selectAll(value)
        }
      },
    },
    methods: {
      deleteAllCompleted () {
        if(window.confirm('确定清除已完成的吗?')) {
          this.deleteCompleteTodos()
        }
      }
    }
  }
</script>

【3】 props的三种写法

① 第一种简写

 export default {
    // 声明接收标签属性
    props: ['todos'], // 会成为当前组件对象的属性, 可以在模板中直接访问, 也可以通过this来访问
    components: {
      TodoItem
    }
  }


② 第二种写法

 export default {
    props: {// 指定属性名和属性值的类型
      todo: Object,
      index: Number
    }
}


第三种复杂写法

 export default {
    props: {
      todo: {
    type:Function,
    required:true,
     default: function () {
          return { message: 'hello' }
        },
     validator: function (value) {
            // 这个值必须匹配下列字符串中的一个
            return ['success', 'warning', 'danger'].indexOf(value) !== -1
          }
      },
      index: Number
    }
}


type:可以是下列原生构造函数中的一种:String、Number、Boolean、Array、Object、Date、Function、Symbol、任何自定义构造函数、或上述内容组成的数组


会检查一个 prop 是否是给定的类型,否则抛出警告。Prop 类型的更多信息如下所示:

props: {
  title: String,
  likes: Number,
  isPublished: Boolean,
  commentIds: Array,
  author: Object,
  callback: Function,
  contactsPromise: Promise // or any other constructor
}


default:any

为该 prop 指定一个默认值。如果该 prop 没有被传入,则换做用这个值。对象或数组的默认值必须从一个工厂函数返回。


required:Boolean

定义该 prop 是否是必填项。在非生产环境中,如果这个值为 truthy 且该 prop 没有被传入的,则一个控制台警告将会被抛出。

validator:Function

自定义验证函数会将该 prop 的值作为唯一的参数代入。在非生产环境下,如果该函数返回一个 falsy 的值 (也就是验证失败),一个控制台警告将会被抛出。你可以在这里查阅更多 prop 验证的相关信息。

props更多文档参考:https://cn.vuejs.org/v2/guide/components-props.html


【4】组件通信之消息发布订阅

消息订阅与发布(PubSubJS 库),此方式可实现任意关系组件间通信(数据)。

需要先安装PubSubJS 库,npm install --save pubsub-js

然后引入:

import PubSub from 'pubsub-js'


① 发布消息

PubSub.publish('msg', data)

触发事件(发布消息)

DOM 事件: 用户在浏览器上对应的界面上做对应的操作
自定义: 编码手动触发

实例如下:

 deleteItem () {
        // this.deleteTodo(this.index)
        // 发布消息(deleteTodo)
        PubSub.publish('deleteTodo', this.index)
      }


② 订阅消息

PubSub.subscribe('msg', function(msg, data){})

绑定事件监听(订阅消息)

目标: 标签元素<button>
事件名(类型): click/focus
回调函数: function(event){}


实例如下:

    mounted () {
      // 绑定自定义事件(addTodo)监听
      this.$refs.header.$on('addTodo',  this.addTodo)
      // 订阅消息(deleteTodo)
      PubSub.subscribe('deleteTodo', (msg, index) => {
        this.deleteTodo(index)
      })
    },


【5】组件间通信之slot

slot主要用于父组件向子组件传递标签数据。

父组件实例

<TodoFooter>
  <input slot="checkAll" type="checkbox" v-model="checkAll" />
  <span slot="size">已完成{{completeSize}} / 全部{{todos.length}}</span>
  <button slot="delete" class="btn btn-danger" v-show="completeSize" @click="deleteAllCompleted" >清除已完成任务</button>
</TodoFooter>


子组件实例

<template>
  <div class="todo-footer">
    <label>
      <!--<input type="checkbox" v-model="checkAll"/>-->
      <slot name="checkAll"></slot>
    </label>
    <span>
      <slot name="size"></slot>
     <!-- <span>已完成{{completeSize}} / 全部{{todos.length}}</span>-->
    </span>
    <slot name="delete"></slot>
   <!-- <button class="btn btn-danger" v-show="completeSize" @click="deleteAllCompleted">清除已完成任务</button>-->
  </div>
</template>


【6】自定义事件

① v-on指令监听事件

可以用 v-on 指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码。v-on:事件名, 可以缩写为: @事件名

事件修饰符

在事件处理程序中调用 event.preventDefault()event.stopPropagation() 是非常常见的需求。尽管我们可以在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。

为了解决这个问题,Vue.js 为 v-on 提供了事件修饰符。之前提过,修饰符是由点开头的指令后缀来表示的。

.stop
.prevent
.capture
.self
.once
.passive

代码示例如下

<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>
<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>
<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>



② 自定义事件监听

第一种方式

#给TodoHeader 标签对象绑定addTodo事件监听
<TodoHeader @addTodo="addTodo"/>

那么子组件如何触发事件呢?

//this.addTodo(todo)---原先使用props通信
/*触发自定义事件: addTodo*/
this.$emit('addTodo', todo)

第二种方式

<TodoHeader ref="header"/>
mounted () {
  // 绑定自定义事件(addTodo)监听
  this.$refs.header.$on('addTodo',  this.addTodo)
}

需要注意的是上面函数传递方式只适用于父-子,也就是A-B;A-B-C则不适用。



目录
相关文章
|
27天前
|
JavaScript API 开发者
Vue是如何进行组件化的
Vue是如何进行组件化的
|
24天前
|
缓存 JavaScript UED
Vue3中v-model在处理自定义组件双向数据绑定时有哪些注意事项?
在使用`v-model`处理自定义组件双向数据绑定时,要仔细考虑各种因素,确保数据的准确传递和更新,同时提供良好的用户体验和代码可维护性。通过合理的设计和注意事项的遵循,能够更好地发挥`v-model`的优势,实现高效的双向数据绑定效果。
126 64
|
3天前
|
JavaScript 关系型数据库 MySQL
基于VUE的校园二手交易平台系统设计与实现毕业设计论文模板
基于Vue的校园二手交易平台是一款专为校园用户设计的在线交易系统,提供简洁高效、安全可靠的二手商品买卖环境。平台利用Vue框架的响应式数据绑定和组件化特性,实现用户友好的界面,方便商品浏览、发布与管理。该系统采用Node.js、MySQL及B/S架构,确保稳定性和多功能模块设计,涵盖管理员和用户功能模块,促进物品循环使用,降低开销,提升环保意识,助力绿色校园文化建设。
|
24天前
|
前端开发 JavaScript 测试技术
Vue3中v-model在处理自定义组件双向数据绑定时,如何避免循环引用?
Web 组件化是一种有效的开发方法,可以提高项目的质量、效率和可维护性。在实际项目中,要结合项目的具体情况,合理应用 Web 组件化的理念和技术,实现项目的成功实施和交付。通过不断地探索和实践,将 Web 组件化的优势充分发挥出来,为前端开发领域的发展做出贡献。
29 8
|
24天前
|
JavaScript
在 Vue 3 中,如何使用 v-model 来处理自定义组件的双向数据绑定?
需要注意的是,在实际开发中,根据具体的业务需求和组件设计,可能需要对上述步骤进行适当的调整和优化,以确保双向数据绑定的正确性和稳定性。同时,深入理解 Vue 3 的响应式机制和组件通信原理,将有助于更好地运用 `v-model` 实现自定义组件的双向数据绑定。
|
27天前
|
缓存 监控 JavaScript
Vue.js 框架下的性能优化策略与实践
Vue.js 框架下的性能优化策略与实践
|
27天前
|
JavaScript 前端开发 API
Vue.js 3:深入探索组合式API的实践与应用
Vue.js 3:深入探索组合式API的实践与应用
|
27天前
|
JavaScript 前端开发 开发者
Vue是如何进行组件化的
Vue是如何进行组件化的
|
27天前
|
存储 JavaScript 前端开发
介绍一下Vue的核心功能
介绍一下Vue的核心功能
|
29天前
|
JavaScript 前端开发 开发者
vue 数据驱动视图
总之,Vue 数据驱动视图是一种先进的理念和技术,它为前端开发带来了巨大的便利和优势。通过理解和应用这一特性,开发者能够构建出更加动态、高效、用户体验良好的前端应用。在不断发展的前端领域中,数据驱动视图将继续发挥重要作用,推动着应用界面的不断创新和进化。
下一篇
DataWorks