Categories
Vue 3

Vue 3 — Keyboard and Mouse

Vue 3 is in beta and it’s subject to change.

Vue 3 is the up and coming version of Vue front end framework.

It builds on the popularity and ease of use of Vue 2.

In this article, we’ll look at how to handle key and mouse events in Vue 3 components.

Key Modifiers

Vue 3 can handle keyboard events.

For instance, we can write:

<input @keyup.enter="submit" />

to run the submit method when the keyup event is triggered by pressing the enter key.

Any valid key name is acceptable as the modifier.

The following key aliases can also be used as modifiers:

  • .enter
  • .tab
  • .delete (captures both "Delete" and "Backspace" keys)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

System Modifier Keys

We can also add modifiers for system modifier keys like Alt and Ctrl.

We can use the following as modifiers:

  • .ctrl
  • .alt
  • .shift
  • .meta

The meta key is the Windows key on Windows keyboards.

On Sun keyboards, it’s the diamond key.

And on Macs, it’s the command key.

So we can listen to the Ctrl + Enter key combo press on an element by writing:

<input @keyup.ctrl.enter="clear" />

We can also listen to Ctrl + click by writing:

<div @click.ctrl="onCtrlClick">ctrl + click me</div>

.exact Modifier

The .exact modifier lets us control the exact combination of system modifiers needed to trigger an event.

For example, if we have:

<button @click.ctrl="onClick">click me</button>

then if alt or shift is pressed, then onClick will also be run.

However, if we have:

<button @click.ctrl.exact="onCtrlClick">A</button>

Then onCtrlClick only runs when we Ctrl + click the button.

Mouse Button Modifiers

Vue 3 also provides modifiers for mouse buttons.

They are:

  • .left
  • .right
  • .middle

for listening to the presses of specific buttons.

Listeners in HTML

Listeners in HTML frees the component code including DOM logic, which is cleaner than having them all in JavaScript.

When the view model is destroyed, all event listeners are automatically removed.

Form Input Bindings

We can use the v-model directive to bind the input value to the state property.

It’s syntactic sugar for updating data on user input events.

v-model ignores the initial value , checked , or selected attributes found in any element.

Only the state in the Vue instances is treated as the source of truth.

Therefore, we should remove those attributes and just set the initial value in the Vue instance.

v-model internally uses different properties and emit different events for different input elements.

Text inputs use value property and input event.

Checkboxes and radio buttons use the checked property and change event.

Select fields use the value as a prop and change as an event.

To use the v-model directive, we can write:

<!DOCTYPE html>  
<html lang="en">  
  <head>  
    <title>App</title>  
    <script src="https://unpkg.com/vue@next"></script>  
  </head>  
  <body>  
    <div id="app">  
      <input v-model="message" placeholder="message" />  
      <p>{{ message }}</p>  
    </div>  
    <script>  
      const vm = Vue.createApp({  
        data() {  
          return {  
            message: ""  
          };  
        }  
      }).mount("#app");  
    </script>  
  </body>  
</html>

We returned an object with the message property so that we can use it with v-model .

Then we render the value of message to show what we entered.

v-model will automatically synchronize the input value and the value of message .

Therefore, when we type something in the box, it’ll be displayed below it.

Conclusion

We can listen to key and mouse events with v-on .

v-model binds the inputted value to the Vue instance state.

Categories
Vue 3

Vue 3 — Inline Styles and v-if

Vue 3 is in beta and it’s subject to change.

Vue 3 is the up and coming version of Vue front end framework.

It builds on the popularity and ease of use of Vue 2.

In this article, we’ll look at inline style bindings and v-if.

Binding Inline Styles

There’re various ways to bind inline styles to an element.

One way is to pass in an object to the :style directive.

For example, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <div :style="{ color, fontSize: `${fontSize}px` }">
        hello
      </div>
    </div>
    <script>
      const vm = Vue.createApp({
        data() {
          return {
            color: "red",
            fontSize: 30
          };
        }
      }).mount("#app");
    </script>
  </body>
</html>

We have the color and fontSize properties in the object we return in the data method.

Then we used that in the object we use as the value of the :style directive.

So ‘hello’ should be red and 30px in size.

We can replace that with an object to make the template shorter.

For instance, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <div :style="styleObj">
        hello
      </div>
    </div>
    <script>
      const vm = Vue.createApp({
        data() {
          return {
            styleObj: {
              color: "red",
              fontSize: "30px"
            }
          };
        }
      }).mount("#app");
    </script>
  </body>
