Vue component development--encapsulation of public components

Table of contents

Why package components

Application Scenario

Vue encapsulates components by itself (local, global) 

Three elements of Vue components

①Global components

1) Method:

 2) Example:

②Partial components

1) Method:

2) Example:

Naming convention: (note)

Scaffolding components in vue-cli

Father to son (props)

Pass the parent component method through $on

$parent gets the parent component and then uses the data in the parent component (not recommended)

Pass parent component data via $emit (recommended) 

refs get

Component style modification Style penetration 

Plugin use: slot


Why package components

The projects developed with Vue are all developed with the idea of ​​componentization.

Generally, when building a project, a views directory, a commen directory and a feature directory will be created.

  • Put page-level components in the views directory
  • Put public components in commen (such as: head (common header component), foot (common bottom component), etc.)
  • Functional components are placed in the feature directory (such as: swiper (carousel functional component), tabbar (switching functional component), list (pull up to load more functional components))

Components can improve the development efficiency of the entire project. It can abstract the page into multiple relatively independent modules, which solves the problems of our traditional project development: low efficiency, difficult maintenance, and low reusability.

Benefits of using components

  • Components are reusable
  • easy to maintain
  • Encapsulated and easy to use
  • Reduce duplication between components in large projects
     

Application Scenario

Many modules in the project are often reused: side navigation components, paging, file downloads, encapsulation of echarts charts commonly used in projects (such as line charts, histograms, etc.), or many reusable components in some background management and menu management , forms and the like.


Packaging components need to consider reusability:

  • Reserved slot slot, multiple calls If the sub-component view structure is different, then it is necessary to reserve a slot in the sub-component template (single slot, named slot, scope slot)
  • Considering data transfer, define the props component to receive the data passed by the parent component, and pay attention to the one-way data flow, props cannot be modified directly, $emit custom event, parent component modification
  • Business logic should not be processed in subcomponents. When subcomponents are called in different parent components, the business processing codes are different. Remember not to directly process business in subcomponents. Subcomponents should $emit custom events and pass data to parent components. The parent component handles the business.

Vue encapsulates components by itself (local, global) 

Closure: When the component is defined, it cannot be modified outside;

Openness: transfer dynamic content and component communication methods to ensure component scalability;

Three elements of Vue components

1. props parameter
2. slot custom slot
3. event custom event

①Global components

1) Method:

It can be registered as a global component in main.js.

import Bread from '@/layout/bread';// 引入
Vue.component("Bread",Bread);// 全局注册

 2) Example:

Reference the global component my-header

<body>
  <div id="main1">
    <!-- 正常模板解析的时候,不会将自定义标签解读出来,而是将自己定义组件里的参数解读出来,也就是下面template中的h1标签 -->
    <my-header></my-header>
  </div>
   <div id="main2">
     <!-- 自定义组件具有复用性 -->
    <my-header></my-header>
  </div>
   <div id="main3">
    <my-header></my-header>
  </div>
</body> 

Register global componentsmy-header

//全局组件:在任何地方,任何方式,任何地点都可以使用的标签组件
vue.component("my-header", {
    	// h1标签是我们在自定义主键里面写的参数的标签
    	template: '<h1>标题{
   
   {msg}}</h1>',
    	data(){
    	   return {msg:100}
    	}
    })
	new Vue({
	  	el: '#main'
	  });
	  new Vue({
	  	el: '#main2'
	  });
	  new Vue({
	  	el: '#main3'
	  });

②Partial components

1) Method:

  • Create a new vue file
  • Introduce in the components that need to be used: import UploadIDCard from “./fillInfo/upIDCard”;
  • register
components: {
    Position: () => import("@/layout/position"),
    UploadIDCard
},

After registration, UploadIDCard can be used as a label. (local components).

2) Example:

Partial components: only within the scope of our regulations will take effect.

 <body>
    <div id="main">
      <my-header></my-header>
      <my-header></my-header>
    </div>
  </body>
  new Vue({
    	el: '#main',
    	components: {
    		"my-header": {
    		template: '<h1>标题{
   
   {vue}}</h1>'
    		}
    	}
    })

