Vue表单类的父子组件数据传递示例


Posted in Javascript onMay 03, 2018

使用Vue.js进行项目开发,那必然会使用基于组件的开发方式,这种方式的确给开发和维护带来的一定的便利性,但如果涉及到组件之间的数据与状态传递交互,就是一件麻烦事了,特别是面对有一大堆表单的页面。

在这里记录一下我平时常用的处理方式,这篇文章主要记录父子组件间的数据传递,非父子组件主要通过Vuex处理,这篇文章暂时不作说明。

与文档里给的方案一样,父组件向子组件传递数据主要通过 props,子组件向父组件传递数据主要通过触发器 $emit(),只是在用法上会有些不同。

1、传递基本类型数据

当子组件内容较少时,会直接传递基本类型数据,通常为String, Number, Boolean三种。

先看个例子:

<!-- 父组件 parent.vue -->

<template>
  <div class="parent">
    <h3>问卷调查</h3>
    <child v-model="form.name"></child>
    <div class="">
      <p>姓名:{{form.name}}</p>
    </div>
  </div>
</template>

<script>
  import child from './child.vue'

  export default {
    components: {
      child
    },
    data () {
      return {
        form: {
          name: '请输入姓名'
        }
      }
    }
  }
</script>
<!-- 子组件 child.vue -->

<template>
  <div class="child">
    <label>
      姓名:<input type="text" :value="currentValue" @input="changeName">
    </label>
  </div>
</template>

<script>
  export default {
    props: {
      // 这个 prop 属性必须是 valule,因为 v-model 展开所 v-bind 的就是 value
      value: ''
    },
    methods: {
      changeName (e) {
        // 给input元素的 input 事件绑定一个方法 changeName 
        // 每次执行这个方法的时候都会触发自定义事件 input,并且把输入框的值传递进去。
        this.$emit('input', e.target.value)
      }
    }
  }
</script>

给子组件的 input 事件绑定一个方法 changeName,每次执行这个方法的时候都会触发自定义事件 input,并且把输入框的值传递进去。

父组件通过 v-model 指令绑定一个值,来接收子组件传递过来的数据。但这样只是父组件响应子组件的数据,如果还要子组件响应父组件传递的数据,就需要给子组件定义一个props属性 value,并且这个属性必须是 value,不能写个其它单词。

v-model 其实就是一个语法糖,详情可以参考使用自定义事件的表单输入组件。

2、传递引用类型数据

当子组件里的内容比较多时,比如子组件有多个表单元素,如果还像上面那样给每个表单元素绑定值,那就要写很多重复代码了。所以这个时候通常传递的是一个对象,传值的基本原理不变,不过写法上会有些不同。

还是先看代码:

<!-- 父组件 parent.vue -->

<template>
  <div class="parent">
    <h3>问卷调查</h3>
    <child :formData.sync="form"></child>
    <div class="">
      <p>姓名:{{form.name}}</p>
    </div>
  </div>
</template>

<script>
  import child from './child.vue'

  export default {
    components: {
      child
    },
    data () {
      return {
        form: {
          name: '请输入姓名',
          age: '21'
        }
      }
    }
  }
</script>
<!-- 子组件 child.vue -->

<template>
  <div class="child">
    <label>
      姓名:<input type="text" v-model="form.name">
    </label>
    <label>
      年龄:<input type="text" v-model="form.age">
    </label>
    <label>
      地点:<input type="text" v-model="form.address">
    </label>
  </div>
</template>

<script>
  export default {
    data () {
      return {
        form: {
          name: '',
          age: '',
          address: ''
        }
      }
    },
    props: {
      // 这个 prop 属性接收父组件传递进来的值
      formData: Object
    },
    watch: {
      // 因为不能直接修改 props 里的属性,所以不能直接把 formData 通过v-model进行绑定
      // 在这里我们需要监听 formData,当它发生变化时,立即将值赋给 data 里的 form
      formData: {
        immediate: true,
        handler (val) {
          this.form = val
        }
      }
    },
    mounted () {
      // props 是单向数据流,通过触发 update 事件绑定 formData,
      // 将 data 里的 form 指向父组件通过 formData 绑定的那个对象
      // 父组件在绑定 formData 的时候,需要加上 .sync
      this.$emit('update:formData', this.form)
    }
  }
</script>

props 是单向数据流,当我们需要对 props 内的属性进行双向绑定时,就需要用到.sync 修饰符,详情请参考.sync 修饰符,这里不做赘述。

这里需要注意的是,vue 中是不能直接修改 props 的,所以如果我们要向父组件传值,还是需要通过修改 data 里的值,prop 只是作为父子之间通话的中间人存在。

另外,如果我们想要预览父组件最开始传的数据,就需要通过 watch 监听 prop 的变化,在子组件初始化的时候就把值传进去。

注意: 我在子组件里把 this.$emit('update:formData', this.form) 放在 mounted 当中的,其原因是为了避免在每个 input 标签的 input 事件中触发自定义事件,但这样写的前提是,父子组件都要共用一个对象。

