Vue.js 入门:渲染、指令和事件

Avatar of Sarah Drasner
Sarah Drasner

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

如果要总结我对 Vue 的体验,我可能会说类似“它非常合理”或“它在我需要时提供我想要的工具,并且从不阻碍我”的话。在学习 Vue 的过程中,我一次又一次地对自己微笑。它非常合理,优雅。

这是我个人对 Vue 的入门介绍。这是我初学 Vue 时希望拥有的文章。如果您想了解更多中立的介绍,请访问 Vue 非常精心设计且易于理解的 指南

文章系列

  1. 渲染、指令和事件 (您当前所在位置!)
  2. 组件、Props 和插槽
  3. Vue-cli
  4. Vuex
  5. 动画

我最喜欢 Vue 的一点是,它汲取了其他框架的所有成功之处,并将它们融入其中,而不会变得杂乱无章。一些让我印象深刻的例子

  • 具有响应式组件的虚拟 DOM,仅提供视图层,类似 React 的 props 和 Redux 式存储。
  • 类似 Angular 的条件渲染和服务。
  • Vue 部分受到 Polymer 的启发,在简洁性和性能方面,Vue 提供了类似 HTML 的开发风格,HTML、样式和 JavaScript 协同组成。

与 Vue 的竞争对手相比,我享受的一些优势:更简洁、语义更强的 API 提供,比 React 略好的性能,不使用像 Polymer 这样的 polyfill,以及与 Angular(MVC)相比,更孤立、更少意见的视图。

我可以继续说下去,但您最好阅读他们全面且社区驱动的 与其他框架的比较。值得一读,但如果您想深入研究代码,可以稍后再返回。

开始吧!

在我们开始之前,不能不先来个必备的“Hello, world!”示例。让我们来做一下,这样您就可以开始使用了。

<div id="app">
 {{ text }} Nice to meet Vue.
</div>
new Vue({
 el: '#app',
 data: {
   text: 'Hello World!'
 }
});

查看 Sarah Drasner 在 CodePen 上的笔 Vue Hello World@sdras)。

如果您熟悉 React,就会发现两者有一些相似之处。我们使用 mustache 模板在内容中间转义到 JavaScript 中并使用了变量,但不同之处在于我们使用的是纯 HTML,而不是 JSX。JSX 非常易于使用,但我认为不必花费时间将 class 更改为 className 等也很不错。您还会注意到,这样可以非常轻松地启动并运行。

现在让我们尝试使用我最喜欢的功能之一:循环和条件渲染来体验 Vue。

条件渲染

假设我有一组项目,例如导航,我知道我将重复使用它们。将它们放在数组中以动态且一致地在几个地方更新它们可能是有意义的。在原生 JS(使用 Babel)中,我们可能会这样做:创建数组,然后创建一个空字符串,在其中添加用 <li> 包裹的每个项目,然后将所有这些项目用 <ul> 包裹起来,并使用 innerHTML 将其添加到 DOM 中。

<div id="container"></div>
const items = [
  'thingie',
  'another thingie',
  'lots of stuff',
  'yadda yadda'
];

function listOfStuff() {
  let full_list = '';
  for (let i = 0; i < items.length; i++) {
      full_list = full_list + `<li> ${items[i]} </li>`
  }
  const contain = document.querySelector('#container');
  contain.innerHTML = `<ul> ${full_list} </ul>`;     
}

listOfStuff();

查看 Sarah Drasner 在 CodePen 上的笔 e699f60b79b90a35401cc2bcbc588159@sdras)。

这可以正常工作,但对于如此标准的事情来说有点混乱。现在让我们使用 Vue 的 v-for 循环实现相同的功能。

<div id="app">
  <ul>
    <li v-for="item in items">
      {{ item }}
    </li>
  </ul>
</div>
const app4 = new Vue({
  el: '#app',
  data: {
    items: [
      'thingie',
      'another thingie',
      'lots of stuff',
      'yadda yadda'
    ]
  }
});

查看 Sarah Drasner 在 CodePen 上的笔 Vue 中的条件渲染@sdras)。

非常简洁且声明式。如果您熟悉 Angular,这很可能很熟悉。我发现这是一种非常简洁易读的条件渲染方式。如果您跳入代码并需要更新它,您可以非常轻松地做到。

另一个非常棒的功能是使用 v-model 进行动态绑定。看看这个

<div id="app">
  <h3>Type here:</h3>
  <textarea v-model="message" class="message" rows="5" maxlength="72"></textarea><br>
  <p class="booktext">{{ message }} </p>
</div>
new Vue({
  el: '#app',
  data() {
    return {
      message: 'This is a good place to type things.'  
    }
  }
});

查看 Sarah Drasner 在 CodePen 上的笔 Vue Book v-model 基础@sdras)。

您可能会注意到此演示中的两件事。首先,直接在书中键入并动态更新文本实际上不需要任何操作。Vue 使我们能够使用 v-model<textarea><p> 之间非常轻松地设置双向绑定。

您可能注意到的另一点是,我们现在将数据放在一个函数中。在此示例中,即使不这样做也可以正常工作。我们可以像之前的示例一样将其放在对象中。但这仅适用于 Vue 实例,并且在整个应用程序中完全相同(因此,对于单个组件来说不太好)。对于一个 Vue 实例来说是可以的,但它也会在所有子组件之间共享数据。最好从将数据放在函数中开始,因为当我们开始使用组件并希望它们各自拥有自己的状态时,我们需要这样做。

这些并不是唯一可用的简单输入绑定,甚至 v-if 也有一个替代方案 v-show,它不会挂载/卸载组件,而是保留在 DOM 中并切换可见性。

