Vue -- properties of an instance -- use / tutorial / instance

Original website:

brief introduction

explain

        This article uses examples to illustrate the use of the properties of Vue instances.

        The attributes of the instance include: $data, $props,$el, $options,$parent,$root,$children,$slots,$scopedSlots,$refs,$isServer,$attrs,$listeners.

        The bold items above are the items introduced in this article, and others will continue to be added later.

Official website

API — Vue.js

$data

brief introduction

The data of components should be defined by functions, such as:

data: function () {
  return {
    count: 0
  }
}

Instead of being defined by objects, such as:

data: {
  count: 0
}

Because when using a function, every time you use the value in data, you will create a new object to return, and each instance has its own data; When using objects, data will be shared (in the relatively new vue version, if it is written in the form of objects, it will not be displayed directly (test version: 2.5.16)).

Example: Vue.js

Other web sites

Component foundation - Vue.js official website

Instance (component)

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

<head>
    <meta charset="UTF-8">
    <title>this is title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
</head>

<body>

<div id="components-demo">
    <button-counter></button-counter>
    <button-counter></button-counter>
</div>

<script>
    Vue.component('button-counter', {
        data: function () {
            return {
                count: 0
            }
        },
        template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
    })

    new Vue({
        el: '#components-demo'
    })
</script>

</body>
</html>

result

  If put   Replace the data of Vue. Component ('button counter '...) with the following definition method:

  data: {
    count: 0
  },

Results: (the results are as follows: (no numbers are displayed, and there is no response when clicking the button)  ) 

Instance (vue only)

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

<head>
    <meta charset="UTF-8">
    <title>this is title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
</head>

<body>

<div id="components-demo">
    <input type="button" @click="changeName">
    {{count}}
</div>

<script>
    new Vue({
        el: '#components-demo',
        data(){return  {
            count: 0,
        }},
        methods:{
            changeName() {
                this.count = this.count + 1;
            }
        }
    })
</script>

</body>
</html>

Test (number plus 1 for each button click)

If you change the data of new Vue to the following definition method:

  data: {
    count: 0
  },

The results are also normal:

Example: combined with engineering

Count component components/Counter.vue

<template>
  <div>
    <input v-model="count" type="button" @click="increase">
    count: {{ count }}
  </div>
</template>

<script>
export default {
  name: "Count",
  data() {
    return {
      count: 0
    }
  },
  methods: {
    increase() {
      this.count++;
    }
  }
}
</script>

<style scoped>

</style>

Reference component components/MyCount.vue

<template>
  <div>
    <MyCounter></MyCounter>
    <MyCounter></MyCounter>
  </div>
</template>

<script>
import MyCounter from "@/components/Counter";
export default {
  name: "MyCount",
  components:{
    MyCounter
  }
}
</script>

<style scoped>

</style>

router/index.js

import Vue from 'vue'
import Router from 'vue-router'
import MyCount from "@/components/MyCount";

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/myCount',
      name: 'myCount',
      component: MyCount
    }
  ]
})

test

Each button is displayed independently, and one button is added for each click.

If put   Replace the data of components/Counter.vue with the following definition method:

  data: {
    count: 0
  },

The results are as follows (no numbers are displayed, and there is no response when clicking the button)  

Webstorm tips:  

principle

Other web sites

Why can't the data attribute in Vue(ES6) be an object?

Why can you define objects with functions?

vue supports taking an object as the value of the data attribute in the vue construction parameter. If data is a method, the internally returned object result will be obtained first. See the code for details:

// vue/src/core/instance/state.js
function initData (vm: Component) {
  var data = vm.$options.data;
  data = vm._data = typeof data === 'function'
    ? getData(data, vm)
    : data || {};
  if (!isPlainObject(data)) {
    data = {};
    process.env.NODE_ENV !== 'production' && warn(
      'data functions should return an object:\n' +
      'https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function',
      vm
    );
  }
  ...
}

$attrs

brief introduction

        $ attrs can collect all the attributes passed from the parent component (excluding these two items: 1.class and style attributes)   2. Not defined by props in the component.

        $ Attrs can easily pass attributes through, and it is relatively simple to use, avoiding the pain of writing more props. During the interview, you often ask what the communication methods of parent-child components are, so props and $attrs are OK.

example

  There are three components A-B-C, and then the attributes in A are passed into C. method 1: pass down layer by layer through props. Method 2: pass through $attrs. Use $attrs here.

components/CompA.vue

<template>
  <div id="compA">
    <comp-b :prop1="aa"
            :prop2="bb"
            :prop3="cc">
    </comp-b>
  </div>
</template>
<script>
import CompB from "@/components/CompB";

export default {
  components: {CompB},
  data() {
    return {
      aa: 'aa',
      bb: 'bb',
      cc: 'cc'
    };
  },
};
</script>

components/CompB

<template>
  <div class="compB">
    <p>in compB</p>
    <p>props: {{prop1}}</p>
    <p>$attrs: {{$attrs}}</p>
    <hr>
    <comp-c v-bind="$attrs"></comp-c>
  </div>
</template>
<script>
import CompC from "@/components/CompC";
export default {
  props: ['prop1'],
  components: { CompC },
};
</script>

