Vue componentization ideas

If all the processing logic in a page is put together, the processing will be very complicated and chaotic, and it is not conducive to subsequent management and expansion.

If the page is split into small functional blocks, and each functional block completes its own independent function, the management and maintenance of the entire page becomes easier.

Insert picture description here
Insert picture description here

A page can be divided into multiple components, and each component can be subdivided

Vue's component idea

① It provides an abstraction that allows us to develop independent and reusable groups to construct our applications in the future.

② Any application will be abstracted into a component tree.

One, the basic steps of registering components

The use of components is divided into three steps

  1. Create component constructor

  2. Registered components (global registration, partial registration)

  3. Use components

1.1 Call Vue.extend() API: Create component constructor: const x = Vue.extend({ })

2.1 Call Vue.component() API: Register component

3.1 Use components within the scope of a Vue instance

1.1.1 Create a component template: (old way of writing)
x is the name of the constructor, which will be quoted during registration. The component is equivalent to an html page, the outermost layer needs to be wrapped with a div, and then the content.
const x = Vue.extend({
    
    
	template:
		`
		<div>
			<h2>我是组件标题</h2>
		</div>
		`
})
2.1.1 Globally register components:'my-cpn' is the tag name of the component, and x is the content of 1.1.1. In other words, when using the x component in the future, use <my-cpn></my-cpn> to replace it.
Vue.component('my-cpn',x)
3.1.1 Use in Vue instance:
<div id="app">
	<my-cpn></my-cpn>
</div>

Second, analysis of the steps to create a component constructor

1. Vue.extend() creates a component constructor, usually in the place where the component is created, the template is passed in to represent the template of the custom component. This template is the HTML code to be displayed where the component is used. The old wording refers to the content of 1.1.1.

2. Vue.component() needs to pass in two parameters, one is the label name of the registered component, and the other is the name of the component constructor. Such as x in 1.1.1.

3. Custom components can be nested multiple times, but there can be no other content in the component tag <my-cpn>

Four, parent and child components

First construct two components:

First:
const cpn1 = Vue.extend({
    
    
	template :`<div><h2>组件1</h2></div>`
})
The second one: Register component 1 in component 2:
const cpn2 = Vue.extend({
    
    
	template :`
	<div>
		<h2>组件2</h2>
		<cpn1></cpn1>
	</div>
	`,
	components:{
    
     
        cpn1:cpn1 // 可以简写为一个cpn1
    } 
})
Component 2 is registered in the instance
const app = new Vue({
    
    
      el: "#app",
      components: {
    
    
        cpn2: cpn2 // 可以简写为一个cpn1
      },
})
use:
  <div id="app">
    <cpn1></cpn1> // 未在实例中注册,不可使用
    <cpn2></cpn2> // 已在实例中注册,可以使用
  </div>

In fact, the const app instance is also a component, but the largest component of the page: the root component ROOT, so the vue instance also has a template. The child component must be created before the parent component, otherwise the child component will not be recognized.

Five, syntactic sugar for registered components

This syntactic sugar is to embed the component's constructor into the registration step.

Original: Follow the order of 1.1->2.1->3.1

1.1 and 2.1 are now combined: (global)

Vue.component('my-cpn',{
    
    
	template: `<div><h2>组件标题</h2></div>`
})

(Partial)

const app = new Vue({
    
    
      el: "#app",
      components: {
    
    
        	'my-cpn': {
    
    
        		template:`<div><h2>组件标题</h2></div>`
        }
      },
  })

Six, the writing method of component template extraction

Because the convenience of writing html statements in the template is not good, so separate the html statements to write

6.1 Written in the <script> tag:

<script type="text/x-template" id="cpn1">
	<div>
		<h2>组件1</h2>
	</div>
</script>

The script tag type is: text/x-template, and the id must be specified for ease of use

Take global registration as an example:

Vue.components( 'my-cpn1' , {
    
     template: '#cpn1' })

