1 the introduction

Anchor point is a kind of hyperlink in the web page, also called named anchor. A named anchor, like a quick locator, is a kind of in-page hyperlink that is quite common. Its English name is Anchor.

Named anchors allow you to set tags in a document, usually at or at the top of a specific topic of the document. You can then create links to these named anchors that quickly take visitors to the specified location.

If this function is encapsulated as a component, it is typically written like this:

HTML:

<div id="app">
    <anchor :level="3" title="news"</ Anchor > <script >6 light years away 'super-earth' could support lifetype="text/x-template" id="anchor">
        <div>
            <h1 v-if="level===1">
                <a :href="'#'+title">
                    <slot></slot>
                </a>
            </h1>
            <h2 v-if="level===2">
                <a :href="'#'+title">
                    <slot></slot>
                </a>
            </h2>
            <h3 v-if="level===3">
                <a :href="'#'+title">
                    <slot></slot>
                </a>
            </h3>
            <h4 v-if="level===4">
                <a :href="'#'+title">
                    <slot></slot>
                </a>
            </h4>
            <h5 v-if="level===5">
                <a :href="'#'+title">
                    <slot></slot>
                </a>
            </h5>
            <h6 v-if="level===6">
                <a :href="'#'+title">
                    <slot></slot>
                </a>
            </h6>
        </div>
    </script>
</div>
<div style="margin-top: 1500px;">
</div>
<a id="news"> A giant super-Earth six light years away could harbor simple life, researchers have found. Barnard B (or GJ 699 B) is a recently discovered "super-Earth" planet orbiting Barnard's star, the second closest to Earth. Barnard B is thought to be extremely cold, with temperatures similar to Europa at about minus 150 degrees Celsius. </a>Copy the code

Js:

Vue.component('anchor', {
	template: '#anchor',
	props: {
		level: {
			type: Number,
			required: true
		},
		title: {
			type: String,
			default: ' '}}}); var app = new Vue({ el:'#app',
	data: {}
});
Copy the code

When you click on the anchor point “6 light years away” super-earth or life “, you will jump to the content specified on the current page. The thickness of the anchor point is determined by the level value.

The downside is that the template code for the component is verbose, with only a few differences and most of the rest identical.

We can use the Render function to construct

elements as concatenated strings.

HTML:

<div id="app2">
    <anchor2 :level="3" title="news"</anchor2> </div>Copy the code

Js:

Vue.component('anchor2', {
	props: {
		level: {
			type: Number,
			required: true
		},
		title: {
			type: String,
			default: ' '
		}
	},
	render: function (createElement) {
		return createElement(
			'h' + this.level,
			[
				createElement(
					'a',
					{
						domProps: {
							href: The '#' + this.title
						}
					},
					this.$slots.default
				)
			]
		)
	}
});


var app2 = new Vue({
	el: '#app2',
	data: {}
});
Copy the code

The effect is the same, but in this scenario, using the Render function simplifies the code significantly.

Above example DEMO

2 createElement

We use createElement to build the vue.js Virtual Dom template.

2.1 parameter

CreateElement takes three parameters:

parameter Whether the choice instructions
HTML tags, component options, or functions Will choose
The data object optional Used in template.
Child nodes optional The value can be String or Array.

In the example above, a comment should make it a little clearer:

returnCreateElement method (/ / HTML tags, components, options or Function (String | Object | Function)'h'+ this.level, // Data object (optional) {}, // child node, can be String or Array [createElement()'a',
			{
				domProps: {
					href: The '#' + this.title
				}
			},
			this.$slots.default
		)
	]
)
Copy the code

The data objects are structured like this:

// The data object corresponding to the attribute (optional) {// Corresponds to V-bind :class'class': {}, // corresponding to v-bind:style style: {}, //HTML attrs: {}, // component props: {}, //DOM attribute domProps: {}, // Custom on event listener, does not support decorator on: {}, // only for component, for listening on native event nativeOn: {}, // Custom directive directives: [], / / scope slot / / {name: props = > VNode | Array < VNode >} scopedSlots: {}, / / subcomponents of slot names (if the component is defined) slot:'xxx', // Other custom attributes XXX:'xxx'
}
Copy the code

Before template, we used v-bind:class directives in component tags, whereas in Render, these are defined in data objects.

While the Render function is flexible, it is bloated in some scenarios. Let’s take a look at an example. Suppose we need to define a simple DIV component that is bound to class and click.

HTML:

<div id="app">
    <e></e>
</div>
Copy the code

Js:

Vue.component('e', {
	template: '\ < div id = "e" \ "class =" {show: isShow} \ @ click "=" click "> after the fine lines on the windshield so use < / div > \',
	data: function () {
		return {
			isShow: true
		}
	},
	methods: {
		click: function () {
			console.log('click');
		}
	}
})