这也就是上面代码中,父组件中使用 :formData.sync="form" 绑定值时,form 是一个对象,而子组件中的触发自定义事件 this.$emit('update:formData', this.form) ,this.form 也得是一个对象。

这里还需要注意的是,如果有多个子组件使用一个对象,那就要避免这种写法,因为一个组件修改了这个对象的数据,那么其它子组件也就都跟着改变了。

所以我在用的时候都是给每个子组件分配了一个自己的对象,比如:

data () {
 return {
  parentObject: {
   child_1_obj: {},
   child_2_obj: {},
  }
 }
}

这是在父组件里定义的数据,当然名字不会这样取了。

结尾

也没什么说的了,对 Vue 还是处于使用的阶段,对其底层的东西了解还不够,我也好想读读源码,但总只是想想.....大家觉得有什么不妥的地方尽管说,大家相互交流交流。

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

Javascript 相关文章推荐
显示js对象所有属性和方法的函数
Oct 16 Javascript
JavaScript取得鼠标绝对位置程序代码介绍
Sep 16 Javascript
JS链式调用的实现方法
Mar 07 Javascript
jquery实现的图片点击滚动效果
Apr 29 Javascript
JQuery给元素绑定click事件多次执行的解决方法
May 29 Javascript
JS组件Bootstrap Table布局详解
May 27 Javascript
微信小程序之网络请求简单封装实例详解
Jun 28 Javascript
Vue中封装input组件的实例详解
Oct 17 Javascript
swiper动态改变滑动内容的实现方法
Jan 17 Javascript
angularJs复选框checkbox选中进行ng-show显示隐藏的方法
Oct 08 Javascript
vue基于viewer实现的图片查看器功能
Apr 12 Javascript
JavaScript事件冒泡机制原理实例解析
Jan 14 Javascript
Webpack path与publicPath的区别详解
May 03 #Javascript
Webpack中publicPath路径问题详解
May 03 #Javascript
Angular Renderer (渲染器)的具体使用
May 03 #Javascript
react router4+redux实现路由权限控制的方法
May 03 #Javascript
vue.js学习笔记之v-bind和v-on解析
May 03 #Javascript
jQuery实现每隔一段时间自动更换样式的方法分析
May 03 #jQuery
详解VueJs中的V-bind指令
May 03 #Javascript
You might like
编写自己的php扩展函数
2006/10/09 PHP
PHP获取和操作配置文件php.ini的几个函数介绍
2013/06/24 PHP
php上传图片客户端和服务器端实现方法
2015/03/30 PHP
PHP输出多个元素的排列或组合的方法
2017/03/14 PHP
PHP函数用法详解【初始化、嵌套、内置函数等】
2020/06/02 PHP
用js得到网页中所有的div的id
2020/10/19 Javascript
Javascript实现div的toggle效果实例分析
2015/06/09 Javascript
自定义vue全局组件use使用、vuex的使用详解
2017/06/14 Javascript
vue+node实现图片上传及预览的示例方法
2018/11/22 Javascript
详解在React-Native中持久化redux数据
2019/05/22 Javascript
[48:11]完美世界DOTA2联赛 Magma vs GXR 第二场 11.07
2020/11/10 DOTA
使用python提取html文件中的特定数据的实现代码
2013/03/24 Python
python网络编程学习笔记(七):HTML和XHTML解析(HTMLParser、BeautifulSoup)
2014/06/09 Python
python和flask中返回JSON数据的方法
2018/03/26 Python
Python实现读取机器硬件信息的方法示例
2018/06/09 Python
PyQtGraph在pyqt中的应用及安装过程
2019/08/04 Python
Python自动化导出zabbix数据并发邮件脚本
2019/08/16 Python
python selenium操作cookie的实现
2020/03/18 Python
python数据类型强制转换实例详解
2020/06/22 Python
pytest fixtures装饰器的使用和如何控制用例的执行顺序
2021/01/28 Python
python使用Windows的wmic命令监控文件运行状况,如有异常发送邮件报警
2021/01/30 Python
纯CSS3实现鼠标滑过按钮动画第二节
2020/07/16 HTML / CSS
SEPHORA丝芙兰捷克官网:购买香水、化妆品和护肤品
2018/11/26 全球购物
Interrail法国:乘火车探索欧洲,最受欢迎的欧洲铁路通票
2019/08/27 全球购物
您在慕尼黑的跑步商店:Lauf-bar
2019/10/11 全球购物
澳大利亚领先的在线礼品网站:Gifts Australia
2020/08/15 全球购物
Yahoo-PHP面试题4
2012/05/05 面试题
《最大的麦穗》教学反思
2014/04/17 职场文书
我的祖国演讲稿
2014/05/04 职场文书
党建工作经验交流材料
2014/05/25 职场文书
湖南省召开党的群众路线教育实践活动总结大会报告
2014/10/21 职场文书
大学生就业推荐表自我评价
2015/03/02 职场文书
篮球赛闭幕式主持词
2015/07/03 职场文书
会议室管理制度范本
2015/08/06 职场文书
使用Nginx+Tomcat实现负载均衡的全过程
2022/05/30 Servers
 python中的元类metaclass详情
2022/05/30 Python