Vue3 official website basic Class and Style binding (binding HTML Class, inline, array), conditional rendering (v-if), list rendering v-for (array update, using v-for on components)

Vue3 official website basic (III) Class and Style binding (binding HTML Class, inline, array), conditional rendering (v-if), list rendering v-for (array update, using v-for on components)

Summary:

  • supplement

    • Vue (pronunciation / vju) ː/, Similar to view) is a progressive framework for building user interfaces. Unlike other large frameworks, Vue is designed to be applied layer by layer from bottom to top. Vue's core library only focuses on view layers, which is not only easy to start, but also easy to integrate with third-party libraries or existing projects.
    • Truth: in JavaScript In, truth refers to Boolean value In context, the converted value is a true value. All values are true unless they are defined as False value (that is, all values are true except false, 0, "", null, undefined and NaN). The values in parentheses are false.
    • The. prevent modifier tells the v-on instruction to call event.preventDefault() for the triggered event
    • ==The Event.preventDefault method cancels the browser's default behavior for the current event== For example, after clicking the link, the browser will jump to another page by default. After using this method, it will not jump; For another example, press the spacebar and the page will scroll down for a distance. This method will not scroll in the future. The precondition for this method to take effect is that the cancelable attribute of the event object is true. If it is false, calling this method has no effect.
  • Class is bound to Style

    • Bind HTML Class

      • inline

        :class="{ active: isActive, 'text-danger': hasError }"
        
      • The bound data object does not need to be defined inline in the template, but can also bind a return object here Calculation properties. :

        <div :class="classObject"></div>
        --------------------------------------------------
        data() {
          return {
            isActive: true,
            error: null
          }
        },
        computed: {
          classObject() {
            return {
              active: this.isActive && !this.error,
              'text-danger': this.error && this.error.type === 'fatal'
            }
          }
        }
        
      • Array syntax (array, ternary expression, object syntax)

        <div :class="[activeClass, errorClass]"></div>
        ---------------------------------------------------
        <div :class="[isActive ? activeClass : '', errorClass]"></div> //Ternary expression
        ---------------------------------------------------
        <div :class="[{ active: isActive }, errorClass]"></div>//Object syntax
        
      • Using class on components

  • Conditional rendering (if)

  • v-if

    • v-if is a "real" conditional rendering because it ensures that the event listeners and subcomponents within the conditional block are properly destroyed and rebuilt during switching.

      v-if is also lazy: if the condition is false at the initial rendering, nothing is done -- the conditional block does not start rendering until the condition first becomes true.

    • Because v-if is an instruction, it must be added to an element. But what if you want to switch multiple elements? At this point, you can treat a < template > element as an invisible wrap element and use v-if on it. The final render will not contain the < template > element.

  • v-else-if

  • v-else

    • The v-else element must follow the element with v-if or v-else-if, otherwise it will not be recognized.
  • v-show

    • Another option for conditionally presenting elements
    • The difference is that elements with v-show are always rendered and retained in the DOM. V-show simply switches the CSS property display of the element.
    • In contrast, v-show is much simpler -- no matter what the initial conditions are, elements are always rendered and simply switched based on CSS.
  • v-if has higher switching overhead, while v-show has higher initial rendering overhead. Therefore, if you need to switch very frequently, it is better to use v-show; If the conditions rarely change at run time, it is better to use v-if.

  • List rendering v-for

    • array

      • <li v-for="item in items">
            {{ item.message }}
        </li>
        ---------------------------------------------------
         <li v-for="(item, index) in items">
            {{ parentMessage }} - {{ index }} - {{ item.message }}
          </li>//v-for also supports an optional second parameter, the index of the current item.
        
    • object

      • <li v-for="value in myObject">
            {{ value }}
        </li>
        ---------------------------------------------------
        <li v-for="(value, name) in myObject">
          {{ index }}. {{ name }}: {{ value }}
        </li>
        
  • Maintenance status

    • It is recommended to provide key attribute when using v-for as much as possible, unless it is very simple to traverse the output DOM content, or deliberately rely on the default behavior to improve performance.
  • Array update

    • Change original array
      • push(): used to add one or more elements at the end of the array and return the length of the array after adding new elements.
      • pop(): used to delete the last element of the array and return it.
      • shift(): used to delete the first element of the array and return it
      • unshift(): used to add an element at the first position of the array and return the length of the array after adding a new element
      • splice(): used to delete some members of the original array and add new array members at the deleted position. The return value is the deleted element. Note that this method changes the original array.
      • sort(): sort the array members in dictionary order by default. After sorting, the original array will be changed.
      • reverse(): used to invert the array elements and return the changed array.
    • Returns a new array without changing the original array
      • filter(): used to filter array members. Members that meet the conditions form a new array and return.
      • concat()
      • slice(): used to extract a part of the target array and return a new array. The original array remains unchanged.
      • Replacing the original array with an array containing the same elements is a very efficient operation.