</html>

There’s also an array syntax to let us add multiple style objects to the same element.

For example, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <div :style="[baseStyles, overridingStyles]">
        hello
      </div>
    </div>
    <script>
      const vm = Vue.createApp({
        data() {
          return {
            baseStyle: {
              color: "red",
              fontSize: "30px"
            },
            overridingStyles: {
              color: "green"
            }
          };
        }
      }).mount("#app");
    </script>
  </body>
</html>

We have the baseStyles and overridingStyles in one array.

The styles in overridingStyles will override the styles in baseStyle completely.

So we get that the text is green and it’s in its default size.

If browser-specific prefixes are needed, then they’ll be added automatically.

We can also provide an array of values to a style property with an array.

For instance, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }">
        hello
      </div>
    </div>
    <script>
      const vm = Vue.createApp({
        data() {
          return {};
        }
      }).mount("#app");
    </script>
  </body>
</html>

We have all the variants of flex in the array.

Conditional Rendering

We can add conditional rendering with the v-if directive.

For instance, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <button @click="on = !on">toggle</button>
      <h1 v-if="on">hello world!</h1>
    </div>
    <script>
      const vm = Vue.createApp({
        data() {
          return {
            on: true
          };
        }
      }).mount("#app");
    </script>
  </body>
</html>

We have the on property returned with the object we return indata , so we can use it with v-if to conditionally render the h1 element.

Also, we have a button to toggle on between true or false so that we’ll see the h1 toggled on and off as we click the button.

Conclusion

Inline styles can be added with the :style directive.

It takes an object or an array.

We can use v-if to conditionally render an element.

Categories
Vue 3

Vue 3 — HTML and Directives

Vue 3 is the up and coming version of Vue front end framework.

It builds on the popularity and ease of use of Vue 2.

In this article, we’ll look at how to create templates with Vue 3.

Raw HTML

We can render raw HTML with the v-html directive.

For example, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <p>{{ rawHtml }}</p>
      <p><span v-html="rawHtml"></span></p>
    </div>
    <script>
      const vm = Vue.createApp({
        data() {
          return {
            rawHtml: `<b>foo</b>`
          };
        }
      }).mount("#app");
    </script>
  </body>
</html>

We have the rawHtml property returned with the object we return in the data method.

If we pass raw HTML into the mustache, it’ll be sanitized. This means the raw code will be displayed.

If we pass it into the v-html directive, it’ll be displayed as HTML, so it’ll be bold.

Therefore, if we use v-html , we should be careful of cross-site scripting vulnerabilities.

We should only display trusted content with v-html .

Attributes

If we want to set attribute values dynamically, we’ve to use the v-bind directive.

For instance, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <div v-bind:id="dynamicId"></div>
    </div>
    <script>
      const vm = Vue.createApp({
        data() {
          return {
            dynamicId: `foo`
          };
        }
      }).mount("#app");
    </script>
  </body>
</html>

to set the id attribute of the div to foo by using v-bind .

If we have boolean attributes, its existence means we set the value totrue .

For example, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <button v-bind:disabled="disabled">Button</button>
    </div>
    <script>
      const vm = Vue.createApp({
        data() {
          return {
            disabled: true
          };
        }
      }).mount("#app");
    </script>
  </body>
</html>

We disabled the button by passing in the disabled value to v-bind:disabled , which is true .

JavaScript Expressions

We can put JavaScript expressions between the double curly braces.

For instance, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      {{message.split('').reverse().join('')}}
    </div>
    <script>
      const vm = Vue.createApp({
        data() {
          return {
            message: "hello world"
          };
        }
      }).mount("#app");
    </script>
  </body>
</html>

to reverse 'hello world' in the template.

We can only put in single expressions and not statements, so we can’t write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      {{ var a = 1 }}}
    </div>
    <script>
      const vm = Vue.createApp({
        data() {
          return {
            message: "hello world"
          };
        }
      }).mount("#app");
    </script>
  </body>
</html>

The Vue template compiler will give us an error.

Directives

Directives are special attributes that starts with v- .

The values they expect are single JavaScript expressions.

v-for and v-on are exceptions to this.

We reactively apply the side effects to the DOM when the value of its expression changes.

