专栏名称: 图雀社区
一只图雀 @ 公众号「图雀社区」
目录
相关文章推荐
何夕  ·  #a股# ... ·  昨天  
并购优塾产业链地图  ·  32亿并购过会!能源互联网并购跟踪:朗新集团 ... ·  3 天前  
人生资本论  ·  一把手罕见强调:绝不手软,绝不姑息 ·  2 天前  
51好读  ›  专栏  ›  图雀社区

从零到部署:用 Vue 和 Express 实现迷你全栈电商应用(三)

图雀社区  · 掘金  ·  · 2020-01-06 06:34

正文

阅读 207

从零到部署:用 Vue 和 Express 实现迷你全栈电商应用(三)

这篇文章中,我们将讲解 Vue 实例的 Props 和 Methods,接着我们又讲解了最常见的 Vue 模板语法,并通过实例的方式将这些模板语法都实践了一番,最后我们讲解了 Vue 组件的组合,并完成了我们的发表商品页面。

欢迎阅读《从零到部署:用 Vue 和 Express 实现迷你全栈电商应用》系列:

用模板语法和双向绑定实现数据的添加

当我们完成了商城应用的基本页面框架之后,我们就可以开始考虑具体页面的内容了。首先我们要考虑的就是数据的来源,即添加商品页面。有了添加商品的入口,我们就可以展示商品列表,获取商品详情,甚至是修改商品信息。

不过在此之前,我们打算先复习一下 Vue 的一些重要知识点。如果你已经很熟悉了,可以直接跳到下面实现 ProductForm.vue 的代码部分。

Vue 实例:Props 和 Methods

Props

props 是 Vue 进行组件之间传参的形式。比如我们有如两个组件 New.vue ProductForm.vue ,在 New.vue 组件中需要使用到 ProductForm.vue 组件。其中 New.vue 组件是用来创建商品的,它的代码大致是这样的:

import ProductForm from '@/components/ProductForm.vue';

<ProductForm :manufacturers="manufacturers" />
复制代码

它需要给 ProductForm.vue 组件传递一个 manufacturers 属性,以确保我们在创建商品时,可以选择这个商品所属的制造商,接着我们就可以在 ProductForm.vue 中的 props 中取到这个 manufacturers 属性。 ProductForm.vue 的代码大致是这样的:

<template>
<!-- 模板部分 -->
</template>

<script>
export default {
  props: ['manufacturers'],
}
</script>
复制代码

可以看到,我们在 ProductForm.vue script 部分导出的对象里面找到 props 属性,然后取到 manufacturers 属性。

Methods

然后是 methods methods 是用来定义在组件中会用到的一些方法,如果说我们前面提到的 data ,是从数据从逻辑层(JS)向视图层(Html)流动的话,那么这里的 methods 就是视图层触发事件,如 click、submit等,反过来修改逻辑层的数据的方法, methods 使得数据可以双向流动。

让我们在完善一下我们的 ProductForm.vue ,看一下 Methods 在 Vue 中是如何运作的:

<template>
<form @submit.prevent="saveProduct">
<!-- 其他表单,如 input 等 -->

<div class="form-group new-button">
  <button class="button">Add Product</button>
</div>
</form>
</template>

<script>
export default {
  data: { isSaved: false },
  props: ['manufacturers'],
  methods: {
    saveProduct() {
       this.isSaved = true;

      // 完成一些保存创建商品的逻辑 ...
    }
  }
}
</script>
复制代码

可以看到,我们可以通过在 template (视图层)通过点击提交按钮,发起表单提交事件,进而调用在 script 中定义在 methods 属性中的 saveProduct 方法,这个方法可以进一步修改定义在定义在 data 属性中的数据;甚至如果父组件 New.vue 传递了方法(以 props 的形式)给 ProductForm.vue 组件,我们可在 saveProduct 调用这个传递下来的方法,进而可以影响到父组件 New.vue 中的数据。我们将在后面的正式实现 ProductForm 组件时讲解到它。

模板语法:v-on

接下来我们再来谈一谈 v-bind 和 v-on 。

在 Vue 中,我们通过 v-on 的方式接管了之前在 HTML 中 onEvent

比如之前我们在 HTML 中的写法是这样的:

<div onclick="alert('I love tuture')">
Hello Tuture
</div>
复制代码

现在在 Vue 的模板语法中我们需要写出这样:

<div v-on:click="alert('I love tuture')">
Hello Tuture
</div>
复制代码

类似的 onEvent 都要改成 v-on:Event 。然后这样写显得比较冗余,所以 Vue 支持简化写法,用 @ 替换 v-on: 部分,我们就可以写出这样:

<div @click="alert('I love tuture')">
Hello Tuture
</div>
复制代码

调用事件之后我们一般有一些这样的操作,比如禁用浏览器默认行为,然后自己去处理事件,获取后端数据,以前我们会这样写:

<div onclick="saveProduct()">
Hello Tuture

<script>
var saveProduct = function (e) {
  e.preventDefault();

  // do something you like
}
</script>
复制代码

但是这样写又显得特别繁琐了,Vue 也觉得这样可以简化,于是我们直接将这些禁止默认行为的调用作为绑定事件的属性来进行处理,于是乎在 Vue 中我们可以写出这样:

<template>
  <div @click.prevent="saveProduct">
  Hello Tuture
  </div>
</template>

<script>
export default {
  methods: {
    saveProduct() {
      // do something you like
    }
  }
}
</script>
复制代码

不知道看了上面的长文,你有没有一点晕,不管你晕不晕,我是得喝口水缓一下。 - v -

模板语法:v-bind

我们已经看到在 Vue 模板中我们可以使用如下的功能:

  • {{}} 插值语法将 data 渲染到 HTML 元素内容中
  • v-on 或者简化写法 @ ,等用来取代 HTML 的事件绑定

有了上面的功能,我们可以让 HTML 动起来了,但是还缺点什么,比如我们的 HTML 属性,如 id class 等,是不是也能动态的获取变化值,你还别说,还真的可以,Vue 模板语法为我们提供了 v-bind 用于动态绑定属性值,我们来看个例子:

<template>
<option v-bind:id="_id"  v-bind:value="value" />
</template>

<script>
export default {
  data: { _id: '1', value: "Xiaomi" },
}
</script>
复制代码

可以看到,我们在 script 中导出的对象属性 data 中,定义了 _id value 值,然后我们通过在 <template> 模板中使用 v-bind 语法动态的给 option 标签的 id value 属性赋值,最后的结果看起来是这样的:

<option id="1" value="Xiaomi" />
复制代码

当然,当需要绑定的属性多了,每次都写 v-bind 显得相当繁琐,所以 Vue 为我们提供了 v-bind 的简洁语法 : ,即我们之前的绑定语法从 v-bind:id="_id" 变成了 :id="_id"

上面的代码用简洁语法改写如下:

<template>
<option :id="_id"  :value="value" />
</template>

<script>
export default {
  data: { _id: '1', value: "Xiaomi" },
}
</script>
复制代码

模板语法:v-model 双向绑定

前面我们提到通过 {{}} 插值语法渲染来自 data 的数据实现了逻辑层向视图层的数据流动,通过 methods 在视图层操作逻辑层的数据,实现了视图层的数据向逻辑层的数据流动,从而达到了双向绑定,当我们的应用越来越复杂,我们会发现这样的数据双向流动会越来越频繁,而且粒度也会大小不一,有很多单纯修改某个值的方法调用就会显得特别繁杂,因此 Vue 通过提供 v-model 进行了视图层和逻辑层的双向绑定,让我们来看个例子:

<template>
<!-- 其他代码 ... -->
<input
  type="text"
  placeholder="Name"
  v-model="name"
/>
<!-- 其他代码 ... -->
</template>

<script>
export default {
  data: { name: 'ProductForm' },
}
</script>
复制代码

这里我们通过申明 v-mode 将此 input 的值和我们在 Vue 实例中的 model name 属性进行了双向绑定,即当 data 中的 name 发生变化,input 的值也会跟着变化,当 input 的值发生变化,我们 data 中的 name 的值也会被修改,这一切都是自动发生的,不需要我们额外的添加 methods 里面的方法调用来手动修改。

模板语法:循环

好了,Vue 替我们接管了 HTML 元素属性值、事件处理、元素内容,这些都还只属于原来 HTML 的部分,它更强大的一点就是将 JS 的功能引入了模板语法中,使得我们可以实现类似循环,条件选择操作等功能。