Naming convention: ( note )

  • When defining a component using kebab-case (named with a dash), you must also use kebab-case when referencing this custom element, such as <my-component-name>
  • When defining a component using PascalCase (CamelCase), you can use both naming conventions when referring to the custom element. That is, both <my-component-name> and <MyComponentName> are acceptable. Note , however, that only kebab-case is valid when used directly in the DOM (ie non-string templates).
  • Summary: The dash name must be consistent when used, and the camel case can be used with both hump and dash.
//中划线 使用语法: <my-component-name>`
Vue.component('my-component-name', { /* ... */ })
//驼峰  使用语法:<my-component-name> `和` <MyComponentName>`都可以
Vue.component('MyComponentName', { /* ... */ })

Scaffolding components in vue-cli

Data transfer between components
We generally develop projects through scaffolding vue-cli, and each .vue single file is a component. Use import in the parent component to import a child component and register the child component in components. The child component needs data and can accept definitions in props. After the child component modifies the data, it wants to pass the data to the parent component. You can use the $emit method to trigger custom events to pass parameters.


Father to son (props)

The definition of prop should be as detailed as possible, at least its type needs to be specified

Parent components pass data to child components in the form of attributes, and child components receive data using props. However, the application scenarios of common components are more complicated. Some validation rules should be added to the parameters passed by props, namely:

props: {
    propA: Number,  // 基础类型检测 (`null` 意思是任何类型都可以)
    propB: [String, Number],   // 多种类型
    propC: {  // 必传且是字符串
      type: String,
      required: true
    },
    propD: {   // 数字,有默认值
      type: Number,
      default: 100
    },
    propE: {   // 数组/对象的默认值应当由一个工厂函数返回
      type: Object,
      default: function () {
        return { message: 'hello' }
      }
    },
    propF: {   // 自定义验证函数
      validator: function (value) {
        return value > 10
      }
    }
  }

Due to the problem of a single-item data flow, the data passed from the parent component to the child component should not be modified directly, because the data in the parent component will also be modified, and problems will arise when this data is also passed to other components. Vue2.5 has been optimized for props, and this problem no longer exists. If you must have such an operation, you can write it like this:

let copyData = JSON.parse(JSON.stringify(this.data))

Why not just write let myData = this.data? Because of direct assignment, it is only a shallow copy for objects and arrays, pointing to the same memory address, and changing one of them will also change the other. However, after the reverse conversion of JSON, the deep copy is realized, which can not affect each other.

<!-- 父组件 -->
<template>
    <div>
        <my-child :parentMessage="parentMessage"></my-child>
    </div>
</template>

<script>
    import MyChild from '@components/common/MyChild'

    export default {
        components: {
            MyChild
        },
        data() {
            return {
                parentMessage: "我是来自父组件的消息"
            }
        }
    }
</script>
<!-- 子组件 -->
<template>
    <div>
        <span>{
   
   { parentMessage }}</span>
    </div>
</template>

<script>
    export default {
        props: {
            parentMessage: {
                type: String,
                default: '默认显示的信息'
                // require: true // 必填
            }
        }
    }
</script>

Pass the parent component method through $on

Passing the parent component method through $on is a common method passing method in component communication. It can achieve the same effect as passing methods through props. Compared with props passing function, it is more intuitive and shows the calling relationship

<!-- 父组件 -->
<template>
    <div>
        <my-child @childEvent="parentMethod"></my-child>
    </div>
</template>

<script>
    import MyChild from '@components/common/MyChild'

    export default {
        components: {
            MyChild,
        },
        data() {
            return {
                parentMessage: '我是来自父组件的消息',
            }
        },
        methods: {
            parentMethod() {
                alert(this.parentMessage)
            }
        }
    }
</script>
<!-- 子组件 -->
<template>
    <div>
        <h3>子组件</h3>
    </div>
</template>

<script>
    export default{
        mounted() {
            this.$emit('childEvent')
        }
    }
</script>

$parentGet the parent component and use the data in the parent component (not recommended)

To be precise, this method does not belong to the transmission of data but an active search . The parent component does not actively pass data to the child component, but the child component obtains the data of the parent component through the relationship with the parent component.
Although this method can obtain the data in the parent component, this method is not recommended, because Vue advocates one-way data flow, and only the data that the parent component hands over to the child component has the permission to use it, and the child component is not allowed to obtain the parent without permission. Component data is used. In the relationship between father and son, the son should be in a passive relationship