For instance, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <p v-if="show">hello world</p>
    </div>
    <script>
      const vm = Vue.createApp({
        data() {
          return {
            show: true
          };
        }
      }).mount("#app");
    </script>
  </body>
</html>

to show the ‘hello world’ message with v-if since show is true .

v-if is a directive that shows something when its value is truthy.

Conclusion

Templates can have raw HTML, attributes, and directives.

Directives are special attributes that take values.

Categories
Vue 3

Vue 3 — Event Handling

Vue 3 is in beta and it’s subject to change.

Vue 3 is the up and coming version of Vue front end framework.

It builds on the popularity and ease of use of Vue 2.

In this article, we’ll look at how to handle events in Vue 3 components.

Listening to Events

We can listen to events with the v-on directive, or @ for short.

For instance, we can listen to clicks by writing:

<!DOCTYPE html>  
<html lang="en">  
  <head>  
    <title>App</title>  
    <script src="https://unpkg.com/vue@next"></script>  
  </head>  
  <body>  
    <div id="app">  
      <button v-on:click="onClick">click me</button>  
    </div>  
    <script>  
      const vm = Vue.createApp({  
        methods: {  
          onClick() {  
            alert("clicked");  
          }  
        }  
      }).mount("#app");  
    </script>  
  </body>  
</html>

We added the v-on:click directive to run the onClick method when we click the button.

So we should see an alert when we click the button.

To shorten it, we can write:

<!DOCTYPE html>  
<html lang="en">  
  <head>  
    <title>App</title>  
    <script src="https://unpkg.com/vue@next"></script>  
  </head>  
  <body>  
    <div id="app">  
      <button @click="onClick">click me</button>  
    </div>  
    <script>  
      const vm = Vue.createApp({  
        methods: {  
          onClick() {  
            alert("clicked");  
          }  
        }  
      }).mount("#app");  
    </script>  
  </body>  
</html>

We can put any JavaScript expression as the value of the v-on directive.

Methods in Inline Handlers

We don’t have to bind directly to the method in the expression we pass into v-on .

We can also call the method in there.

For example, we can write:

<!DOCTYPE html>  
<html lang="en">  
  <head>  
    <title>App</title>  
    <script src="https://unpkg.com/vue@next"></script>  
  </head>  
  <body>  
    <div id="app">  
      <button @click="onClick('hi')">hi</button>  
      <button @click="onClick('bye')">bye</button>  
    </div>  
    <script>  
      const vm = Vue.createApp({  
        methods: {  
          onClick(str) {  
            alert(str);  
          }  
        }  
      }).mount("#app");  
    </script>  
  </body>  
</html>

We pass in an argument to the onClick method so that onClick will get the argument and display the message.

To access the event object of the event, we can use the $event object.

For example, we can write:

<!DOCTYPE html>  
<html lang="en">  
  <head>  
    <title>App</title>  
    <script src="https://unpkg.com/vue@next"></script>  
  </head>  
  <body>  
    <div id="app">  
      <button @click="onClick('hi', $event)">click me</button>  
    </div>  
    <script>  
      const vm = Vue.createApp({  
        methods: {  
          onClick(str, event) {  
            event.stopPropagation();  
            alert(str);  
          }  
        }  
      }).mount("#app");  
    </script>  
  </body>  
</html>

to pass in the $event object to our event handler.

Then we can call stopPropagation on it to stop the click event from propagation to parent elements.

This event object is the native event object.

Multiple Event Handlers

We can have multiple event handlers in one expression.

For example, we can write:

<!DOCTYPE html>  
<html lang="en">  
  <head>  
    <title>App</title>  
    <script src="https://unpkg.com/vue@next"></script>  
  </head>  
  <body>  
    <div id="app">  
      <button @click="one($event), two($event)">click me</button>  
    </div>  
    <script>  
      const vm = Vue.createApp({  
        methods: {  
          one(event) {  
            console.log("one");  
          },  
          two(event) {  
            console.log("two");  
          }  
        }  
      }).mount("#app");  
    </script>  
  </body>  
</html>

to run one and two as event handlers when we click on the button.

Event Modifiers

We can add event modifiers so that we don’t have to call methods like event.preventDefault() or event.stopPropagation() in our event handlers.

The modifiers include:

  • .stop
  • .prevent
  • .capture
  • .self
  • .once
  • .passive

These are added to the v-on directive.

For example, to call event.stopPropagation in our event handler, we can write:

