前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >16 处理表单数据与父子组件之间的数据交换

16 处理表单数据与父子组件之间的数据交换

作者头像
LIYI
发布2020-02-13 11:54:53
2.6K0
发布2020-02-13 11:54:53
举报
文章被收录于专栏:艺述论专栏
代码语言:javascript
复制
目录

处理表单输入
    1,单行文本
    2,多行文本textarea
    3,复选框checkbox
    4,单选按钮radio
    5,select下拉选择框
    6,所有input类型
父子组件的表单数据交换
    1,使用sync
    2,使用v-model模式

处理表单输入

vue开发中获取表单输入的值,不是像JQuery那样是主动查询一个Html组件,然后访问其属性,取得它的值。

vue获取表单输入的数据,是通过被动的方式。在vue组件有输入操作时,主动将数值绑定到data变量上;在提交表单前,从data数据源取得表单数据。

vue对有限个数的表单组件进行特别处理,包括:

1,单行文本

代码语言:javascript
复制
<!-- 单行文本 -->
<input type="text" v-model.trim="message" placeholder="edit me" />
<p>Message is: {{ message }}</p>

其input type为text。v-model.trim用于将用户输入值绑定在变量message上,trim这个修饰指令实现的是自动将输入值去除首尾空格。

v-model实现的是一种双向绑定。这是一种语法糖,上面的v-model相当于一个v-bind:value+一个v-on:input,如下所示:

代码语言:javascript
复制
<input v-bind:value="message" v-on:input="message=$event.target.value">

v-model代表的一定是属性value与事件input的结合。vue开发里所有支持v-model绑定的表单组件,都实现了对input事件的处理,即使原生的html组件没有input事件也是如此。

2,多行文本textarea

代码语言:javascript
复制
<p>{{ message1 }}</p>
<textarea @input="handleInput" v-model.lazy="message1" placeholder="add multiple lines"></textarea>

3,复选框checkbox

代码语言:javascript
复制
<!-- 复选框 -->
<p>
  <input @input="handleInput" type="checkbox" id="checkbox" v-model.number="checked" true-value="1" false-value="2" />
  <label for="checkbox">{{ checked }}</label>
</p>

其input type为checkbox。v-model.number用于将复选框选择的结果绑定到变量checked上,number修饰实现的是自动转换输入为数值类型。

true-value与false-value定义的是真、假数值,即选择与非选择时的取值,默认是true与false。但是需要注意,这两个属性定义的选项值都是字符串,所以在v-model上需要使用number修饰。

复选框支持多个放在一起,组合一组多选选项的集合:

代码语言:javascript
复制
<!-- 多个复选框 -->
<p>
  <input type="checkbox" id="checkbox1" v-model="checked2" value="value1" />
  <label for="checkbox1">value1</label>
  <input type="checkbox" id="checkbox2" v-model="checked2" value="value2" />
  <label for="checkbox2">value2</label>
  <input type="checkbox" id="checkbox3" v-model="checked2" value="value3" />
  <label for="checkbox3">value3</label>
  <br/>
  <span>Checked names: {{ checked2 }}</span>
</p>

多个checkbox放在一起,绑定到一个变量checked2上,就实现了多选效果。checked2的数据类型是一个数组。

4,单选按钮radio

代码语言:javascript
复制
<!-- 单选按钮 -->
<div>
  <input type="radio" id="one" value="One" v-model="picked" />
  <label for="one">One</label>
  <br />
  <input type="radio" id="two" value="Two" v-model="picked" />
  <label for="two">Two</label>
  <br />
  <input type="radio" id="three" value="Three" v-model="picked" />
  <label for="three">Three</label>
  <br />
  <span>Picked: {{ picked }}</span>
</div>

其input type为radio。

5,select下拉选择框

