惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Attack and Defense Labs
Attack and Defense Labs
N
News and Events Feed by Topic
L
LINUX DO - 热门话题
PCI Perspectives
PCI Perspectives
www.infosecurity-magazine.com
www.infosecurity-magazine.com
爱范儿
爱范儿
D
DataBreaches.Net
Simon Willison's Weblog
Simon Willison's Weblog
S
Secure Thoughts
S
SegmentFault 最新的问题
博客园 - 【当耐特】
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 叶小钗
P
Proofpoint News Feed
The Hacker News
The Hacker News
T
ThreatConnect
N
News and Events Feed by Topic
T
Threatpost
The Register - Security
The Register - Security
WordPress大学
WordPress大学
博客园 - Franky
Recorded Future
Recorded Future
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Project Zero
Project Zero
大猫的无限游戏
大猫的无限游戏
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
罗磊的独立博客
Stack Overflow Blog
Stack Overflow Blog
腾讯CDC
F
Future of Privacy Forum
F
Full Disclosure
Cyberwarzone
Cyberwarzone
J
Java Code Geeks
李成银的技术随笔
Schneier on Security
Schneier on Security
Know Your Adversary
Know Your Adversary
H
Hacker News: Front Page
人人都是产品经理
人人都是产品经理
博客园_首页
Scott Helme
Scott Helme
Google DeepMind News
Google DeepMind News
美团技术团队
Malwarebytes
Malwarebytes
Last Week in AI
Last Week in AI
T
Tailwind CSS Blog
T
The Exploit Database - CXSecurity.com
G
GRAHAM CLULEY
Recent Announcements
Recent Announcements
C
CXSECURITY Database RSS Feed - CXSecurity.com

CSS-Tricks

Revealing Text With CSS letter-spacing | CSS-Tricks Technical Writing in the AI Age | CSS-Tricks Cross-Document View Transitions: Scaling Across Hundreds of Elements | CSS-Tricks Cross-Document View Transitions: Scaling Across Hundreds of Elements | CSS-Tricks The State of CSS Centering in 2026 | CSS-Tricks Stack Overflow: When We Stop Asking | CSS-Tricks Cross-Document View Transitions: The Gotchas Nobody Mentions | CSS-Tricks What’s !important #11: 3D Voxel Scenes, Flying Focus, CSS Syntaxes, and More | CSS-Tricks Computing and Displaying Discounted Prices in CSS | CSS-Tricks rotateX() | CSS-Tricks rotateY() | CSS-Tricks rotateZ() | CSS-Tricks rotate() | CSS-Tricks Soon We Can Finally Banish JavaScript to the ShadowRealm | CSS-Tricks Using CSS corner-shape For Folded Corners | CSS-Tricks A Scrollytelling Gift for Mum on Mother’s Day 2026 | CSS-Tricks Google’s Prompt API | CSS-Tricks Making Zigzag CSS Layouts With a Grid + Transform Trick | CSS-Tricks Fixed-Height Cards: More Fragile Than They Look | CSS-Tricks What’s !important #10: HTML-in-Canvas, Hex Maps, E-ink Optimization, and More | CSS-Tricks The Importance of Native Randomness in CSS | CSS-Tricks contrast() | CSS-Tricks contrast-color() | CSS-Tricks Let’s Use the Nonexistent ::nth-letter Selector Now | CSS-Tricks Quick Hit #126 Recreating Apple’s Vision Pro Animation in CSS | CSS-Tricks Quick Hit #125 Enhancing Astro With a Markdown Component | CSS-Tricks Quick Hit #124 Markdown + Astro = ❤️ | CSS-Tricks Quick Hit #123 What’s !important #9: clip-path Jigsaws, View Transitions Toolkit, Name-only Containers, and More | CSS-Tricks A Well-Designed JavaScript Module System is Your First Architecture Decision | CSS-Tricks hypot() | CSS-Tricks The Radio State Machine | CSS-Tricks 7 View Transitions Recipes to Try | CSS-Tricks Quick Hit #122 Quick Hit #121 Selecting a Date Range in CSS | CSS-Tricks saturate() | CSS-Tricks justify-self | CSS-Tricks Quick Hit #120 Alternatives to the !important Keyword | CSS-Tricks Quick Hit #119 New CSS Multi-Column Layout Features in Chrome | CSS-Tricks Quick Hit #118 Making Complex CSS Shapes Using shape() | CSS-Tricks Quick Hit #117 Front-End Fools: Top 10 April Fools’ UI Pranks of All Time | CSS-Tricks Sniffing Out the CSS Olfactive API | CSS-Tricks What’s !important #8: Light/Dark Favicons, @mixin, object-view-box, and More | CSS-Tricks Quick Hit #116 Form Automation Tips for Happier User and Clients | CSS-Tricks Quick Hit #115 Generative UI Notes | CSS-Tricks Quick Hit #114 Quick Hit #113 Experimenting With Scroll-Driven corner-shape Animations | CSS-Tricks Quick Hit #112 JavaScript for Everyone: Destructuring | CSS-Tricks Quick Hit #111 Quick Hit #110 What’s !important #7: random(), Folded Corners, Anchored Container Queries, and More | CSS-Tricks 4 Reasons That Make Tailwind Great for Building Layouts | CSS-Tricks Quick Hit #109 Quick Hit #108 Abusing Customizable Selects | CSS-Tricks Quick Hit #107 The Value of z-index | CSS-Tricks Quick Hit #106 The Different Ways to Select <html> in CSS Quick Hit #105 Popover API or Dialog API: Which to Choose? Quick Hit #104 What’s !important #6: :heading, border-shape, Truncating Text From the Middle, and More Yet Another Way to Center an (Absolute) Element An Exploit ... in CSS?! Quick Hit #103 A Complete Guide to Bookmarklets Quick Hit #102 Loading Smarter: SVG vs. Raster Loaders in Modern Web Design Potentially Coming to a Browser :near() You Quick Hit #101 Distinguishing "Components" and "Utilities" in Tailwind Quick Hit #100 Spiral Scrollytelling in CSS With sibling-index() Interop 2026 Quick Hit #99 What’s !important #5: Lazy-loading iframes, Repeating corner-shape Backgrounds, and More Quick Hit #98 Making a Responsive Pyramidal Grid With Modern CSS Approximating contrast-color() With Other CSS Features Quick Hit #97 Trying to Make the Perfect Pie Chart in CSS Quick Hit #96 Quick Hit #95 CSS Bar Charts Using Modern Functions Quick Hit #94 No Hassle Visual Code Theming: Publishing an Extension Quick Hit #93
Intro to Vue.js: Rendering, Directives, and Events
CSS-Tricks · 2017-01-30 · via CSS-Tricks