接下来我们先来看一下 Vue 为我们提供的 “循环” 模板语法, 它使得我们可以快速渲染大量具有相似结构的数据,比如渲染一个数组的数据,生成一个 HTML 元素列表,这在我们平时看到的新闻 App 里面很常见,我们浏览新闻时,发现其实每条新闻的结构都很相似,并且有很多条新闻(可能多大几百上千条),如果每一条我们都手动写 HTML 代码的话,无疑显得相当繁琐,并且数据一多,我们手动就显得无能为力了,而 Vue 为我们提供的 “循环” 模板语法,使得我们可以通过非常简单的写法就可以渲染大量数据,我们来看个例子:

<!--
manufacturers = [
  { _id: 1, name: 'Apple' },
  { _id: 2, name: 'Xiaomi' }
]

model = { _id: 1, name: 'Apple' }

 -->
<template v-for="manufacturer in manufacturers">
  <option :value="manufacturer._id" :selected="manufacturer._id == model._id">{{manufacturer.name}}</option>
</template>
复制代码

最后渲染的结果为:

<option value="1" selected="true">Apple</option>
<option value="2" selected="false">Xiaomi</option>
复制代码

注意到,如果我们在写 “循环” 语法时,使用了一个额外的标签 template 来包裹我们需要渲染的 HTML 元素,这也是 Vue 推荐的写法;我们在 template 标签的属性上添加 v-for 然后给它赋值 "manufacturer in manufacturers" ,通过这样的形式进行列表数据的遍历,每次从 manufacturers 中取一个元素,并赋值给 manufacturer ,然后我们就可以在 option 标签中使用 manufacturer 和我们定义的 model 进行比较。

因为我们的 model._id 1 ,它和 manufacturers 数组的第一项元素的 _id 一致,所以我们返回的两个 option 标签,第一个 selected 属性为 true ,第二个为 false

模板语法:条件选择

上面的讲述了循环是如何在 Vue 中使用的,下面我们来看一看条件语法是如何在 Vue 中使用的:

<span v-if="isEditing">Update Product</span>
<span v-else>Add Product</span>

<script>
export default {
  data: { isEditing: false },
}
</script>
复制代码

我们可以看到,通过在标签上加 v-if 并后面紧跟加 v-else 的标签我们可以判断最终渲染的标签,比如我们这里 isEditing false ,那么我们最终渲染的结果为:

<span>Add Product</span>
复制代码

当然你可以添加诸如 v-else-if 的标签来做多重判断。

提示

这里的带 v-if v-else-if v-else 的标签需要依次紧跟着前面的标签,不能在这些带条件属性的标签中插入其他不带条件的标签,比如下面这段代码就是错误的:

<span v-if="isEditing">Update Product</span>
<span>我是错误插入的标签</span>
<span v-else>Add Product</span>

<script>
export default {
  data: { isEditing: false },
}
</script>
复制代码

动手实现

讲解完 Vue 的基础知识之后,我们马上将所有的知识运用起来,来编写我们的 ProductForm.vue 组件,它用来添加或者更新商品的信息。

我们在 src/components 中创建 ProductForm.vue 表单组件,代码如下:

<template>
  <form @submit.prevent="saveProduct">
    <div class="col-lg-5 col-md-5 col-sm-12 col-xs-12">
      <div class="form-group">
        <label>Name</label>
        <input
          type="text"
          placeholder="Name"
          v-model="model.name"
          name="name"
          class="form-control" />
      </div>
      <div class="form-group">
        <label>Price</label>
        <input
          type="number"
          class="form-control"
          placeholder="Price"
          v-model="model.price"
          name="price" />
      </div>
      <div class="form-group">
        <label>Manufacturer</label>
        <select
          type="text"
          class="form-control"
          v-model="model.manufacturer"
          name="manufacturer">
          <template v-for="manufacturer in manufacturers">
            <option :value="manufacturer._id" :selected="manufacturer._id == (model.manufacturer && model.manufacturer._id)">{{manufacturer.name}}</option>
          </template>
        </select>
      </div>
    </div>

    <div class="col-lg-4 col-md-4 col-sm-12 col-xs-12">
      <div class="form-group">
        <label>Image</label>
        <input
          type="text"
          lass="form-control"
          placeholder="Image"
          v-model="model.image"
          name="image"
          class="form-control" />
      </div>
      <div class="form-group">
        <label>Description</label>
        <textarea
          class="form-control"
          placeholder="Description"
          rows






请到「今天看啥」查看全文