<a @click.stop="onClick"></a>

then the click event won’t be propagated to the parent elements.

And if we write:

<form @submit.prevent="onSubmit"></form>

event.preventDefault() will be called when running onSubmit .

Modifiers can also be chained, so we can write:

<a @click.stop.prevent="onClick"></a>

The capture modifier lets us use capture mode when adding an event listener.

And the self modifier only triggers the event handler if the event.target is the element itself.

once will only trigger the event handler at most once.

The passive modifier corresponds to the addEventListener ‘s passive option.

If we add it to the @scroll directive:

<div @scroll.passive="onScroll">...</div>

then the scroll event’s default behavior will happen immediately instead of waiting for onScroll to complete.

passive and prevent shouldn’t be used together since prevent will be ignored.

passive communicates to the browser that we don’t want to prevent the default browser behavior.

Conclusion

We can listen to events with the v-on directives.

It makes many arguments and modifiers.

Categories
Vue 3

Vue 3 — Directive Shorthands and Arguments

Vue 3 is in beta and it’s subject to change.

Vue 3 is the up and coming version of Vue front end framework.

It builds on the popularity and ease of use of Vue 2.

In this article, we’ll look at the dynamic arguments of a directive.

Dynamic Arguments

Vue 3 directives can take dynamic arguments.

For example, we can write:

<a v-bind:[attributeName]="url"> ... </a>

or:

<a v-on:[eventName]="doSomething"> ... </a>

We can pass in an argument to a directive.

This applies to any directives, including the ones we create.

Modifiers

We can also pass in modifiers to a directive.

For instance, the v-on directive can take a modifier for some event.

We can write:

<form v-on:submit.prevent="onSubmit">...</form>

to let us call event.preventDefault in the onSubmit handler.

This lets us stop the default behavior from happening.

For example, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="[https://unpkg.com/vue@next](https://unpkg.com/vue@next)"></script>
  </head>
  <body>
    <div id="app">
      <form v-on:submit.prevent="onSubmit">
        <input v-model="name" />
      </form>
    </div>
    <script>
      const vm = Vue.createApp({
        data() {
          return {
            name: ""
          };
        },
        methods: {
          onSubmit() {
            console.log(this.name);
          }
        }
      }).mount("#app");
    </script>
  </body>
</html>

to create a form with the v-on:submit:prevent directive to run the onSubmit method with the event.preventDefault method all in one directive.

Shorthands

We can shorten v-bind to : .

For example, we can write:

<a :href="url"> ... </a>

instead of:

<a v-bind:href="url"> ... </a>

We can also pass in an argument with the shorthand by writing:

<a :[key]="url"> ... </a>

We can use it by writing:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <a :href="url">link</a>
    </div>
    <script>
      const vm = Vue.createApp({
        data() {
          return {
            url: "http://example.com"
          };
        }
      }).mount("#app");
    </script>
  </body>
</html>

v-on also has their own shorthand.

Instead of writing:

<a v-on:click="doSomething"> ... </a>

We can write:

<a @click="doSomething"> ... </a>

for short.

If we want a dynamic event, we can write:

<a @[event]="doSomething"> ... </a>

So we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <button @click="toggle">toggle</button>
      <p>{{on}}</p>
    </div>
    <script>
      const vm = Vue.createApp({
        data() {
          return {
            on: true
          };
        },
        methods: {
          toggle() {
            this.on = !this.on;
          }
        }
      }).mount("#app");
    </script>
  </body>
</html>

to add a click listener to our button.

Caveats

Dynamic value has some constraints.

Whatever is inside the square brackets must return a string or null .

null can be used to remove the binding.

Any other value will trigger a warning.

Certain characters aren’t valid in HTML, so we can’t have them as the dynamic argument’s value.

So we can’t have names with spaces of quotes.

Something like:

<a v-bind:['foo ' + bar]="value"> ... </a>

won’t work.

We should also avoid naming keys with uppercase characters since browsers will convert them to lowercase.

JavaScript Expressions

Templates expressions are sandboxes so we can’t use global variables in template expressions.

It can only access the list of global variables from a whitelist.

The whitelist is at https://github.com/vuejs/vue-next/blob/master/packages/shared/src/globalsWhitelist.ts#L3.

Conclusion

Vue directives can take dynamic arguments.

Also, there’re various shorthands we can use in place of some directives.