创建自定义输入,Vue.js

基于组件的库或框架,如Vue公司给我们的精彩能够创建可重用的组件在他们各自的应用程序中传播,确保它们是一致的,并且(希望)简化如何使用它们。

特别是,表单输入往往有很多复杂的,你会希望在组件隐藏起来,比如定制设计,标签,验证,帮助信息,并确保每个片都以正确的顺序,使它们呈现正确。

编写可重用模块中ES6

你兴奋地利用新的JavaScript语言特性,但不知道哪里开始,或如何?阅读更多→

上,虽然之上,Vue公司有一个叫做内置指令v-model模拟2路结合通过结合一个值,并捕获输入事件。如果你要建立一个自定义输入组件,那么你肯定会想要支持的v-model指令。

可悲的是,当我环顾四周的单选按钮或复选框在Vue公司的自定义输入的例子,他们要么没有考虑v-model考虑所有,或他们没有正确地执行它。有一些像样的自定义文本输入的文档,但由于它没有解释自定义电台或复选框,我们将讨论这一点。

本教程旨在帮助你…

  1. 了解如何v-model在本地投入工作,主要侧重于收音机和复选框
  2. 了解如何v-model在默认情况下自定义组件的工作原理
  3. 了解如何创建自定义的复选框和收音机是模拟如何v-model对他们本身的工作原理

快速记在我们开始之前:ES2015 +代码将在整个代码示例中使用。我也有利于单个文件组件在使用语法Vue.componentnew Vue

如何v-model正常工作状态?

官方的Vue文件实际上是对这个话题相当不错的,但也有一些小的盲点。在任何情况下,我们将努力几乎完全是包括在这里。

从本质上说,v-model仅仅是一个速记指令,为我们提供了2路数据绑定,并且它的代码是简写形式,取决于它正在使用什么类型的输入。

文本框

<input v-model="message" placeholder="edit me">
<p>Message: {{ message }}</p>

<!-- OR -->

<p>message:</p>
<p style="white-space: pre-line">{{ message }}</p>
<textarea v-model="message" placeholder="add multiple lines"></textarea>

当使用文本input(包括类型,例如emailnumber等)或textareav-model="varName"等价于:value="varName" @input="e => varName = e.target.value"。这意味着,输入的值被设置为varName每次更新到输入后varName更新为输入的值。一个正常的select元素会像这样过,虽然multiple选择会有所不同。

单选按钮

那么,怎么样的单选按钮?

<input type="radio" value="One" v-model="picked">
<input type="radio" value="Two" v-model="picked">
<span>Picked: {{ picked }}</span>

这相当于:

<input type="radio" value="One" :checked="picked == 'One'" @change="e => picked = e.target.value">
<input type="radio" value="Two" :checked="picked == 'Two'" @change="e => picked = e.target.value">
<span>Picked: {{ picked }}</span>

注意如何v-model甚至没有接触value了。它仍然在做了同样的事情,change事件处理程序(虽然它改为change代替input),但现在它决定是否checked应该是真实的还是取决于是否错误picked是相同的单选按钮的值。

复选框

复选框是有点困难谈谈,因为他们有这取决于是否有只有一个复选框与给定的两种不同的行为v-model或多个。

如果您使用的是单个复选框,v-model将像对待一个布尔值,并忽略value

<input type="checkbox" value="foo" v-model="isChecked">

是相同的…

<input type="checkbox" value="foo" :checked="!!isChecked" @change="e => isChecked = e.target.checked">

如果你希望它是比其他的东西truefalse,你可以使用true-valuefalse-value属性,它控制哪些值你的模型将被设定,当复选框被选中或不。

<input type="checkbox" value="foo" v-model="isChecked" true-value="1" false-value="0">

是相同的…

<input type="checkbox" value="foo" :checked="isChecked == '1'" @change="e => isChecked = e.target.checked ? '1' : '0'">

这几乎是它的单选框例子。如果你有一个共享模型多个复选框,则这些复选框将填充数组与被检查所有复选框的值,但要确保你通过在模型中已经是一个数组,否则你会得到一些奇怪的行为。此外,true-valuefalse-value属性不再有任何影响。

<template>
  <div>
    <input type="checkbox" value="foo" v-model="checkedVals">
    <input type="checkbox" value="bar" v-model="checkedVals">
    <input type="checkbox" value="baz" v-model="checkedVals">
  </div>
</template>
<script>
  export default {
    data: () => ({
      checkedVals: ['bar']
    })
  }
</script>

等效是有点困难,以保持在模板中,所以我将一些逻辑移动到组件上的方法:

<template>
  <div>
    <input type="checkbox" value="foo" v-model="checkedVals">
    <input type="checkbox" value="bar" v-model="checkedVals">
    <input type="checkbox" value="baz" v-model="checkedVals">
  </div>
</template>
<script>
  export default {
    data() {
      return { checkedVals: ['bar'] }
    },
    methods: {
      shouldBeChecked(val) {
        return this.checkedVals.includes(val)
      },
      updateVals(e) {
        let isChecked = e.target.checked
        let val = e.target.value

        if (isChecked) {
          this.checkedVals.push(val)
        } else {
          this.checkVals.splice(this.checkedVals.indexOf(val), 1)
        }
      }
    }
  }
</script>