var app = new Vue({
	el: '#app',
	data: {}
});
Copy the code

CSS:

.show {
	cursor: pointer
}
Copy the code

If you use the Render function, the code looks like this:

Vue.component('e2',{
	render:function (createElement) {
		return createElement(
			'div',
			{
				class:{
					'show':this.isShow
				},
				attrs:{
					id:'e2'
				},
				on:{
					click:this.click
				}
			},
			'The thread on the rear windshield is so useful.')},... });Copy the code

So, in this scenario, it’s much cleaner to code using template.

2.2 limit

In the component tree, a VNode must be unique if it is a component or a slot containing a component.

Suppose we want to render two child components within a child node.

2.2.1 Error Example 1 — Reuse components

HTML:

<div id="app3">
    <e3></e3>
</div>
Copy the code

Js:

var Child3 = {
	render: function (createElement) {
		return createElement('p'.'Monster Hunter series Worldview Science'); }}; Vue.component('e3',{
	render: function(createElement) {var ChildNode= createElement(Child3);return createElement('div',[
			ChildNode,ChildNode
		])

	}
});

var app3 = new Vue({
	el: '#app3',
	data: {}
});
Copy the code

Render result:

<div><p> </div>Copy the code

Due to limitations, only one child is actually rendered!

2.2.2 Error Example 2 — Reuse component slot

HTML:

<div id="app4">
    <e4>
        <div>
            <Child4></Child4>
        </div>
    </e4>
</div>
Copy the code

Js:

// Vue.component('Child4', {
	render: function (createElement) {
		return createElement('p'.'High-end Business is necessary to solve users' pain points more professionally'); }}); Vue.component('e4', {
	render: function (createElement) {
		return createElement('div', [
			this.$slots.default,
			this.$slots.default
		])
	}
});
var app4 = new Vue({
	el: '#app4',
	data: {}
});

Copy the code

Render result:

<div> < P > High-end business this existence necessity interpretation: to solve user pain points more professional </p> </div>Copy the code

Due to limitations, only one child is actually rendered!

There are ways to render multiple components

2.2.3 Loops and factory functions

HTML:

<div id="app5">
    <e5></e5>
</div>
Copy the code

Js:

var Child5 = {
	render: function (createElement) {
		return createElement('p'.'How can smart technology help the real economy and mass entrepreneurship? '); }}; Vue.component('e5', {
	render: function (createElement) {
		return createElement('div', [
			Array.apply(null, {
				length: 3
			}).map(function () {
				returncreateElement(Child5); }}})])); var app5 = new Vue({ el:'#app5',
	data: {}
});

Copy the code

Here we set an array of length 3 using the Apply factory function and create child components for each item of the array using the map function.

Related knowledge:

  • Each function contains two non-inherited methods: apply() and call(), which are used to call the function in a particular scope, essentially setting the value of this in the function body. Apply () takes two arguments (the scope of the function to run, and an Array of arguments), which can be Array instances or arguments objects.
  • Map () is an iterative method that runs a given function on each item of the array and returns an array of the results of each function call.

Effect:

2.2.4 Deep copy Slot

HTML:

<div id="app6">
    <e6>
        <div>
            <Child6></Child6>
        </div>
    </e6>
</div>
Copy the code

Js:

Vue.component('Child6', {
	render: function (createElement) {
		return createElement('p'.'Four trends in online Education development'); }}); Vue.component('e6', {
	render: function(createElement) {// Copy the slot nodefunction// Const children = vnode.children &&vnode.children. Map () {// Const children = vnode.children &&vnode.children.function (vnode) {
				return copy(vnode);
			});
			const element = createElement(
				vnode.tag,
				vnode.data,
				children
			);
			element.text = vnode.text;
			element.isComment = vnode.isComment;
			element.componentOptions = vnode.componentOptions;
			element.elm = vnode.elm;
			element.context = vnode.context;
			element.ns = vnode.ns;
			element.isStatic = vnode.isStatic;
			element.key = vnode.key;
			return element;
		}

		const vNodes = this.$slots.default;
		const copyVNodes1 = vNodes.map(function (vnode) {
			return copy(vnode);
		});
		const copyVNodes2 = vNodes.map(function (vnode) {
			return copy(vnode);
		});

		return createElement('div', [
			vNodes, copyVNodes1, copyVNodes2
		])
	}
});
var app6 = new Vue({
	el: '#app6',
	data: {}
});
Copy the code

In the Render function, we create a factory function that copies slot nodes, recursively copies all of the slot’s children, and also copies the key attributes in the VNode. This approach is mainly applied to the development of standalone components.

Effect:

The above example