Vue.js面向初学者,第10课:表格

今天,在Vue课程的第10课中,我们将讨论如何使用表单。表格使您可以收集用户输入。另外,这里我们将讨论表单验证,即检查输入的内容。







Vue.js初学者课程1:实例Vue

Vue.js初学者,课程2:绑定属性

Vue.js初学者课程3:条件渲染

Vue.js初学者课程4:列表渲染

Vue .js初学者课程5:事件处理

Vue.js初学者课程6:绑定类和样式

Vue.js初学者课程7:计算的属性

Vue.js初学者课程8:组件

Vue。初学者第9课js:自定义事件



本课目的



我们将创建一个允许站点访问者提交产品评论的表单。同时,只有在填写表格的所有字段(必须填写)时,才可以发送审阅。



初始码



这是现在的内容index.html



<div id="app">
  <div class="cart">
    <p>Cart({{ cart.length }})</p>
  </div>

  <product :premium="premium" @add-to-cart="updateCart"></product>
</div>


看起来像这样main.js



Vue.component('product', {
  props: {
    premium: {
      type: Boolean,
      required: true
    }
  },
  template: `
  <div class="product">
    <div class="product-image">
      <img :src="image" />
    </div>

    <div class="product-info">
      <h1>{{ title }}</h1>
      <p v-if="inStock">In stock</p>
      <p v-else>Out of Stock</p>
      <p>Shipping: {{ shipping }}</p>

      <ul>
        <li v-for="detail in details">{{ detail }}</li>
      </ul>
      <div
        class="color-box"
        v-for="(variant, index) in variants"
        :key="variant.variantId"
        :style="{ backgroundColor: variant.variantColor }"
        @mouseover="updateProduct(index)"
      ></div>

      <button
        v-on:click="addToCart"
        :disabled="!inStock"
        :class="{ disabledButton: !inStock }"
      >
        Add to cart
      </button>

    </div>
  </div>
  `,
  data() {
    return {
      product: 'Socks',
      brand: 'Vue Mastery',
      selectedVariant: 0,
      details: ['80% cotton', '20% polyester', 'Gender-neutral'],
      variants: [
        {
          variantId: 2234,
          variantColor: 'green',
          variantImage: './assets/vmSocks-green.jpg',
          variantQuantity: 10
        },
        {
          variantId: 2235,
          variantColor: 'blue',
          variantImage: './assets/vmSocks-blue.jpg',
          variantQuantity: 0
        }
      ]
    }
  },
    methods: {
      addToCart() {
        this.$emit('add-to-cart', this.variants[this.selectedVariant].variantId);
      },
      updateProduct(index) {
        this.selectedVariant = index;
        console.log(index);
      }
    },
    computed: {
      title() {
        return this.brand + ' ' + this.product;
      },
      image() {
        return this.variants[this.selectedVariant].variantImage;
      },
      inStock() {
        return this.variants[this.selectedVariant].variantQuantity;
      },
      shipping() {
        if (this.premium) {
          return "Free";
        } else {
          return 2.99
        }
      }
    }
})

var app = new Vue({
  el: '#app',
  data: {
    premium: true,
    cart: []
  },
  methods: {
    updateCart(id) {
      this.cart.push(id);
    }
  }
})


任务



我们希望网站访问者能够对产品发表评论,但是我们的网站尚无法从用户那里接收数据。形式就是这样的手段。



问题的解决



为了解决摆在我们面前的任务,我们需要创建一个表单。让我们从创建一个专门用于表单的新组件开始。让我们将此组件称为product-review。选择该名称是因为该组件将支持用于收集产品评论的表单。该组件product-review将嵌套在component中product



让我们注册一个新组件,开始形成其模板并为其配备一些数据:



Vue.component('product-review', {
  template: `
    <input>
  `,
  data() {
    return {
      name: null
    }
  }
})


如您所见,组件模板中有一个元素,而<input>组件数据中有一个属性data,而该属性为空。



如何将用户在字段中输入的内容绑定到属性name



在上一课中,我们讨论了使用指令的数据绑定v-bind,但是随后我们仅考虑了单向绑定。数据流从存储数据的属性转到呈现数据的控件。现在,我们需要用户在字段中输入的内容位于name存储在组件数据中的属性中。换句话说,我们希望将数据流从输入字段定向到属性。



V模型指令