这是一个很多比我们以前看到更复杂,但如果你打破它,它也不是太糟糕。shouldBeCheckedtrue当被包括在阵列中该复选框的值,并且false,如果它不是。updateVals增加了复选框的值到数组时,它被选中并删除它时,它被选中。

如何v-model上工作的组件?

由于Vue公司不知道你的组件是如何工作的,或者如果它试图充当某种类型的输入的替代品,它把与问候到相同的所有组件v-model。它的实际工作,因为它确实为文本输入,但在事件处理程序,它并不期望一个事件对象传递给它,而它预计值传递直奔它完全相同的方式。所以…

<my-custom-component v-model="myProperty" />

…是同样的事情…

<my-custom-component :value="myProperty" @input="val => myProperty = val" />

一个组件可以更改为使用小的程度model属性:

export default {
  name: 'my-custom-component',
  model: {
    prop: 'foo',
    event: 'bar'
  },
  // ...
}

v-model将着眼于这些属性和,而不是使用value属性,它会使用在指定属性prop和而不是听的input情况下,它会使用在指定的事件event。所以上面的my-custom-component例子实际上扩大了以下几点:

<my-custom-component :foo="myProperty" @bar="val => myProperty = val" />

这是很好的,但如果我们正在做一个自定义的无线电或复选框,这并不能很好地工作。一段时间的努力,但是,我们可以移动的逻辑v-model上的收音机和复选框我们的自定义组件内部使用。

支持v-model在定制无线电

相比复选框,定制无线电是非常简单的。下面是我建,只是包装了一个很基本的自定义电台input在标签并接受label属性添加标签文本。

<template>
  <label>
    <input type="radio" :checked="shouldBeChecked" :value="value" @change="updateInput">
    {{ label }}
  </label>
</template>
<script>
export default {
  model: {
    prop: 'modelValue',
    event: 'change'
  },
  props: {
    value: {
      type: String,
    },
    modelValue: {
      default: ""
    },
    label: {
      type: String,
      required: true
    },
  },
  computed: {
    shouldBeChecked() {
      return this.modelValue == this.value
    }
  }
  methods: {
    updateInput() {
      this.$emit('change', this.value)
    }
  }
}
</script>

:我只包括props那些用于解释它们如何一起工作有帮助v-model,但是input标签可以采取的其他几个属性(如优势namedisabled),所以请确保您创建的所有props您需要,并将它们传递到input。您也想加入考虑无障碍 WAI-ARIA的属性,以及使用插槽用于添加内容,而不是像道具我在这里做label

你可能会认为,因为我没有包括name在这个例子中,一组无线电实际上不会彼此同步。实际上,模型的更新将依次更新共享模型中的其他单选按钮,所以他们并不需要像他们在纯HTML的形式做共享一个名字,只要它们共享相同的模型。

支持v-model在自定义复选框

制作自定义的复选框明显比单选按钮比较复杂,主要是因为我们要支持两种不同的使用情况:一个真/假复选框(可能会或可能不会使用true-value和/或false-value),并且所有的检查值组合成多个复选框数组。

那么,我们如何确定它是用例?你可能会认为,我们需要确定是否有其他复选框具有相同name的属性,但实际上并不是什么Vue公司的内置系统使用。就像收音机,Vue公司不走name的属性考虑的。当本地提交表单,这只是使用。所以,那么你可能会认为这决定它的基础上是否有共享同一模式的其他复选框,但这不是它的。它是由模型是否是一个数组确定。而已。

因此,代码将被结构类似于定制单选按钮的代码,但内部shouldBeCheckedupdateInput该逻辑将根据是否不分裂modelValue是一个数组。

<template>
<label>
<input type="checkbox" :checked="shouldBeChecked" :value="value" @change="updateInput">
{{ label }}
</label>
</template>
<script>
export default {
model: {
prop: 'modelValue',
event: 'change'
},
props: {
value: {
type: String,
},
modelValue: {
default: false
},
label: {
type: String,
required: true
},
// We set `true-value` and `false-value` to the default true and false so
// we can always use them instead of checking whether or not they are set.
// Also can use camelCase here, but hyphen-separating the attribute name
// when using the component will still work
trueValue: {
default: true
},
falseValue: {
default: false
}
},
computed: {
shouldBeChecked() {
if (this.modelValue instanceof Array) {
return this.modelValue.includes(this.value)
}
// Note that `true-value` and `false-value` are camelCase in the JS
return this.modelValue === this.trueValue
}
},
methods: {
updateInput(event) {
let isChecked = event.target.checked
if (this.modelValue instanceof Array) {
let newValue = [...this.modelValue]
if (isChecked) {
newValue.push(this.value)
} else {
newValue.splice(newValue.indexOf(this.value), 1)
}
this.$emit('change', newValue)
} else {
this.$emit('change', isChecked ? this.trueValue : this.falseValue)
}
}
}
}
</script>

有你有它。它可能会更好,不过,这种分成两个不同的部分组成:一个用于处理单真/假切换,一个用于在选项列表中使用。这将允许它更紧密地跟随单责任原则,但如果你正在寻找一个简易替换到复选框,这是你在找什么(加上另外所有其他有用的属性和定制功能你可能想)。

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/259331.html

(0)
上一篇 2022年5月21日
下一篇 2022年5月21日

相关推荐

发表回复

登录后才能评论