Used in the example:

<div id="app">
	<my-cpn1></my-cpn1>
</div>

6.2 Written in the <template> tag:

<template id="cpn2">
	<div>
		<h2>组件2</h2>
	</div>
</template>

Add id to the template tag for ease of use.

Take partial registration as an example:

const app = new Vue({
    
    
      el: "#app",
      components: {
    
    
        	'my-cpn2': {
    
    
        		template: '#cpn2'
        }
      },
  })

Used in the example:

<div id="app">
	<my-cpn2></my-cpn2>
</div>

Seven, notes

1. The internal data or methods of the instance cannot be directly accessed inside the component.

2. A component is a package of a separate functional module, with its own html template.

3. Even if the component is not directly but indirectly allowed to access the data in the instance, assuming that a page has hundreds of components and all the data is stored in the instance, the instance will appear bloated.

4. The vue component must have a place to store its own data.

8. Data storage of components

At the time of registration

<template id="cpn3">
	<div>
		<h2>{
    
    {
    
    title}}</h2>
	</div>
</template>

Vue.components( 'my-cpn3' , 
	{
    
     
		template: '#cpn3',
			data() {
    
    
				return {
    
    
                    title: '组件3'
				}
			}
	})

The place where the component stores its own data is in the data() function at the same level as the template, so it needs to return a value. This value is an object type, which is not the same as the data:{} in the instance. In fact, the prototype of the component points to the vue instance, so there are also instance things in the component, such as life cycle functions.

9. Why data(){} in the component must be a function?

1. If it is stored in the form of an object

①Define an object first:

const obj = {
    
    name: "小明", age:18}

②Save to data:

data(){
    
     return obj }

At this time, memory space has been allocated to store this object, assuming the memory address: 0x100

Follow-up operations:

let obj1 = data() 
let obj2 = data() 
obj1.name = '小红'
console.log(obj1) 
console.log(obj2) 

结果: name: '小红' age :18
      name: '小红' age :18

obj1 and obj2 point to the content of the same memory space, obj1.name ='Xiaohong', which is equivalent to modifying the content in this memory address, so even if obj2 does not modify the object, the content obtained has changed .

2. If it is stored in the form of a function

data(){
    
    
	return{
    
    
		name: "小明",
		age:18
	}
}

It is just a definition and declaration. There is no space for object storage in the memory. If this function is called, the memory space is opened up.

Follow-up operations:

let obj1 = data() 
let obj2 = data() 
obj1.name = '小红'
console.log(obj1) 
console.log(obj2) 

结果: name: '小红' age :18
      name: '小明' age :18

obj1 calls data() once, the memory opens up space to store name and age, assuming the memory address is 0x100

obj2 calls data() once, and the memory opens up space to store name and age, assuming the memory address is 0x200

Every time data() is called, a new space will be opened for storage, so the memory address is different, that is, obj1 and obj2 are just two memory spaces with the same content but no relationship. In subsequent operations, obj1 modifies the name, but only modifies the data in 0x100. Obj2 remains the same as the content obtained for the first time and is not affected. The two use data independently. Ensure the independence and reusability of components.

10. Communication between parent and child components

1. The parent component passes messages to the child component through props.

2. The child component sends a message to the parent component through the event.

Insert picture description here

The basic usage of props: pass data from the parent component (root component) to the child component

10.1 Define a template (subcomponent)
<template id="soncpn">
	<div>
		<p>{
   
   {sonmessage}}</p>
		<h2>{
   
   {sonmovies}}</h2>
	</div>
</template> 
// 先留两个空位给message和movies
10.2 Construct component, constructor name: cpn
const cpn = {
    
    
     template: "#soncpn",
     props: ['sonmessage','sonmovies']
  }
  // props用来接收父组件传来的数据
10.3 Treat the vue instance as the parent component and register the child component in the parent component
const app = new Vue({
    
    
      el: "#app",
      data:{
    
    
      	message: "hello world!",
      	movies:['电影1','电影2']
      }
      components: {
    
    
        	cpn
      },
  })