该指令v-model允许组织双向数据绑定。通过这种工作方案,如果输入字段中出现新的内容,则会导致数据更改。并且,因此,当数据改变时,使用该数据的控件的状态被更新。



让我们在输入字段中添加一个指令,并将该字段v-model绑定到name组件数据中的属性



<input v-model="name">


现在,将完整的表单代码添加到组件模板中:



<form class="review-form" @submit.prevent="onSubmit">
  <p>
    <label for="name">Name:</label>
    <input id="name" v-model="name" placeholder="name">
  </p>

  <p>
    <label for="review">Review:</label>
    <textarea id="review" v-model="review"></textarea>
  </p>

  <p>
    <label for="rating">Rating:</label>
    <select id="rating" v-model.number="rating">
      <option>5</option>
      <option>4</option>
      <option>3</option>
      <option>2</option>
      <option>1</option>
    </select>
  </p>

  <p>
    <input type="submit" value="Submit">  
  </p>

</form>


正如你所看到的,v-model领域inputtextarea并且都配备了指令select。请注意,在设置字段时select,使用了修饰符.number(我们将在下面更详细地讨论它)。这允许将相应的数据转换为type Number,而通常以字符串形式显示。



让我们通过向其添加绑定上述控件的数据来补充组件的数据集:



data() {
  return {
    name: null,
    review: null,
    rating: null
  }
}


在表单模板的顶部,您可以看到提交表单时会调用方法onSubmit。我们将很快创建此方法。但首先,让我们谈谈建筑的作用.prevent



这是一个事件修饰符。它防止事件发生后重新加载页面submit。还有其他有用的事件修饰符。是的,我们不会谈论它们。



现在我们准备创建一个方法onSubmit。让我们从下面的代码开始:



onSubmit() {
  let productReview = {
    name: this.name,
    review: this.review,
    rating: this.rating
  }
  this.name = null
  this.review = null
  this.rating = null
}


如您所见,此方法基于用户输入的数据创建一个对象。对它的引用将写入变量productReview。在这里,我们顺路null属性值namereviewrating。但是工作还没有结束。我们仍然需要发送到某个地方productReview。该对象发送到哪里?



将产品评论存储在存储组件数据的位置很有意义product。考虑到组件product-review嵌套在组件内product,我们可以说它product-review是组件的子代product。正如我们在上一课中学到的,您可以使用通过将事件从子组件发送到父组件所生成的事件$emit



让我们完善一下方法onSubmit



onSubmit() {
  let productReview = {
    name: this.name,
    review: this.review,
    rating: this.rating
  }
  this.$emit('review-submitted', productReview)
  this.name = null
  this.review = null
  this.rating = null
}


现在,我们生成一个带有名称的事件,review-submitted并在其中传递新创建的对象productReview



接下来,我们需要通过在模板中放置product以下内容来组织侦听此事件



<product-review @review-submitted="addReview"></product-review>


该行的内容如下:“发生事件时review-submitted,需要运行addReviewcomponent方法product。”



这是此方法的代码:



addReview(productReview) {
  this.reviews.push(productReview)
}


该方法获取productReview来自该方法的对象onSubmit然后将其放入reviews存储在组件数据中的数组product但是该组件的数据中还没有这样的数组。因此,我们将其添加到此处:



reviews: []


精彩!现在,表单元素已绑定到组件数据product-review此数据用于创建对象productReview提交表单后,此对象将传递给component product结果,将对象productReview添加到数组reviews,该数组存储在组件数据中product



显示产品评论



现在,仅保留在产品页面上显示站点访问者留下的评论。我们将product通过在组件中放置相应代码的代码上方放置相应的代码来在组件product-review中执行此操作product



<div>
 <h2>Reviews</h2>
 <p v-if="!reviews.length">There are no reviews yet.</p>
 <ul>
   <li v-for="review in reviews">
   <p>{{ review.name }}</p>
   <p>Rating: {{ review.rating }}</p>
   <p>{{ review.review }}</p>
   </li>
 </ul>
</div>


在这里,我们使用指令创建评论列表,v-forreview使用点符号显示存储在对象中的数据。 



在标签中,<p>我们检查数组中是否有东西reviews(通过检查其长度)。如果数组中没有任何内容,我们将输出一条消息There are no reviews yet





反馈表页面



表格验证