1. Bind class to Style

The class list and inline style of operation elements are a common requirement of data binding. Because they are all attribute s, we can handle them with v-bind: we just need to calculate the string result through the expression. However, string splicing is cumbersome and error prone. Therefore, Vue.js has been specially enhanced when using v-bind for class and style. In addition to strings, the type of expression results can also be objects or arrays.

Bind HTML Class

Object syntax

We can pass: class (v-bind: short for class) an object to dynamically switch class:

<div :class="{ active: isActive }"></div>

The above syntax indicates that the existence of the active class will depend on the data property isActive truthiness.

You can dynamically switch multiple classes by passing in more fields in the object. In addition, the: class instruction can coexist with the normal class attribute. When there are the following templates:

<div
  class="static"
  :class="{ active: isActive, 'text-danger': hasError }"
></div>

And the following data:

data() {
  return {
    isActive: true,
    hasError: false
  }
}

The rendered result is:

<div class="static active"></div>

When isActive or hasError changes, the class list will be updated accordingly. For example, if the value of hasError is true, the class list will change to "static active text danger".

The bound data object does not need to be defined inline in the template:

<div :class="classObject"></div>
data() {
  return {
    classObject: {
      active: true,
      'text-danger': false
    }
  }
}

The rendering result is the same as above. We can also bind a return object here Calculation properties . This is a common and powerful pattern:

<div :class="classObject"></div>
data() {
  return {
    isActive: true,
    error: null
  }
},
computed: {
  classObject() {
    return {
      active: this.isActive && !this.error,
      'text-danger': this.error && this.error.type === 'fatal'
    }
  }
}

Array syntax

We can pass an array to: class to apply a class list:

<div :class="[activeClass, errorClass]"></div>
data() {
  return {
    activeClass: 'active',
    errorClass: 'text-danger'
  }
}

The rendered result is:

<div class="active text-danger"></div>

If you want to switch class es in the list according to conditions, you can use a ternary expression:

<div :class="[isActive ? activeClass : '', errorClass]"></div>

This will always add errorClass, but only if isActive is true[ 1] activeClass is added only when.

However, it is cumbersome to write this when there are multiple conditional class es. Therefore, object syntax can also be used in array syntax:

<div :class="[{ active: isActive }, errorClass]"></div>

Use on components

This chapter assumes that you have Vue components Of course, you can skip here and look back later.

When you use class attribute on a custom component with a single root element, these classes will be added to the element. Existing classes on this element will not be overwritten.

For example, if you declare this component:

const app = Vue.createApp({})

app.component('my-component', {
  template: `<p class="foo bar">Hi!</p>`
})

Then add some class es when using it:

<div id="app">
  <my-component class="baz boo"></my-component>
</div>

The HTML will be rendered as:

<p class="foo bar baz boo">Hi</p>

The same applies to class es with data binding:

<my-component :class="{ active: isActive }"></my-component>

When isActive is true[ 1] When, HTML is rendered as:

<p class="foo bar active">Hi</p>

