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 相关文章推荐
两个SUBMIT按钮,如何区分处理
Aug 22 Javascript
仅IE6/7/8中innerHTML返回值忽略英文空格的问题
Apr 07 Javascript
jQuery的Ajax的自动完成功能控件简要说明
Feb 22 Javascript
jQuery 顶部导航跟随滚动条滚动固定浮动在顶部
Jun 06 Javascript
基于jQuery实现Ajax验证用户名是否存在实例
Mar 30 Javascript
深入理解JavaScript 函数
Jun 06 Javascript
javascript基于原型链的继承及call和apply函数用法分析
Dec 15 Javascript
解决element-ui中下拉菜单子选项click事件不触发的问题
Aug 22 Javascript
vue响应式系统之observe、watcher、dep的源码解析
Apr 09 Javascript
webpack中的模式(mode)使用详解
Feb 20 Javascript
解决vue单页面 回退页面 keeplive 缓存问题
Jul 22 Javascript
JS实现选项卡插件的两种写法(jQuery和class)
Dec 30 jQuery
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
论建造顺序的重要性
2020/03/04 星际争霸
全国FM电台频率大全 - 9 上海市
2020/03/11 无线电
php截取指定2个字符之间字符串的方法
2015/04/15 PHP
详解PHP用substr函数截取字符串中的某部分
2016/12/03 PHP
php获取字符串前几位的实例(substr返回字符串的子串用法)
2017/03/08 PHP
不用MOUSEMOVE也能滑动啊
2007/05/23 Javascript
jquery 屏蔽一个区域内的所有元素,禁止输入
2009/10/22 Javascript
extJs 常用到的增,删,改,查操作代码
2009/12/28 Javascript
js 弹出框 替代浏览器的弹出框
2010/10/29 Javascript
jQuery焦点图切换特效插件封装实例
2013/08/18 Javascript
点击显示指定元素隐藏其他同辈元素的方法
2014/02/19 Javascript
jQuery使用removeClass方法删除元素指定Class的方法
2015/03/26 Javascript
BootStrap中Datetimepicker和uploadify插件应用实例小结
2016/05/26 Javascript
ES6新特性之数组、Math和扩展操作符用法示例
2017/04/01 Javascript
解决vue初始化项目时,一直卡在Project description上的问题
2019/10/31 Javascript
如何构建 vue-ssr 项目的方法步骤
2020/08/04 Javascript
在vue中使用inheritAttrs实现组件的扩展性介绍
2020/12/07 Vue.js
[48:48]2014 DOTA2国际邀请赛中国区预选赛 SPD-GAMING VS Dream TIME
2014/05/21 DOTA
深入探究Django中的Session与Cookie
2017/07/30 Python
Python set常用操作函数集锦
2017/11/15 Python
python pygame实现2048游戏
2018/11/20 Python
python os.fork() 循环输出方法
2019/08/08 Python
Python中filter与lambda的结合使用详解
2019/12/24 Python
简单总结CSS3中视窗单位Viewport的常见用法
2016/02/04 HTML / CSS
HTML 5.1来了 9月份正式发布 更新内容预览
2016/04/26 HTML / CSS
德国骆驼商店:ActiveFashionWorld
2017/11/18 全球购物
英国IT硬件供应商,定制游戏PC:Mesh Computers
2019/03/28 全球购物
建筑工程技术应届生自荐信
2013/09/27 职场文书
施工协议书范本
2014/04/22 职场文书
学雷锋月活动总结
2014/04/25 职场文书
关爱残疾人演讲稿
2014/05/24 职场文书
详细的本科生职业生涯规划范文
2014/09/16 职场文书
工作失职检讨书范文
2015/05/05 职场文书
2016年五四青年节校园广播稿
2015/12/17 职场文书
浅谈resultMap的用法及关联结果集映射
2021/06/30 Java/Android
Python re.sub 反向引用的实现
2021/07/07 Python