Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

10 simple tips to make your vue .js code more elegant


Jun 01, 2021 Article blog


Table of contents


The article was reproduced from the public number: Frontman

preface

As a deep code cleaner, we all want to write simple and efficient code, make our code look more elegant, let us abandon the complicated code, together to start a simple journey

Slots' new syntax is in alignment with 3.0

Available in Vue 2.6.0 plus using the newly named slot abbreviation syntax with the word """

For example:

When building slots, it's a good idea to plan the layout. T his is the layout of my article. B uilding slots is no different from building components. Essentially, slots are powerful components, so let's break down the layout above, and the components look like this:

<!-- TidbitPage.vue -->
<template>
  <article-layout>


    <template #articleHeader>
      <h1>I am the header</h1>
    </template>


    <template #articleContent>
      <p>I am the content</p>
    </template>


    <template #articleFooter>
      <footer>I am the footer</footer>
    </template>


    <template #side>
      <aside>I am the side stuff</aside>
    </template>


    <template #banner>
      <div>I am the banner</div>
    </template>


  </article-layout>
<template>

Dynamic instruction parameters

Instruction parameters can now accept dynamic JavaScript expression Dynamic parameter values should be strings, but it would be convenient to allow null as a special value that explicitly indicates that the binding should be removed. A ny other non-string values can go wrong and trigger a warning. v-bind和v-on only)

<div v-bind:[attr]="attributeName"></div>
//简写
<div :[attr]="attributeName"></div>

The attributeName here is dynamically evaluated as a JavaScript expression, and the resulting value is used as the final argument. For example, if your Vue instance has a data attributeName with a value of href the binding will be equivalent to v-bind:href

Similarly, you can use dynamic parameters to bind handlers for a dynamic event name:

<button v-on:[eventName]="handler"></button>
//简写
<button @[eventName]="handler"></button>

When the value of eventName is focus v-on:[eventName] will be equivalent to v-on:focus

The same applies to slot bindings:

<my-component>
<template v-slot:[slotName]>
Dynamic slot name
</template>
</my-component>
//简写
<foo>
<template #[name]>
Default slot
</template>
</foo>

Dynamic parameters are expected to find a string with an unusual value of null. T his particular null value can be explicitly used to remove bindings. Any other value of a non-string type will trigger a warning.

<!-- 这会触发一个编译警告 且 无效 -->
<a v-bind:['foo' + bar]="value"> ... </a>

The workaround is to use an expression without spaces or quotation marks, or to replace this complex expression with a calculated property.

@hook those things

To work with the timer within the component. Usually we do this:

<script>
  export default {
    mounted() {
      this.timer = setInterval(() => { ... }, 1000);
    },
    beforeDestroy() {
      clearInterval(this.timer);
    }
  };
</script>

But it's actually better to:

<script>
  export default {
    mounted() {
      const timer = setInterval(() => { ... }, 1000);
      this.$once('hook:beforeDestroy', () => clearInterval(timer);)
    }
  };
</script>

Imagine a scenario where we need to let the page loading before the data is rendered to loading page. S top loading after mounted loading beforeUpdata loading updatad stop loading

The easiest way is to override the component's lifecycle function so that it notifies the parent component to display or hide the load when mounted/beforeUpdata /updatad

This does not show well because the logic from the component is intruded, and the added logic is not related to the functionality of the component itself. The best way is to use v-on="hook:xxx"

<v-chart
    @hook:mounted="loading = false"
    @hook:beforeUpdated="loading = true"
    @hook:updated="loading = false"
    :data="data"
/>

In this way, monitoring of the lifecycle of subcomponents is implemented. It works for any component, including third-party components that are introduced.

$props $attrs and $listeners in vue (can be used for secondary package components)

$props: The props object received by the current component. The Vue instance represents access to its props object properties.

Suppose you have an input input box. W e have many native properties, such as name, placeholder, disabled, and so on. I f we all define receiving in the props display, it is too cumbersome. S o the official website appears: v-bind="$props" such an operation. If the parent component passes many native properties, we can directly:

//good
<input v-bind="$props">

 
//bad
//而不是下面这样,如果很多的属性就特别繁琐
<input :name="name" :placeholder="placeholder" :disabled="disabled">

We can pass native properties directly to child components $attrs which is a new property that Vue adds in 2.4.0 and contains attribute bindings (except class and style) that are not recognized (and acquired) as props in the parent scope. When a component does not declare any props, it contains bindings for all parent scopes (except class and style), and internal components can be passed in via v-bind "$attrs" - useful when creating high-level components.

<input
   v-bind="$attrs"
   :value="value"
   @focus=$emit('focus', $event)"
   @input="$emit('input', $event.target.value)"
>

$listeners Contains the v-on event listener in the parent scope (without .native decorator). It can be passed in to internal components through v-on="$listeners" -- which is useful when creating higher-level components.

If the child component is not under the parent component's root, you can pass all event listeners from the parent component to the child component as follows:

<template>
<div>
  ...
<childComponent v-on="$listeners" />...
</div>
</template>

Responsive data (2.6.0 new)

We're used to using Vuex to solve state sharing problems, but using it in small projects can have the hassle of increasing code volume and complicating it, so Vue will be added in later releases

Vue.observable( object ) an object to respond, which Vue internally uses to handle objects returned by the data function.

The returned objects can be used directly within rendering functions and calculated properties, and updates are triggered when changes occur. It can also be used as a minimized cross-component state memory for simple scenarios:

Official example:

const state = Vue.observable({ count: 0 })


const Demo = {
  render(h) {
    return h('button', {
      on: { click: () => { state.count++ }}
    }, `count is: ${state.count}`)
  }
}

jsx template component

Using the following set of status-judgment buttons as an example, it's easy to subconsciously write this code in a template

<button v-if="status === 1" class="btn1" :class="status === 1" @click="">未开始</button>
<button v-if="status === 2" class="btn2" :class="status === 2" @click="">进行中</button>
<button v-if="status === 3" class="btn3" :class="status === 3" @click="">可领取</button>
<button v-if="status === 4" class="btn4" :class="status === 4" @click="">已领取</button>

But if we use the render function, we can extract the above code into an elegant usage component

<!DOCTYPE html>
<html lang="en">


<body>
    <div id="app">
        <child :status="status"></child>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        Vue.component('child', {
            props: {
                status: {
                    type: Number,
                    required: true
                }
            },
            render(createElement) {
                const innerHTML = ['未开始', '进行中', '可领取', '已领取'][this.status]
                return createElement('button', {
                    class: {
                        active: this.status
                    },
                    attrs: {
                        id: 'btn'
                    },
                    domProps: {
                        innerHTML
                    },
                    on: {
                        click: () => console.log(this.status)
                    }
                })
            }
        })
        var app = new Vue({
            el: '#app',
            data: {
                status: 0
            }
        })
    </script>
</body>


</html>

We encapsulate all the logic into the render function, and the outside only needs to pass one state parameter to change

<child :status="status"></child>

Dynamic components

The effect of dynamic components can be achieved by adding a special is attribute to the elements of Vue

As shown, this is a list of v-for renderings (only this section is just beginning to be done, there is only one at present), and within the circle is a component, which is the v-for dynamic component

Actual use

The basic components were introduced from the beginning

import ColorIn from '@/components/Magic/ColorIn.vue'
import LineIn from "@/components/Magic/LineIn.vue";
import Header from "@/components/Magic/Header.vue";
import Footer from "@/components/Magic/Footer.vue";


export default{
      components:{
        ColorIn,
        LineIn,
        Header,
        Footer
    }
}

Next up is the use of dynamic v-for dynamic componentList:['ColorIn','LineIn','Header','Footer'] use the following code to loop the code in turn

<component v-for="(item,index) in componentList" :key="index" :is="item"></component>

The effect after compilation is

<ColorIn></ColorIn>
<LineIn></LineIn>
<Header></Header>
<Footer></Footer>

Vue.filter

A brief introduction to the filter, as the name implies, filtering is a data after this filter out of another thing, can be from which to get what you want, or add some decoration to that data, then filter is a filtering tool. For example, if you get a value containing 'ab', from the array of 'abc', 'abd', 'ade', you can filter out 'abc' and 'abd';

Scenario: Timestamp conversion into adult moon days is a common method, so it can be pumped away into a filter to use

// 使用
// 在双花括号中
{{ message | capitalize }}


// 在 `v-bind` 中
<div v-bind:id="rawId | formatId"></div>


// 全局注册
Vue.filter('stampToYYMMDD', (value) =>{
  // 处理逻辑
})


// 局部注册
filters: {
  stampToYYMMDD: (value)=> {
    // 处理逻辑
  }
}


// 多个过滤器全局注册
// /src/common/filters.js
let dateServer = value => value.replace(/(\d{4})(\d{2})(\d{2})/g, '$1-$2-$3')
export { dateServer }
// /src/main.js
import * as custom from './common/filters/custom'
Object.keys(custom).forEach(key => Vue.filter(key, custom[key]))

.sync grammar sugar

sync is to implement prop for "two-way binding" and that's all (parent-to-child, child-to-parent, back-and-forth)

This method works well when you need to modify parent component values in child components, and its implementation mechanism is the same as v-model.

Improve performance with object.freeze

Object.freeze() method freezes an object. A frozen object can no longer be modified, an object that is frozen cannot add new properties to the object, cannot delete existing properties, cannot modify the enumeration, configurability, writeability, and cannot modify the value of an existing property. I n addition, the prototype of an object cannot be modified after it is frozen. freeze() returns objects with the same parameters as the incoming ones.

For example, we need to render a very large array of objects, such as user lists, object lists, article lists, and so on.

export default {
  data: () => ({
    users: {}
  }),
  async created() {
    const users = await axios.get("/api/users");
    this.users = users;
  }
};

vue adds all the properties in the data object to vue's responsive system, and when the values of those properties change, the view produces a response that, if the object is large, consumes a lot of browser resolution time.

So we can provide front-end performance by reducing the responsive transformation of data.

export default {
  data: () => ({
    users: {}
  }),
  async created() {
    const users = await axios.get("/api/users");
    this.users = Object.freeze(users);
  }
};

Here's a look at W3Cschool编程狮 about 10 simple tips to make your vue .js code more elegant.