component/CompC

<template>
  <div class="compC">
    <p>in compC</p>
    <p>props: {{prop2}}</p>
    <p>$attrs: {{$attrs}}</p>
    <hr>
  </div>
</template>
<script>
export default {
  props: ['prop2'],
};
</script>

router/index.js

import Vue from 'vue'
import Router from 'vue-router'
import CompA from "@/components/CompA";

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/compA',
      name: '/compA',
      component: CompA
    }
  ]
})

test

visit: http://localhost:8080/#/compA

Result: $attrs saves data that is not defined in props.

$listeners

brief introduction

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

example

components/CompA.vue

<template>
  <div id="compA">
    <comp-b v-on:test1="onTest1"
            v-on:test2="onTest2">
    </comp-b>
  </div>
</template>
<script>
import CompB from "@/components/CompB";

export default {
  components: {CompB},
  methods: {
    onTest1() {
      alert('test1 running...');
    },
    onTest2() {
      alert('test2 running...');
    },
  }
};
</script>

components/CompB.vue

<template>
  <div class="compB">
    <comp-c v-bind="$attrs" v-on="$listeners"></comp-c>
  </div>
</template>
<script>
import CompC from "@/components/CompC";
export default {
  props: ['prop1'],
  components: { CompC },

  mounted() {
    this.$emit('test1');
  }
};
</script>

components/CompC.vue

<template>
  <div class="compC">
    <button @click="emit1">CompC button</button>
  </div>
</template>
<script>
export default {
  props: ['prop2'],
  methods:{
    emit1() {
      this.$emit('test2');
    }
  }
};
</script>

router/index.js

import Vue from 'vue'
import Router from 'vue-router'
import CompA from "@/components/CompA";

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/compA',
      name: '/compA',
      component: CompA
    }
  ]
})

test

visit: http://localhost:8080/#/compA

Result: after the CompB is loaded, the event is passed to the CompA for execution: execute the test1 event

Click the button: pass the event from CompC to CompA execution: execute test2 event

$children/$parent/$refs

brief introduction

$refs

Labels, including subcomponents, can be marked.

Example 1: < p ref = "one" > this is content < / P >, and then you can access this tag through this.$refs.one.
Example 2: < firstchild ref = "two" > < / firstchild >, the parent component can access this sub component through this.$refs.two, including accessing the data in the component's data and calling its function.

$children

Returns a collection of components. You can use the this.$children[i]. Property to access sub component data.

$parent

Returns the parent component. this.$parent. Property value / function can be used in child components

example

router/index.js

import Vue from 'vue'
import Router from 'vue-router'
import CompA from "@/components/CompA";

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/compA',
      name: 'compA',
      component: CompA
    }
  ]
})

components/CompA.vue (parent component)

<template>
  <div class="compA">
    <p>CompA</p>
    <button @click="showChildData">Click here for sub components data</button>
    <button @click="runChildFunc">Click here for sub components methods</button>
    <hr>
    <child-one ref="f1"></child-one>
    <child-two ref="f2"></child-two>
  </div>
</template>

<script>
import ChildOne from "@/components/ChildOne";
import ChildTwo from "@/components/ChildTwo";

export default {
  components: {ChildOne, ChildTwo},
  data() {
    return {
      data1: "This is CompA",
    }
  },
  methods: {
    showChildData() {
      //Accessing self components in children mode
      for (let i = 0; i < this.$children.length; i++) {
        console.log("msg of " + i + " : " + this.$children[i].msg);
      }
      //Access subcomponents through $refs
      console.log("data2 of f1 : " + this.$refs.f1.data2);
      console.log("data3 of f2 : " + this.$refs.f2.data3);
    },

    runChildFunc(){
      //Like the data, only one example is given here
      this.$refs.f1.method2();
    }
  },
}
</script>

<style scoped>
</style>

components/ChildOne.vue (sub component 1)

<template>
  <div class="childOne">
    <p>childOne</p>
    <button @click="method2">Click here to get parent component data</button>
    <hr>
  </div>
</template>

<script>
export default {
  data() {
    return {
      data2: "This is data2 of ChildOne",
      msg: "This is msg of ChildOne"
    }
  },
  methods:{
    method2(){
      console.log("method2 of ChildOne: get data1 of CompA : " + this.$parent.data1);
    }
  }
}
</script>

<style scoped>
</style>

components/ChildTwo.vue (sub component 2)

<template>
  <div class="childTwo">
    <p>ChildTwo</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      data3: "This is data3 of ChildTwo",
      msg: "This is msg of ChildTwo"
    }
  }
}
</script>

<style scoped>
</style>

test

visit:   http://localhost:8080/#/compA

Click "click here to get sub component data", "click here to get sub component methods" and "click here to get parent component data"

Other web sites

Can you use $attrs in vue?
vm.$attrs [Vue 2.4.0 added inheritAttrs, detailed explanation of attrs] - brief book

Blog using _jingtian678 of vue component ($children,$refs, $parent) - CSDN blog
Usage of children in vue man's true color blog - CSDN blog

Tags: Javascript Front-end Vue Vue.js

Posted on Sat, 06 Nov 2021 22:11:26 -0400 by Masca