If your component has multiple root elements, you need to define which parts will receive this class. You can do this using the $attrs component attribute:

<div id="app">
  <my-component class="baz"></my-component>
</div>
const app = Vue.createApp({})

app.component('my-component', {
  template: `
    <p :class="$attrs.class">Hi!</p>
    <span>This is a child component</span>
  `
})

You can Non prop Attribute Section to learn more about component property inheritance.

Bind inline style

Object syntax

: style's object syntax is very intuitive - it looks very much like CSS, but it is actually a JavaScript object. The CSS property name can be named by camel case or kebab case (remember to enclose it in quotation marks):

<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>

1

data() {
  return {
    activeColor: 'red',
    fontSize: 30
  }
}

It is usually better to bind directly to a style object, which makes the template clearer:

<div :style="styleObject"></div>
data() {
  return {
    styleObject: {
      color: 'red',
      fontSize: '13px'
    }
  }
}

Similarly, object syntax is often used in conjunction with the calculated properties of the returned object.

Array syntax

: style's array syntax can apply multiple style objects to the same element:

<div :style="[baseStyles, overridingStyles]"></div>

Auto prefix

One is required to use in: style vendor prefix (browser engine prefix), Vue will automatically detect and add the corresponding prefix. Vue determines which style properties are supported by the current browser through runtime detection. If the browser does not support a property, Vue will test several times to find the prefix that supports it.

Multiple value

You can provide an array containing multiple values for the property in the style binding. It is often used to provide multiple prefixed values, such as:

<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>

This will render only the last value in the array supported by the browser. In this example, if the browser supports flexbox without browser prefix, only display: flex will be rendered.

translator's note
[1] Truth is not true, see MDN Explanation.

2. Conditional rendering (if)

v-if

The v-if instruction is used to conditionally render a piece of content. This piece of content will only be rendered when the expression of the instruction returns the truth value.

<h1 v-if="awesome">Vue is awesome!</h1>

You can also add an else block with v-else:

<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>Oh no 😢</h1>

Use v-if conditional rendering groups on < template > elements

Because v-if is an instruction, it must be added to an element. But what if you want to switch multiple elements? At this time, you can treat a < template > element as an invisible wrap element and use v-if on it. The final rendering result will not contain < template > elements.

<template v-if="ok">
  <h1>Title</h1>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>
</template>

v-else

You can use the v-else instruction to represent the "else block" of v-if:

<div v-if="Math.random() > 0.5">
  Now you see me
</div>
<div v-else>
  Now you don't
</div>

The v-else element must follow the element with v-if or v-else-if, otherwise it will not be recognized.

v-else-if

v-else-if, as the name suggests, acts as the "else if block" of v-if and can be used continuously:

<div v-if="type === 'A'">
  A
</div>
<div v-else-if="type === 'B'">
  B
</div>
<div v-else-if="type === 'C'">
  C
</div>
<div v-else>
  Not A/B/C
</div>

Similar to the use of v-else, v-else-if must follow the element with v-if or v-else-if.

v-show

Another option for conditional display elements is the v-show instruction. The usage is roughly the same:

<h1 v-show="ok">Hello!</h1>

1

The difference is that elements with v-show are always rendered and retained in the DOM. V-show simply switches the CSS property display of elements.

Note that v-show does not support < template > elements or v-else.

v-if vs v-show

v-if is a "real" conditional rendering because it ensures that the event listeners and subcomponents within the conditional block are properly destroyed and rebuilt during switching.

v-if is also lazy: if the condition is false at the initial rendering, nothing is done -- the conditional block does not start rendering until the condition first becomes true.

In contrast, v-show is much simpler -- no matter what the initial conditions are, elements are always rendered and simply switched based on CSS.

Generally speaking, v-if has higher switching overhead, while v-show has higher initial rendering overhead. Therefore, if you need to switch very frequently, v-show is better; if the conditions change little at runtime, v-if is better.

Use v-if with v-for

Tips

Using both v-if and v-for is not recommended. Please refer to Style guide For more information.