If I was going to sum up my experiences with Vue in a sentence, I’d probably say something like “it’s just so reasonable” or “It gives me the tools I want when I want them, and never gets in my way”. Again and again, when learning Vue, I smiled to myself. It just made sense, elegantly.

This is my own introductory take on Vue. It’s the article I wish I had when I was first learning Vue. If you’d like a more non-partisan approach, please visit Vue’s very well thought out and easy to follow Guide.

Article Series:

  1. Rendering, Directives, and Events (You are here!)
  2. Components, Props, and Slots
  3. Vue-cli
  4. Vuex
  5. Animations

One of my favorite things about Vue is that it takes all of the successful things from other frameworks, and incorporates them without getting disorganized. Some examples that stand out for me:

  • A virtual DOM with reactive components that offer the View layer only, props and a Redux-like store similar to React.
  • Conditional rendering, and services, similar to Angular.
  • Inspired by Polymer in part in terms of simplicity and performance, Vue offers a similar development style as HTML, styles, and JavaScript are composed in tandem.

Some benefits I’ve enjoyed over Vue’s competitors: cleaner, more semantic API offerings, slightly better performance than React, no use of polyfills like Polymer, and an isolated, less opinionated view than Angular, which is an MVC.

I could go on, but it’s probably better if you read their comprehensive and community-driven comparison with other frameworks. It’s worth a read, but you can skip back to it later if you’d like to dive into the code.

Let’s Get Started!

We can’t kick this off without the obligatory “Hello, world!” example. Let’s do that so you can get up and running:

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

See the Pen Vue Hello World by Sarah Drasner (@sdras) on CodePen.

If you’re familiar with React, this will have some similarities. We’ve escaped into JavaScript in the middle of the content with the mustache template and used a variable, but one difference is we are working with straight up HTML instead of JSX. JSX is pretty easy to work with, but I do think it’s nice that I don’t have to spend time changing class to className, etc. You’ll also notice that this is pretty lightweight to get up and running.

Now let’s try Vue out with something I really love: loops and conditional rendering.

Conditional Rendering

Let’s say I have a set of items, like navigation, that I know I’m going to reuse. It might make sense to put it in an array to update it in a few places dynamically and consistently. In vanilla JS (with Babel) we might do something like this: create the array, then create an empty string where we add each item wrapped in an <li>, and then wrap all of that in a <ul> and add it to the DOM with innerHTML:

<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();

See the Pen e699f60b79b90a35401cc2bcbc588159 by Sarah Drasner (@sdras) on CodePen.

This works fine, but it’s a bit messy for something so standard. Now let’s implement that same thing with Vue’s loop with 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'
    ]
  }
});

See the Pen Conditional Rendering in Vue by Sarah Drasner (@sdras) on CodePen.

Pretty clean and declarative. If you’re familiar with Angular, this will likely be familiar to you. I find this to be such a clean and legible way to conditionally render. If you jumped into the code and had to update it, you could do so very easily.

Another really nice offering is dynamic binding with v-model. Check this out:

<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.'  
    }
  }
});

See the Pen Vue Book v-model basic by Sarah Drasner (@sdras) on CodePen.

You’ll probably notice two things about this demo. First, that it really took nothing at all to type directly into the book and dynamically update the text. Vue enables us to very easily set up two-way binding between the <textarea> and the <p> with v-model.

The other thing you might notice is that we’re now putting data in a function. In this example, it would work without doing so. We could have just put it in an object like our earlier examples. But this would only work for the Vue instance and be exactly the same across the application (thus, not so great for individual components). It’s OK for one Vue instance, but this will share data across all of the child components as well. It’s good practice to start putting data in a function because we’ll need to when we start using components and want them to each hold state of their own.

These aren’t the only easy input bindings available to you at all, and even v-if has an alternate, v-show, which won’t mount/unmount the component, but rather, leave it in the DOM and toggle visibility.

There are so many more directives available to you, here’s a sampling of some of the ones I use very often. A lot of these offer shortcuts as well, so I’ll show both. From here on, we’ll mostly use the shortcuts, so it’s good to at least familiarize yourself with them a little bit in this table.

Name Shortcut Purpose Example
v-if, v-else-if, v-else none Conditional Rendering <g v-if="flourish === 'A'"></g>
<g v-else-if="flourish === 'B'"></g>
<g v-else></g>
v-bind : Bind attributes dynamically, or pass props <div :style="{ background: color }"></div>
v-on @ Attaches an event listener to the element <button @click="fnName"></button>
v-model none Creates two-way binding <textarea rows="5" v-model="message" maxlength="72"></textarea>
v-pre none Skip compiling for raw content, can boost performance <div v-pre>{{ raw content with no methods}}</div>
v-once none Don’t rerender <div class="v-once">Keep me from rerendering</div>
v-show none Will show or hide a component/element based on state, but will leave it in the DOM without unmounting (unlike v-if) <child v-show="showComponent"></child> (toggles visibility when showComponent is true)

There are also really nice event modifiers and other API offerings to speed up development like:

  • @mousemove.stop is comparable to e.stopPropogation()
  • @mousemove.prevent this is like e.preventDefault()
  • @submit.prevent this will no longer reload the page on submission
  • @click.once not to be confused with v-once, this click event will be triggered once.
  • v-model.lazy won’t populate the content automatically, it will wait to bind until an event happens.

You can even configure your own keycodes.

We’ll use these in examples a bit more coming up!

Event Handling

Binding that data is all well and good but only gets us so far without event handling, so let’s cover that next! This is one of my favorite parts. We’ll use the binding and listeners above to listen to DOM events.

There are a few different ways to create usable methods within our application. Just like in vanilla JS, you can pick your function names, but methods are intuitively called, well, methods!

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

We’re creating a method called increment, and you can see that this automatically binds to this and will refer to the data in this instance and component. I love this kind of automatic binding, it’s so nice to not have to console.log to see what this is referring to. We’re using shorthand @click to bind to the click event here.

Methods aren’t the only way to create a custom function. You can also use watch. The main difference is that methods are good for small, synchronous calculations, while watch is helpful with more tasking or asynchronous or expensive operations in response to changing data. I tend to use watch most often with animations.

Let’s go a little further and see how we’d pass in the event itself and do some dynamic style bindings. If you recall in the table above, instead of writing v-bind, you can use the shortcut :, so we can bind pretty easily to style (as well as other attributes) by using :style and passing in state, or :class. There are truly a lot of uses for this kind of binding.

In the example below, we’re using hsl(), in which hue calculated as a circle of degrees of color that wraps all the way around. This is good for our use as it will never fail, so as we track our mouse in pixels across the screen, the background style will update accordingly. We’re using ES6 template literals here.

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>

See the Pen Showing simple event handling by Sarah Drasner (@sdras) on CodePen.

You can see that we didn’t even need to pass in the event to the @mousemove handler, Vue will automatically pass it for you to be available as a parameter for the method. (shown as e here).

Also, native methods can also be used, such as event.clientX, and it’s simple to pair them with this instances. In the style binding on the element there’s camel casing for hyphenated CSS properties. In this example, you can see how simple and declarative Vue is to work with.

We don’t even actually need to create a method at all, we could also increase the counter directly inline in the component if the event is simple enough:

<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
    }
  }
});

See the Pen Backpack Shop Counter by Sarah Drasner (@sdras) on CodePen.

You can see that we’re updating the state directly in the @click handler without a method at all- you can also see that we can add a little bit of logic in there as well (as you wouldn’t have lower than zero items on a shopping site). Once this logic gets too complex, though, you sacrifice legibility, so it’s good to move it into a method. It’s nice to have the option for either, though.

Article Series:

  1. Rendering, Directives, and Events (You are here!)
  2. Components, Props, and Slots
  3. Vue-cli
  4. Vuex
  5. Animations