By $emitpassing parent component data (recommended) 

Pass data from child component to parent component

The child component passes data to the parent component: trigger the parent component method, and pass the parameter data to the parent component

Used in conjunction with parent component to child component communication $on, parameters can be passed to the method triggered in the parent component for use by the parent component

<!-- 父组件 -->
<template>
    <div>
        <my-child @childEvent="parentMethod"></my-child>
    </div>
</template>

<script>
    import MyChild from '@components/common/MyChild'

    export default {
        components: {
            MyChild
        },
        data() {
            return {
                parentMessage: '我是来自父组件的消息'
            }
        },
        methods: {
            parentMethod({ name, age }) {
                console.log(this.parentMessage, name, age)
            }
        }
    }
</script>
<!-- 子组件 -->
<template>
    <div>
        <h3>子组件</h3>
    </div>
</template>

<script>
    export default {
        mounted() {
            this.$emit('childEvent', { name: 'zhangsan', age:  10 })
        }
    }
</script>

refsObtain

You can add the ref attribute to the subcomponent, and then you can get the instance of the subcomponent through the ref attribute name. To be precise, this method, like this.$parent,
is not a data transfer but an active search .

Try to avoid using this method. Because in the process of parent-child component communication. The parent component is in a high position and has control, while the child component should be a pure view component in most cases, and is only responsible for the display of the view and the logical operation of its own view. The right to interact externally should be controlled by the parent component. Therefore, the parent component should pass the view data to the child component, and the child component is responsible for displaying. The external interaction of the child component triggers the corresponding method in the parent component through $emit, and then the parent component processes the corresponding logic.

<!-- 父组件 -->
<template>
    <div>
        <my-child ref="child"></my-child>
    </div>
</template>

<script>
    import MyChild from '@components/common/MyChild'

    export default {
        components: {
            MyChild
        },
        mounted() {
            console.log(this.$refs['child'].getData());
        }
    }
</script>
<!-- 子组件 -->
<script>
    export default {
        methods: {
            getData() {
                // do something...
            }
        }
    }
</script>

Component style modification 样式穿透 

Some preprocessors like 
syntax in sass cannot parse correctly . In this case you can use  the operator instead - which is an alias for the same functionsass>>>/deep/>>>

<style scoped>
    .a /deep/ .b { /* ... */ }
</style>

Plugin use: slot

A general-purpose component is often not suitable for all application scenarios, so only 80% of the function of the component needs to be completed when encapsulating the component, and the remaining 20% ​​is solved by the parent component through solt. Solt acts as a placeholder, reserve a position for the button setting in advance, and then write the button in the parent component.

When developing common components, as long as they are not highly independent components, it is best to add a slot. Moreover, during the development process, it is often necessary to add new content in the subcomponent. At this time, one or more sockets can be left inside the subcomponent, and then add content when calling this subcomponent, and the added content will be distributed to the corresponding In the slot:

父组件
<head-component>
	<h2>不具名插槽</h2>
	<h2 slot="s1">这里对应的是s1插口</h2>
	<h2 slot="s2">这里对应的是s2插口</h2>
</head-component>
子组件
<template>
  <div class="headComponent">
    <h3>这是一个头部组件</h3>
    <slot></slot>
    <slot name="s1"></slot>
    <slot name="s2"></slot>
  </div>
</template>

The slot can also be used as a scope to define variables in the child component, and then customize the rendering method in the parent component: (it is used more in the project, the data obtained by ajax in vue+elementUI is displayed in the table, and many times every A piece of data is not displayed directly, some additional processing is required)

子组件
<template>
  <div class="headComponent">
    <h3>这是一个头部组件</h3>
    <slot name="head" v-for="head in heads" :text="head.text"></slot>
  </div>
</template>
父组件
<head-component>
	<template slot="head" scope="props">
		<li> {
   
   { props.text }} </li>
	</template>
</head-component>

Reference link: Vue component development_star@星空的博客-CSDN Blog

Encapsulation of Vue public components_Milly_Liu's Blog-CSDN Blog_Encapsulation of Vue public components

Vue component development_star@星空的博客-CSDN Blog

おすすめ

転載: blog.csdn.net/coinisi_li/article/details/128969548