When v-if is used with v-for, v-if has a higher priority than v-for. See List rendering Guide For details.

3. List rendering

Use v-for to correspond an array to a set of elements

We can use the v-for instruction to render a list based on an array. The v-for instruction requires a special syntax in the form of item in items, where items is the source data array and item is the alias of the array element being iterated.

<ul id="array-rendering">
  <li v-for="item in items">
    {{ item.message }}
  </li>
</ul>
Vue.createApp({
  data() {
    return {
      items: [{ message: 'Foo' }, { message: 'Bar' }]
    }
  }
}).mount('#array-rendering')

result:

In the v-for block, we can access the properties of all parent scopes. v-for also supports an optional second parameter, the index of the current item.

<ul id="array-with-index">
  <li v-for="(item, index) in items">
    {{ parentMessage }} - {{ index }} - {{ item.message }}
  </li>
</ul>
Vue.createApp({
  data() {
    return {
      parentMessage: 'Parent',
      items: [{ message: 'Foo' }, { message: 'Bar' }]
    }
  }
}).mount('#array-with-index')

result:

You can also use of instead of in as the separator, because it is closer to the syntax of JavaScript iterators:

<div v-for="item of items"></div>

Using objects in v-for

You can also use v-for to traverse the properties of an object.

<ul id="v-for-object" class="demo">
  <li v-for="value in myObject">
    {{ value }}
  </li>
</ul>
Vue.createApp({
  data() {
    return {
      myObject: {
        title: 'How to do lists in Vue',
        author: 'Jane Doe',
        publishedAt: '2016-04-10'
      }
    }
  }
}).mount('#v-for-object')

result:

You can also provide the second parameter as property name (i.e. key name):

<li v-for="(value, name) in myObject">
  {{ name }}: {{ value }}
</li>

You can also use the third parameter as an index:

<li v-for="(value, name, index) in myObject">
  {{ index }}. {{ name }}: {{ value }}
</li>

Tips

When traversing an object, it will be traversed according to the result of Object.keys(), but its results under different JavaScript engines cannot be guaranteed to be consistent.

Maintenance status

When Vue is updating the list of elements rendered using v-for, it defaults to the "update in place" policy. If the order of data items is changed, Vue will not move DOM elements to match the order of data items, but update each element in place and ensure that they are rendered correctly at each index position.

This default mode is efficient, but only applies to list rendered output that does not depend on subcomponent state or temporary DOM state (for example, form input value).

In order to give Vue a hint so that it can track the identity of each node and reuse and reorder existing elements, you need to provide a unique key attribute for each item:

<div v-for="item in items" :key="item.id">
  <!-- content -->
</div>

proposal Provide the key attribute when using v-for as much as possible, unless it is very simple to traverse the output DOM content, or deliberately rely on the default behavior to improve performance.

Because it is a general mechanism for Vue to identify nodes, key is not specifically associated with v-for. As we will see later in the guide, it also has other uses.

Tips

Do not use non basic type values such as objects or arrays as v-for key s. Use string or numeric type values instead.

For more detailed usage of key attribute, please move to API documentation for key.

Array update detection

Change method

Vue wraps the change method of the array being listened on, so they will also trigger view updates. These wrapped methods include:

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

You can open the console and try calling the change method on the items array in the previous example. For example, example1. Items. Push ({message: 'Baz'}).

Replace array

Changing methods, as the name suggests, changes the original array that calls these methods. In contrast, there are non change methods, such as filter(), concat(), and slice(). They do not change the original array, but always return a new array. When using the non change method, you can replace the old array with the new array:

example1.items = example1.items.filter(item => item.message.match(/Foo/))

You might think that this will cause Vue to discard the existing Dom and re render the entire list. Fortunately, this is not the case. Vue implements some intelligent heuristic methods to maximize the reuse of DOM elements, so it is very efficient to replace the original array with an array containing the same elements.

Display filtered / sorted results