表单通常包含必须在提交表单之前填写的字段。例如,我们不希望用户提交评论文本字段为空的评论。



幸运的是,HTML5支持required它的用法如下所示:



<input required >


如果用户尝试提交其中必填字段为空的表单,则这种构造将导致自动显示错误消息。





错误消息



在浏览器中拥有标准的表单字段验证器非常好,因为它可以使我们摆脱创建自己的字段验证器的负担。但是在某些特殊情况下,执行标准数据检查的方式可能不适合我们。在这种情况下,编写自己的表单验证代码很有意义。



自定义表格验证



让我们谈谈如何创建自己的表单验证系统。



让我们包括一个product-review用于将错误消息存储到组件数据中的数组。让我们称之为errors



data() {
  return {
    name: null,
    review: null,
    rating: null,
    errors: []
  }
}


我们想向该数组添加有关在表单字段为空的情况下发生的错误的信息。我们正在谈论以下代码:



if(!this.name) this.errors.push("Name required.")
if(!this.review) this.errors.push("Review required.")
if(!this.rating) this.errors.push("Rating required.")


这些行的第一行告诉系统如果该字段name为空,则将errors错误消息放入数组中Name required。验证review字段的其他字符串也类似地工作rating。如果其中任何一个为空,array则会将错误消息发送到array



这段代码放在哪里?



因为我们希望时,才尝试提交表单时,事实证明,这些字段是错误消息被写入到阵列namereview或者submit未填写,我们可以把该方法的代码onSubmit。此外,我们将重写其中的代码,并对其进行一些检查:



onSubmit() {
  if(this.name && this.review && this.rating) {
    let productReview = {
      name: this.name,
      review: this.review,
      rating: this.rating
    }
    this.$emit('review-submitted', productReview)
    this.name = null
    this.review = null
    this.rating = null
  } else {
    if(!this.name) this.errors.push("Name required.")
    if(!this.review) this.errors.push("Review required.")
    if(!this.rating) this.errors.push("Rating required.")
  }
}


现在我们检查字段namereviewrating如果所有这些字段中都有数据,我们将基于它们创建一个对象productReview,并将其发送到父组件。然后,重置相应的属性。



如果至少一个字段为空,则在数组中放置errors一条错误消息,具体取决于用户在提交表单之前未输入的内容。



剩下的就是显示这些错误,可以使用以下代码完成:



<p v-if="errors.length">
  <b>Please correct the following error(s):</b>
  <ul>
    <li v-for="error in errors">{{ error }}</li>
  </ul>
</p>


这里使用v-if一个伪指令,通过该伪指令我们检查数组errors中是否存在错误消息(实际上,我们分析了数组的长度)。如果数组中有东西,则会显示一个元素,该元素<p>在应用v-for时会显示array中的错误列表errors





错误消息



我们现在有自己的表单验证系统。



使用.number修饰符



.number指令中使用 的修饰符v-model可能非常有用。但是,请记住,使用它存在一个问题。如果相应的值为空,则将其表示为字符串,而不是数字。Vue的食谱书提供了一个解决这个问题。它包含将相应的值显式转换为数字类型:



Number(this.myNumber)


作坊



在表单中添加以下问题:“您会推荐此产品吗?” 进行设置,以便用户可以使用“是”和“否”单选按钮进行回答。检查该问题的答案,并在对象中包括相关数据productReview



  • 这是您可以用来解决此问题模板。
  • 这是解决问题的方法。


结果



今天,我们讨论了使用表单的问题。这是您今天学到的最重要的东西:



  • 您可以使用指令来组织表单元素的双向数据绑定v-model
  • 修饰符.number告诉Vue将对应的值转换为数字类型。但是使用它时,存在一个与空值仍然是字符串有关的问题。
  • 事件修饰符.prevent使您可以防止在提交表单后重新加载页面。
  • 使用Vue,您可以实现相当简单的机制来进行自定义表单验证。


你今天有功课吗



Vue.js初学者课程1:实例Vue

Vue.js初学者,课程2:绑定属性

Vue.js初学者课程3:条件渲染

Vue.js初学者课程4:列表渲染

Vue .js初学者课程5:事件处理

Vue.js初学者课程6:绑定类和样式

Vue.js初学者课程7:计算的属性

Vue.js初学者课程8:组件

Vue。初学者第9课js:自定义事件






All Articles