还有 许多其他指令 可供您使用,以下是一些我经常使用的指令示例。许多指令也提供了快捷方式,因此我将同时展示两者。从这里开始,我们将主要使用快捷方式,因此至少在表中熟悉一下它们会很好。

名称 快捷方式 用途 示例
v-if、v-else-if、v-else 条件渲染 <g v-if="flourish === 'A'"></g>
<g v-else-if="flourish === 'B'"></g>
<g v-else></g>
v-bind : 动态绑定属性或传递 props <div :style="{ background: color }"></div>
v-on @ 将事件侦听器附加到元素 <button @click="fnName"></button>
v-model 创建双向绑定 <textarea rows="5" v-model="message" maxlength="72"></textarea>
v-pre 跳过编译以获取原始内容,可以提高性能 <div v-pre>{{ 没有方法的原始内容 }}</div>
v-once 不要重新渲染 <div class="v-once">阻止我重新渲染</div>
v-show 根据状态显示或隐藏组件/元素,但不会卸载它(与 v-if 不同) <child v-show="showComponent"></child>(当 showComponent 为 true 时切换可见性)

还有一些非常棒的事件修饰符和其他 API 功能可以加快开发速度,例如

  • @mousemove.stop 可与 e.stopPropogation() 相媲美
  • @mousemove.prevent 这类似于 e.preventDefault()
  • @submit.prevent 这将不再在提交时重新加载页面
  • @click.once 不要与 v-once 混淆,此 点击事件 将触发一次。
  • v-model.lazy 不会自动填充内容,它将等待事件发生后绑定。

您甚至可以 配置您自己的键码

我们将在接下来的示例中更多地使用这些功能!

事件处理

绑定数据很好,但如果没有事件处理,它只能让我们走这么远,所以接下来让我们来了解一下!这是我最喜欢的部分之一。我们将使用上面的绑定和监听器来监听 DOM 事件。

在我们的应用程序中创建可用方法的方法有几种。就像在原生 JS 中一样,您可以选择函数名称,但方法直观地称为,嗯,方法!

new Vue({
  el: '#app',
  data() {
   return {
    counter: 0
   }
  },
  methods: {
   increment() {
     this.counter++;
   }
  }
});
<div id="app">
  <p><button @click="increment">+</button> {{ counter }}</p>
</div>

我们正在创建一个名为 increment 的方法,您可以看到它会自动绑定到 this,并且将引用此实例和组件中的数据。我喜欢这种自动绑定,不用 console.log 就能看到 this 指的是什么,这真是太好了。我们在这里使用快捷方式 @click 来绑定到 click 事件。

方法并不是创建自定义函数的唯一方法。您还可以使用 watch。主要区别在于,方法适用于小型同步计算,而 watch 则有助于响应数据变化执行更耗时或异步或昂贵的操作。我倾向于最常在动画中使用 watch。

让我们更进一步,看看如何传入事件本身并进行一些动态样式绑定。如果您还记得上面表格中的内容,则无需编写 v-bind,可以使用快捷方式 :,因此我们可以通过使用 :style 并传入状态或 :class 来非常轻松地绑定到样式(以及其他属性)。这种绑定确实有很多用途。

在下面的示例中,我们使用了hsl(),其中色相计算为一个颜色度数圆圈,它会环绕整个圆圈。这对于我们的用途来说很好,因为它永远不会失败,因此当我们在屏幕上用像素跟踪鼠标时,背景样式会相应地更新。我们在这里使用的是ES6 模板字面量

new Vue({
  el: '#app',
  data() {
    return {
      counter: 0,
      x: 0
    }
  },
  methods: {
    increment() {
      this.counter++;
   },
   decrement() {
     this.counter--;
   },
   xCoordinate(e) {
     this.x = e.clientX;
   }
  }
});
<div id="app" :style="{ backgroundColor: `hsl(${x}, 80%, 50%)` }" @mousemove="xCoordinate">
  <p><button @click="increment">+</button> {{ counter }} <button @click="decrement">-</button></p>
  <p>Pixels across: {{ x }}</p>
</div>

查看 CodePen 上 Sarah Drasner (@sdras) 编写的笔 显示简单的事件处理

您可以看到,我们甚至不需要将事件传递给@mousemove 处理程序,Vue 会自动为您传递它,以便作为方法的参数可用。(此处显示为e)。

此外,还可以使用原生方法,例如event.clientX,并且可以轻松地将它们与this 实例配对。在元素上的样式绑定中,带连字符的 CSS 属性使用驼峰命名法。在这个例子中,您可以看到 Vue 使用起来多么简单和声明式。

我们甚至不需要创建方法,如果事件足够简单,我们也可以直接在组件内增加计数器。

<div id="app">
  <div class="item">
    <img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/28963/backpack.jpg" width="235" height="300"/>
    <div class="quantity">
      <button class="inc" @click="counter > 0 ? counter -= 1 : 0">-</button>
      <span class="quant-text">Quantity: {{ counter }}</span>
      <button class="inc" @click="counter += 1">+</button>
    </div>
    <button class="submit" @click="">Submit</button>
  </div><!--item-->
</div>
new Vue({
  el: '#app',
  data() {
    return {
      counter: 0
    }
  }
});

查看 CodePen 上 Sarah Drasner (@sdras) 编写的笔 背包商店计数器

您可以看到,我们直接在@click 处理程序中更新状态,根本没有使用方法——您还可以看到我们也可以在其中添加一些逻辑(因为在购物网站上商品数量不会低于零)。但是,一旦这种逻辑变得过于复杂,可读性就会降低,因此最好将其移到方法中。不过,能够选择两者中的任何一种都很好。

文章系列

  1. 渲染、指令和事件 (您当前所在位置!)
  2. 组件、Props 和插槽
  3. Vue-cli
  4. Vuex
  5. 动画