10.4 Transfer data
<div id="app">
	<cpn :sonmessage="message" :sonmovies="movies"></cpn>
</div>

11. The second way of writing props and type verification

1. Writing

The first way of writing: Refer to 10.2

props:['sonmessage','sonmovies']

The second way of writing:

props:{
    
    
	sonmessage: String,
	sonmovies: Array
}

The second way of writing is extended:

props:{
    
    
	sonmessage: {
    
    
		type: String,
		default: '默认值'
	}
	sonmovies: {
    
    
		type: Array,
		default(){
    
    
			return []
		}
	}
}

The second way of writing is to force the incoming data type. When the incoming type definition is an array or an object, the default value must be specified using a factory function.

When the incoming value is of multiple types:

type: [String,Number...]

2. Attention to props name: Camel case name should be converted to-connection

props:['sonMessageInfo']

In the example:

<cpn :son-message-info="xxx"></cpn>

It doesn't matter in <template>

<template>
	<div>
		<h2>{
   
   {sonMessageInfo}}</h2>
	</div>
</template>

Twelve, the child component passes data to the parent component (custom event)

Two-way binding of props

1. The subcomponent sends events and parameters through $emit.

2. The parent component monitors through v-on / @

If you want to bind the incoming props in two directions, it is not recommended to directly v-model="props", but use a new variable in data instead. Here is an example of the input event of the input input box. The dynamically bound value, which is numberdata, is passed to the parent component through $emit, and then this event is monitored in the parent component template, and the passed value is obtained in the parent component The method is defined in methods, and the obtained value is assigned to the data in the parent component data.

Insert picture description here

<body>
  <div id="app">
    <h2>{
   
   {homeNum}}</h2>
    <cpn :numberprops="homeNum" @numinput="num1change"></cpn>
  </div>

  <script src="./js/vue.js"></script>

  <template id="cpn">
    <div>
      <h2>子组件:{
   
   {numberdata}}</h2>
      <h2>props:{
   
   {numberprops}}</h2>
      <input type="text" :value="numberdata" @input="numinput">

    </div>
  </template>

  <script>
    // 3、在页面中使用组件
    const app = new Vue({
     
     
      el: "#app",
      data: {
     
     
        homeNum: 2
      },
      methods: {
     
     
        num1change(value) {
     
     
          this.homeNum = parseInt(value)
          // console.log(value)
        }
      },
      components: {
     
     
        cpn: {
     
     
          template: "#cpn",
          props: {
     
     
            numberprops: Number
          },
          data() {
     
     
            return {
     
     
              numberdata: this.numberprops
            }
          },
          methods: {
     
     
            numinput() {
     
     
              this.numberdata = event.target.value
              // console.log(this.number)
              this.$emit('numinput', this.numberdata)

            }
          }
        }
      },
    })
  </script>
</body>

Summarized in 4 steps:

1. Add default events to sub-templates.

2. Use $emit in the subcomponent methods to send custom events.

3. @Custom event name = "parent component processing event name" in the parent template to monitor.

4. Processing in parent component methods: parent component processing event name () {processing logic}

13. Access method of parent and child components

Direct access through objects

Parent component access to child components: $children, $refs

To use $refs, you must add the ref attribute to the component tag.

// 在父模板中
<div id="app">
	<cpn ref="aaa"></cpn>
	<cpn1 ref="bbb"></cpn1>
	<cpn2></cpn2>
</div>

this.$refs can get all the subcomponents with ref attribute added

this.$refs.aaa can get specific items

Child component access parent component: $parent​

The parent component may contain multiple child components, so what this.$children gets is an array type.

this.$parent is a single object, it can only get to the upper level component

Supplement: Get the root instance: this.$root

Guess you like

Origin blog.csdn.net/michaelxuzhi___/article/details/106268178