代码语言:javascript
复制
<!-- 选择框 -->
<div>
  <select v-model="selected">
    <option disabled value>请选择</option>
    <option :value="{ number: 1 }">1</option>
    <option :value="{ number: 2 }">2</option>
    <option :value="{ number: 3 }">3</option>
  </select>
  <span>Selected: {{ selected.number }}</span>
</div>

这是由select组件实现的,并不是input组件了。选项option的value支持绑定一个js对象,在这样设置时,select选择的结果selected也是一个js对象。

下拉选择框也同时多选:

代码语言:javascript
复制
<!-- 多选选择框 -->
<div>
  <select multiple v-model="selected2">
    <option disabled value>请选择</option>
    <option :value="{ number: 1 }">1</option>
    <option :value="{ number: 2 }">2</option>
    <option :value="{ number: 3 }">3</option>
  </select>
  <span>Selected: {{ selected2 }}</span>
</div>

给select添加multiple属性,下拉选择框就会默认展开,同时支持按住SHIFT多选,选择的结果selected2是一个数组。

6,所有input类型

上面仅是介绍了text、radio、checkbox三种input类型。事实上input组件功能十分丰富,它共有这些类型:

代码语言:javascript
复制
button	定义可点击的按钮(通常与 JavaScript 一起使用来启动脚本)。
checkbox	定义复选框。
colorNew	定义拾色器。
dateNew	定义 date 控件(包括年、月、日,不包括时间)。
datetimeNew	定义 date 和 time 控件(包括年、月、日、时、分、秒、几分之一秒,基于 UTC 时区)。
datetime-localNew	定义 date 和 time 控件(包括年、月、日、时、分、秒、几分之一秒,不带时区)。
emailNew	定义用于 e-mail 地址的字段。
file	定义文件选择字段和 "浏览..." 按钮,供文件上传。
hidden	定义隐藏输入字段。
image	定义图像作为提交按钮。
monthNew	定义 month 和 year 控件(不带时区)。
numberNew	定义用于输入数字的字段。
password	定义密码字段(字段中的字符会被遮蔽)。
radio	定义单选按钮。
rangeNew	定义用于精确值不重要的输入数字的控件(比如 slider 控件)。
reset	定义重置按钮(重置所有的表单值为默认值)。
searchNew	定义用于输入搜索字符串的文本字段。
submit	定义提交按钮。
telNew	定义用于输入电话号码的字段。
text	默认。定义一个单行的文本字段(默认宽度为 20 个字符)。
timeNew	定义用于输入时间的控件(不带时区)。
urlNew	定义用于输入 URL 的字段。
weekNew	定义 week 和 year 控件(不带时区)。

这些类型的input组件,都可以以一种自定义组件的方式使用之。

父子组件的表单数据交换

在vue开发中我们经常会需要定义一个子组件,然后在这个子组件中获取的表单数据,需要往父组件传递。这里有三种传递方法:

1,使用sync

子组件代码为:

代码语言:javascript
复制
<template>
  <input name="xxxx" v-model="currentValue" @input="handleModelInput" />
</template>
<script>
export default {
  name: "ModelComponent2",
  props: {
    value: [String, Number, Date]
  },
  methods: {
    handleModelInput() {
      this.$emit("update:value", this.currentValue);
    }
  },
  watch: {
    // 属性是只读的
    value(newValue) {
      this.currentValue = newValue;
    }
  },
  data: () => ({
    currentValue: ""
  })
};
</script>

在子组件中,使用v-model获取了原生input组件的输入,并绑定在currentValue变量之上。监听属性value,是为了将属性value的值,极时同步到变量currentValue上,因为vue的属性是单向的,并不能将一个属性用于v-model。

v-model会自动更新输入值到变量currentValue上,但不会自动派发事件。所以我们需要将input事件绑定到函数handleModelInput上,当输入变化时,在当前自定义组件内主动派发一个"update:value"事件,这个事件名称采用的是"update:"+属性名称的格式,是一个vue语法约定。

父组件代码为:

代码语言:javascript
复制
<p>
<SyncComponent1 :value.sync="text1" ></SyncComponent1>
text1:{{text1}}
</p>

运行效果:

使用这种sync模式,假设属性为xxx,要求为:

代码语言:javascript
复制
1,在子组件中当属性变化时,主动派发一个“update:xxx”事件,并附带xxx的值
2,在父组件中,使用:xxx.sync将数据双向绑定到一个data变量上

在这里有一个问题,v-model与sync有什么区别呢?貌似两者实现的功能是一样的,sync实现的效果v-model也能实现。

不同点在于v-model用于表单数据绑定,指定了属性名为value,事件名为input,不能变。而sync模式,在属性名称的设置上,在事件的派发时机上都比较灵活。

2,使用v-model模式

既然默认的vue表单组件可以实现v-model双向绑定,自定义组件同样也能实现。

子组件代码为:

代码语言:javascript
复制
<template>
  <input name="xxxx" v-model="currentValue" @input="handleModelInput" />
</template>
<script>
export default {
  name: "SyncComponent2",
  props: {
    value: [String, Number]
  },
  methods: {
    handleModelInput() {
      this.$emit("input", this.currentValue);
    }
  },
  watch: {
    // 属性是只读的
    value(newValue) {
      this.currentValue = newValue;
    }
  },
  data: () => ({
    currentValue: ""
  })
};
</script>

父组件代码为:

代码语言:javascript
复制
<p>
<SyncComponent2 v-model="text2" ></SyncComponent2>
text2:{{text2}}
</p>

运行效果与方法1是一样的。可以看到父组件代码没有变化。变化的是子组件代码,不再派发"update:value"事件了,取而代之的是派发input事件。这样在父组件中,子组件就被装扮成了和其它vue表单组件一样了,也可以直接使用v-model进行双向绑定了。

3,在子组件中使用model

如果我不想或不方便派发input事件或update:xxx事件,怎么办?也有方法。可以使用model。

子组件代码:

代码语言:javascript
复制
<template>
  <input name="xxxx" v-model="currentValue" @input="handleModelInput" />
</template>
<script>
export default {
  name: "SyncComponent3",
  model: {
   prop: 'value',
   event: 'change'
  },
  props: {
    value: [String, Number]
  },
  methods: {
    handleModelInput() {
      // 与aync模式相比,发射的事件不同
      this.$emit("change", this.currentValue);
    }
  },
  watch: {
    // 属性是只读的
    value(newValue) {
      this.currentValue = newValue;
    }
  },
  data: () => ({
    currentValue: ""
  })
};
</script>

model充许自定义一个属性名称和事件名称,例如value和change,这样当在子组件中派发change事件时,在父组件中可以像方法2那样使用子组件:

代码语言:javascript
复制
<SyncComponent3 v-model="text3" ></SyncComponent3>
text3:{{text3}}
</p>

源码

本文涉及的源码可以从这里下载:

https://git.code.tencent.com/shiqiaomarong/vue-go-rapiddev-example/tags/v20200112

参考链接

  • http://www.fly63.com/article/detial/701
  • https://www.jb51.net/article/142657.htm
  • https://cn.vuejs.org/v2/guide/components-custom-events.html#自定义组件的-v-model
  • https://cn.vuejs.org/v2/guide/forms.html#在组件上使用-v-model
  • https://cn.vuejs.org/v2/guide/forms.html
  • https://www.runoob.com/tags/att-input-type.html
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-01-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 艺述论 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 处理表单输入
    • 1,单行文本
      • 2,多行文本textarea
        • 3,复选框checkbox
          • 4,单选按钮radio
            • 5,select下拉选择框
              • 6,所有input类型
              • 父子组件的表单数据交换
                • 1,使用sync
                  • 2,使用v-model模式
                    • 3,在子组件中使用model
                    • 源码
                    • 参考链接
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档