Sometimes we want to display the filtered or sorted version of an array without actually changing or resetting the original data. In this case, you can create a calculated property to return the filtered or sorted array.

For example:

<li v-for="n in evenNumbers" :key="n">{{ n }}</li>
data() {
  return {
    numbers: [ 1, 2, 3, 4, 5 ]
  }
},
computed: {
  evenNumbers() {
    return this.numbers.filter(number => number % 2 === 0)
  }
}

When the calculated attribute is not applicable (for example, in a nested v-for loop), you can use one method:

<ul v-for="numbers in sets">
  <li v-for="n in even(numbers)" :key="n">{{ n }}</li>
</ul>
data() {
  return {
    sets: [[ 1, 2, 3, 4, 5 ], [6, 7, 8, 9, 10]]
  }
},
methods: {
  even(numbers) {
    return numbers.filter(number => number % 2 === 0)
  }
}

Range of values used in v-for

v-for can also accept integers. In this case, it repeats the template the corresponding number of times.

<div id="range" class="demo">
  <span v-for="n in 10" :key="n">{{ n }} </span>
</div>

result:

Use v-for in < template >

Similar to v-if, you can also use < template > with v-for to loop render a piece of content containing multiple elements. For example:

<ul>
  <template v-for="item in items" :key="item.msg">
    <li>{{ item.msg }}</li>
    <li class="divider" role="presentation"></li>
  </template>
</ul>

v-for is used with v-if

TIP

Note that we do not recommend using v-if and v-for on the same element. More details are available Style guide.

When they are in the same node, the priority of v-if is higher than that of v-for, which means that v-if will not have access to the variables in v-for:

<!-- This will throw an error because property "todo" is not defined on instance. -->

<li v-for="todo in todos" v-if="!todo.isComplete">
  {{ todo.name }}
</li>

You can move v-for to the < template > tab to correct:

<template v-for="todo in todos" :key="todo.name">
  <li v-if="!todo.isComplete">
    {{ todo.name }}
  </li>
</template>

Using v-for on components

This part assumes that you already know assembly Relevant knowledge. You can also skip it first and come back later.

On custom components, you can use v-for as on any common element:

<my-component v-for="item in items" :key="item.id"></my-component>

However, any data will not be automatically transferred to the component, because the component has its own independent scope. To transfer iterative data to components, we use props:

<my-component
  v-for="(item, index) in items"
  :item="item"
  :index="index"
  :key="item.id"
></my-component>

The reason why item s are not automatically injected into components is that this makes components closely coupled with the operation of v-for. Clarifying the source of component data can enable components to be reused in other occasions.

Here is a complete example of a simple todo list:

<div id="todo-list-example">
  <form v-on:submit.prevent="addNewTodo">
    <label for="new-todo">Add a todo</label>
    <input
      v-model="newTodoText"
      id="new-todo"
      placeholder="E.g. Feed the cat"
    />
    <button>Add</button>
  </form>
  <ul>
    <todo-item
      v-for="(todo, index) in todos"
      :key="todo.id"
      :title="todo.title"
      @remove="todos.splice(index, 1)"
    ></todo-item>
  </ul>
</div>
const app = Vue.createApp({
  data() {
    return {
      newTodoText: '',
      todos: [
        {
          id: 1,
          title: 'Do the dishes'
        },
        {
          id: 2,
          title: 'Take out the trash'
        },
        {
          id: 3,
          title: 'Mow the lawn'
        }
      ],
      nextTodoId: 4
    }
  },
  methods: {
    addNewTodo() {
      this.todos.push({
        id: this.nextTodoId++,
        title: this.newTodoText
      })
      this.newTodoText = ''
    }
  }
})

app.component('todo-item', {
  template: `
    <li>
      {{ title }}
      <button @click="$emit('remove')">Remove</button>
    </li>
  `,
  props: ['title'],
  emits: ['remove']
})

app.mount('#todo-list-example')

Tags: Javascript Vue.js html

Posted on Thu, 16 Sep 2021 23:42:28 -0400 by jobe1