Components are used to encapsulate some functions of a page, and encapsulate the structure, style, and logical code of a function as a whole.
Improved functionality reusability and maintainability, and better focus on business logic.
The component is used as a custom HTML tag. The component name is used as the custom tag name.
The component registration
Global registration
Globally registered components can be used after registrationAny instance or componentIn the.
Note: Global registration must be set before the root Vue instance is created.
<body>
<div id="app">
<p>This is the P tag</p>
<my-component></my-component>
</div>
<script src="lib/vue.js"></script>
<script>
Vue.component('my-component', {
template: This is our globally registered component
});
/ / root instance
new Vue({
el: '#app'.data: {}})</script>
</body>
Copy the code
Component based
Components are essentially reusable Vue instances, so they can receive the same options as new Vue, such as Data, methods, and lifecycle hooks.
Note that the only exceptions are root instance-specific options like EL. There is no EL because the root instance needs to be mounted to an element on the page, while the component is used by the root instance or by other components and does not need to be mounted to the page.
Component naming rules
Components have two naming conventions:
- Kebab – case:
'my-component'
- PascalCase:
'MyComponent'
Note: No matter which naming is used, only kebab-case is available in the DOM.
<body>
<div id="app">
<my-com-a></my-com-a>
<! </MyComA> </MyComA>
<my-com-b></my-com-b>
<! -- <MyComB></MyComB>
</div>
<script src="lib/vue.js"></script>
<script>
// kebab-case to register
Vue.component('my-com-a', {template:
A component content
})
// PascalCase to register
Vue.component('MyComB', {
template: '
Contents of b component
'
});
new Vue({
el: '#app'.data: {}})</script>
</body>
Copy the code
The template options
The template option is used to set the structure of the component, which is eventually introduced into the root instance or other components.
Note: The component must have only one root element. That is, no other element can be set at the level of
<body>
<div id="app">
<my-com-a></my-com-a>
</div>
<script src="lib/vue.js"></script>
<script></script>
</body>
Copy the code
The data options
The data option is used to store the component’s data. Unlike the root instance, the component’s data option must be a function, and the data is set in the return value object.
This is implemented to ensure that each component instance can maintain a separate copy of the returned object without affecting each other. Because the scope of a function is only valid inside it.
ES6 abbreviations:
<body>
<div id="app">
<my-com-a></my-com-a>
</div>
<script src="lib/vue.js"></script>
<script></script>
</body>
Copy the code
Local registration
Locally registered components can only be used in the current instance or component. There are two ways to register:
1. Directly add it to the Vue instance
<body>
<div id="app">
<my-com-a></my-com-a>
<my-com-b></my-com-b>
</div>
<div id="app2">
<my-com-a></my-com-a>
<my-com-b></my-com-b>
</div>
<script src="lib/vue.js"></script>
<script></script>
</body>
Copy the code
2. Configure the option object of the component separately
Easier to maintain
ES6 short: (Less compatible than the above method)
<body>
<div id="app">
<my-component-a></my-component-a>
<my-component-b></my-component-b>
</div>
<script src="lib/vue.js"></script>
<script></script>
</body>
Copy the code
Component communication
The operation of passing data between components is called component communication. The delivery mode varies depending on the participating components.
Parent component passes value to child component
Receives a value from the parent component via the props option of the child component. Once accepted, you can use it directly in the template.
Pay attention to:props
Don’t withdata
There is an attribute with the same name, otherwise there will be an overwrite problem.
The parent component is set as follows:
-
A title without a colon is passed statically and cannot be changed.
-
The colon title is passed dynamically, and the text is quoted
<body>
<div id="app">
<my-component-a title="This is a static title." content="This is static content."></my-component-a>
<! -- Bind dynamic content, common -->
<my-component-a :title="item.title" :contnet="item.content"></my-component-a>
</div>
<script src="lib/vue.js"></script>
<script></script>
</body>
Copy the code
Props naming rule
CamelCase is recommended for prop naming and kebab-case for parent component binding
<body>
<div id="app">
<! Create a component and generate content by iterating through data items with v-for -->
<demo-item v-for="item in items" :key="item.title"
:item-title="item.title" :item-content="item.content"></demo-item>
</div>
<script src="lib/vue.js"></script>
<script>
Vue.component("demoItem", {props: ["itemTitle"."itemContent"].template: `
{{ itemTitle }}
{{ itemContent }}
`
})
new Vue({
el: '#app'.data: {
// Prepare data for use by child components
items: [{title: 'Example Title 1'.content: 'Sample Content 1'
},
{
title: 'Example Title 2'.content: 'Sample Content 2'
},
{
title: 'Example Heading 3'.content: 'Sample Content 3'},]}})</script>
</body>
Copy the code
Unidirectional data flow
All prop bindings between parent and child components are one-way downlink. Data changes in the parent component affect the child component, but data changes in the child component do not affect the parent.
If prop data is to be processed by a child component, it should be stored in data (or operated using computed properties).
Note: If prop is an array or object, child component operations will affect the state of the parent component. Because it’s a reference, it gets the address.
Solutions:
- Store data in data before performing operations
- Instead of passing an entire array or object, pass only the value of an attribute of the object.
<body>
<div id="app">
<my-component
:initial-title="title"
:obj="obj"
></my-component>
</div>
<script src="lib/vue.js"></script>
<script>
Vue.component('my-component', {
props: ['initialTitle'.'obj'].template: ` < div > {{title}} < button @ click = "fn" > button < / button > < / div > `,
data () {
return {
title: this.initialTitle
// title: this.initialTitle = "This is the new title"}},methods: {
fn () {
// this.title = 'This is the new title ';
// this.initialTitle = 'This is the new title '; // Does not affect the parent component
this.obj.name = 'jack'; // Causes the root name to change to Jack as well}}});new Vue({
el: '#app'.data: {
title: 'Here's the sample title'.obj: {
name: 'william'.age: 18}}});</script>
</body>
Copy the code
Props type
Prop can set type checking, in which case you need to change props to an object with validation requirements and specify the corresponding type.
-
The corresponding constructor on the later Settings will do the trick. String and Array are constructors.
-
If the type is not limited, it can be null or undefined
Prop can also specify multiple types at the same time and can be stored as an array.
<body>
<div id="app">
<my-component
:par-str="str"
:par-num="num"
:par-arr="arr"
:par-obj="obj"
:par-any="any"
:par-data="str"
></my-component>
</div>
<script src="lib/vue.js"></script>
<script></script>
</body>
Copy the code
Props to verify
When multiple rules need to be set on prop, you can set the value of prop as an option object.
- The previous type detection function passed
type
Option Settings.
Other options:
-
Required Sets the data to mandatory. (eg. required: true)
-
Default specifies the default value for the option, which takes effect when no data is passed by the parent component. (eg.default: 100)
-
Required and default cannot work on a prop at the same time, because required requires values to be passed.
Note: When the default value is an array or object, it must be in the form returned by the factory function.
Or:
validator
Used to set the verification function to the prop passed in. Return isfalse
Vue. Js will issue a warning.Specific content rulesDetection.
Note: Data, methods and other functions of the instance cannot be used in the validation function. Props does validation before the instance is created, so it can’t use data, methods or anything like that. This refers to the Window, not the Vue instance.
The Props attribute
When a parent component sets an attribute to a child component, but the attribute is not received in props, it is automatically bound to the root element of the child component. Custom directives are also bound to the root element.
For example, if the parent element is bound to these values:
If these values are not accepted inside the child elements, they are bound to<div>
On.
A special case
-
If the component root element already has an attribute, the new attribute replaces the original value.
-
The exception is class and style, where properties are automatically merged when both inside and outside are set.
-
If you don’t want to inherit properties set by the parent component, you can set inheritAttrs: False, but only for ordinary properties, leaving class and style unaffected.
Case 1
<div id="app">
<my-component
data-index="3"
:title="' New heading content '"
style="height: 200px;"
class="colorRed"
></my-component>
</div>
Vue.component('MyComponent', {
template: `
<div data-index="Seven"
title="The title of the old"
class="abc"
style="width: 200px;">
<p>This is the content of the component</p>
</div>`});Copy the code
Case 2
<div id="app">
<my-component
data-index="3"
:title="' New heading content '"
style="height: 200px;"
class="colorRed"
></my-component>
</div>
Vue.component('MyComponent', {
inheritAttrs: false,
template: `
<div data-index="Seven"
title="The title of the old"
class="abc"
style="width: 200px;">
<p>This is the content of the component</p>
</div>`});Copy the code
Child components pass values to parent components
The child passes the value to the parent through a custom event. When a child component makes a data change, it raises an event that the parent listens for.
For example, the item is a child component, and the shopping cart is the parent component. The parent component needs to count the number of goods, so it needs to transfer the value to the parent component when the number of child components changes.
A custom event is emitted via $emit() when the child component data changes. $emit() is a method on an instance of vue that can be passed a name internally to fire a custom event for that name. No manual trigger is required.
- You are advised to use kebab-case to customize the event name. I’ll write it in the parent element
@count-change
The parent listens for the child’s custom events and sets up handlers.
- The parent component listens
count-change
When the event is triggered, thetotalCount
Since the 1
Custom event pass values
It would be inconvenient to just tell the parent component that the event was triggered each time. Such as +5 each time, so you can pass values to the parent component.
A child component can pass a value to its parent when it fires an event.
$emit()
The first argument is the name of the event to fire, and the second argument is the value passed (object, variable, etc.).
Method 1: Directly set the code for custom events
The parent component needs to receive the data passed by the child component when it listens for events.
Method two: by processing functions
- Here,
productCount
is$emit()
The value passed.
Components and v – model
When a V-model is used for a component, it needs to be implemented through props and custom events. Because components are independent of each other.
v-model
There are built-in functions for incoming and receiving data, so there is no need to write:value="..."
, so the child component only needs to useprops
Just receive it.
-
Value is the value of the V-Model binding
-
$emit() can emit custom events as well as built-in events by making the input field emit $emit() events at @input (input event is monitored in real time and is called every time input is entered)
-
$event is the event object, target is the current input field, and value is the input data.
Method one:
<body>
<div id="app">
<p>The input box contains the following contents: {{iptValue}}</p>
<com-input v-model="iptValue"></com-input>
</div>
<script src="lib/vue.js"></script>
<script>
var comInput = {
props: ["value"].template: ` `
}
/ / root instance
new Vue({
el: '#app'.data: {
iptValue: ' '
},
components: {
comInput
}
});
</script>
</body>
Copy the code
Method 2:
<body>
<div id="app">
<p>The input box contains the following contents: {{iptValue}}</p>
<com-input v-model="iptValue"></com-input>
</div>
<script src="lib/vue.js"></script>
<script>
var comInput = {
props: ["value"].template: ` `.methods: {
onInpt(event){
this.$emit('input', $event.target.value)
}
}
}
/ / root instance
new Vue({
el: '#app'.data: {
iptValue: ' '
},
components: {
comInput
}
});
</script>
</body>
Copy the code
Non-parent components pass values
A non-parent component is a sibling component or two components that are completely unrelated.
Sibling components pass values
Sibling components can transfer data through parent components.
<body>
<div id="app">
<! -- Parent receives data from child A -->
<com-a
@value-change="value = $event"
></com-a>
<! Parent component passes data to child component B -->
<com-b
:value="value"
></com-b>
</div>
<script src="lib/vue.js"></script>
<script>
// Subcomponent A: sends data
Vue.component('ComA', {
template: {{value}} < button@click ="$emit('value-change', value)" > send ,
data () {
return {
value: 'This is the data in component A'}}});// Subcomponent B: receives data
Vue.component('ComB', {
props: ['value'].template: '
Component B receives: {{value}}
'
});
// Root instance (parent component)
new Vue({
el: '#app'.data: {
// For data transfer
value: ' '}})</script>
</body>
Copy the code
EventBus (Any component passes values)
The EventBus is an independent event center that manages the transfer of values between different components. It is only responsible for transferring values, and does not store data itself.
EventBus manages component-passing operations through a new Vue instance, where components register and invoke events to pass data to the instance. It is usually stored in a separate file.
Advantages:
- There is not a lot of data in data that is irrelevant to the functionality of the current component.
- There is no need to find relationships between components.
Practice:
The component that sends data triggers a BUS event, and the component that receives data registers the corresponding event with the BUS.
- The component that sends data fires a BUS event
- I used to clean it up
this.$emit()
, referring to the VUE instance of the current component. Used herebus.$emit()
Is to use thebus
Vue instance of the component, andbus
Can be accessed by any component.
- The received event passes the bus registration corresponding event
$on()
Operation.
-
Created () is a lifecycle function, and because totalCount is used, it is processed after the instance is created.
-
Parameter 1: indicates the event name
-
Parameter two: event handler. The this in the arrow function refers to the current product-total component. Since the arrow function doesn’t modify this, because it doesn’t have this itself, the this it uses is the this inside the current environment (creat()), which is the instance of the current function. If you use a normal function here, you need to make a store externally.
<body>
<div id="app">
<h3>The shopping cart</h3>
<product-item v-for="product in products" :key="product.id" :title="product.title"></product-item>
<product-total></product-total>
</div>
<script src="lib/vue.js"></script>
<script src="EventBus.js"></script>
<script>
Vue.component("productItem", {props: ['title'].template: ` < div > < span > name of commodity: {{title}}, commodity number: {{count}} < / span > < button @ click = "onChange" > + 1 < / button > < / div > `.data: function(){
return {
count: 0}},methods: {
onChange(){
// Trigger custom events for bus to pass data
bus.$emit("countChange".1);
this.count++;
}
}
})
Vue.component("productTotal", {template:{{totalCount}} '.data: function(){
return {
totalCount: 0}},created(){
// Register events with bus and receive data
bus.$on("countChange".(productCount) = > {
this.totalCount += productCount; })}})var bus = new Vue();
/ / root instance
new Vue({
el: '#app'.data: {
products: [{id: 1.title:The word "apple"
},
{
id:2.title:"Banana"
},
{
id: 3.title:"Orange"}}}]);</script>
</body>
Copy the code
Other value transmission methods
It is not recommended if there are no special requirements. It’s harder to fix mistakes when they go wrong.
$root
$root is used to access the current component root instance, which can be used to pass component values when setting up simple Vue applications.
In addition to $root, vue. js provides $parent and $children for easy access to parent and child components.
- Both A and B components access the vUE root instance directly
count
.
<body>
<div id="app">
<com-a></com-a>
</div>
<script src="lib/vue.js"></script>
<script></script>
</body>
Copy the code
Click the A button to change count to 100; Click the B button and the count changes to 200.
$refs
$refs is used to get the HTML tag or subcomponent with the ref attribute set.
By setting the ref attribute to a normal HTML tag, $refs retrieves the DOM object.
- through
this.$refs.inp
Access to<input>
Tag, set itfocus()
You can make<input>
Automatically get focus.
Component slot
Subsequent complement
Built-in component
Subsequent complement