"Go" "Html" Vuejs2.0 Learning II (Render function, CREATEELEMENT,VM. $slots, functional components, template compilation, JSX)

Source: Internet
Author: User
Tags event listener tag name

1. Render function
So came directly to render, would have wanted to skip, found that the back of the route seems to have a little connection with it. Let's take a look at render
1.1 Official website at the beginning of a very ignorant, do not know what to talk about, try a bit, a start is the use of render, the official website of the chestnut is always a feature, TM is not affixed to the complete, I here is a relatively full version: (in order to see the clear point, replace the next name)

<div id= "Div1" ><child:level= "2" >hello world!</child></div><script type= "text/ X-template "id=" template > <div> 

if= "level = = = 1" > <slot></slot> if= "level = = = 2" > <slot></slot> if= "Level = = = 3" > <slot></slot> if= "level = = = 4" > <slot></slot> if= "level = = = 5" > <slot></slot> if= "level = = = 6" > <slot></slot> Vue.component (' Child ', {Template:' #template ', props: {level: {type:number, Required:true } }}) NewVue ({el:"#div1"})</script>

Review the previous study, here registered a global component called child, whose template is Id=template template, looking up, this writing is not the same as before, Ah, used to be the <template> label, the little friends still have the impression? The API is checked for this, which means that this is the new version. The template has made a decision, according to the level of the value of the head to select the size of H1-h6, while using the slot to distribute content (do not remember the children's shoes can look at my previous article). Where is level? Looking back at the components of the props, this thing also has the impression that the parent component passes the parameter to the child component can use it, also does the props authentication, the level must be the number type, this front we also chatted.

Finally instantiate Vue, using Vue in the ID=DIV1 block, so that DIV1 can use the child template:

<div id= "Div1" ><child:level= "2" >hello world!</child></div>

At this point, the parent component Div1 can use the child template children, while the parent template can use the Level property, the Bind method can pass the value 2, do not: The consequence of the bind is to pass the string "2", this also chatted. Hello world as the content of the slot distribution. So the end of the whole content will be obviously rendered as: ... Do not write, own research.

Suddenly found our case more and more complex, fortunately, before the preparation. But it doesn't seem like a half-penny relationship with Render, it doesn't really matter--! The official lifting of this chestnut is to show that this writing is wasteful, the reason for the waste is, although the last only H2, but the other h1,h3-h5 are actually rendered, but not shown. Render is referenced for optimization purposes.

1.2 Overwrite the above code with render mode

//HTML<div id= "Div1" ><child:level= "3" >hello world!</child></div>//Script<script type= "Text/javascript" >Vue.component (' Child ', {render:function(createelement) {returncreateelement (' H ' + This. Level,//tag name tag names       This. $slots.default //Arrays in sub-assemblies)}, props: {level: {type:number, Required:true    }  }})    NewVue ({el:"#div1"})</script>

No more? Yes, it's gone. Don't believe you try, the effect is the same, bound 1 words rendered out H1, bound 2 rendering H2. I go, very 6 ah, the template will not be done. How do you do that? See CreateElement is a what East first, so began to createelement. So, we found that the logic of this official website is non-mainstream ah, inadvertently I found to understand his logic must be to me to try to look at the side of the line, wow ka ka. But as the name implies, CreateElement looks like the process of dynamically creating DOM nodes (also called Vnode in the node Vue), looking at the content, ' H ' + This.level creates a label h1-h6 based on level, so it only renders a label, not all of it, so it's optimized, and the code saves a lot of it.

1.3 createelement A little impression, JS added DOM node can use it, document.createelement (tag). Here createelement (tag,{},[]) or createelement (tag,{},string) similar, but received different parameters, the following two parameters are optional

//@returns {Vnode}createelement (//{String | Object | Function}  //an HTML tag, a component setting, or a function  //must Return one of the above' Div ',  //{Object}  //a data object that corresponds to a property  //you can use the. Optional option in the template .  {    //(the details will be explained in the next chapter)  },  //{String | Array}  //child node (vnodes). Optional.[CreateElement (' H1 ', ' Hello World '), createelement (MyComponent, {props: {someprop:' Foo '      }    }),    ' Bar '  ])

Where the tag parameter is similar, the second parameter {} is actually a data object, representing the attributes used in that node, such as the common Class,style,props,on, the complete data object is as follows:

{  //the same API as ' V-bind:class '' Class ': {foo:true, bar:false  },  //the same API as ' V-bind:style 'style: {color:' Red ', FontSize:' 14px '  },  //Normal HTML featuresattrs: {ID:' Foo '  },  //Component Propsprops: {myprop:' Bar '  },  //DOM Propertiesdomprops: {innerHTML:' Baz '  },  //the event listener is based on the "on"  //so no longer supports such as V-on:keyup.enter modifiers  //you need to manually match the KeyCode. On : {click: This. ClickHandler},//For components only, listen for native events, not components using VMS. $emit triggered events. Nativeon: {click: This. Nativeclickhandler},//custom directives. Caveats: You cannot set values for old values of bindings  //Vue will keep chasing away for you .directives: [{name:' My-custom-directive ', Value:' 2 'expression:' 1 + 1 ', ARG:' Foo ', modifiers: {bar:true      }    }  ],  //If the subassembly has a name that defines the slotSlot: ' Name-of-slot '//other special top-level propertiesKey: ' MyKey ', ref:' Myref '}

The third parameter [] can be seen to indicate that there are other nodes under the node, which is placed here [createelement (TAG1), createelement (TAG2)]. OK, looking back at 1.2 rewrite the Render method, equivalent to using the form of createelement (tag,[]), wherein tag= ' h ' +this.level, []= this.$slots.default . The first parameter is good to understand, the second parameter this.$slots.default is what ghost, do not know when to go to check api,slots It is obviously the slots that are used for distribution, find the slot in the API. This is what the authorities describe:

Used to access content that is distributed by the slot. Each named slot has its corresponding properties (for example: Content in slot= "foo" will be found in the VM. $slots. foo). the default  property includes all nodes that are not contained in a named slot. When writing a component using the Render function, access the VM. $slots most helpful. 

So the goods actually represent the anonymous slot content, that is [vnode1,vnode2 ...] Array, here is only one vnode is the child wrapped in the Hello world! so 1.2 in the final rendering of the result is actually a node like this.

1.4 After the original text gave a complete example does not describe, the difference is that when creating a tag using the (tag,{},[]) structure

CreateElement (' A ', {          attrs: {            name:headingid,            ' # ' + headingid          }        this . $slots. default)
 var  getchildrentextcontent = function   (children) { return  children.map ( Span style= "COLOR: #0000ff" >function   (node) { return   Node.children ?  Getchildrentextcontent (Node.children): Node.text}). Join ( '  var  headingid = Getchildrentextcontent (this . $slots.  Default  /\w+/g, '-' 

Getchildrentextcontent this function, because this.$slots.default it is the number of groups [vnode1,vnode2 ...], so you can do map processing (the impression is the SE6 method), each element in the array is unified processing: recursion, Layer by layer to see if the Vnode has child nodes, and a child node calls itself until it has no child nodes and then takes out his textual content. Finally, the text of each layer is concatenated with a space character using the array join method.
Like what

<div id= "Div1" >    <child:level= "1" >        Helloworld!                    woqu            

this.$slots.defaultThe value is [Vnode1,vnode2,vnode3], where

VNode1 = Hello world!  = 

VNode1 No child, directly returned to Hello World!,vnode2 have child is H2, so recursive once H2 inside No child, returned WOQU,VNODE3 situation similar, finally returned what. So the result of the map is to get an array [' Hello world! ', ' woqu ', ' What '], and then call the Join method to string up and get ' Hello world! Woqu what ';
Back again. toLowerCase () Turns lowercase to ' Hello world! ' Woqu what ';

Then the replace(/\W+/g, ‘-‘) regular replacement, the regular for the It should not be unfamiliar, JS in the regular format is such,/regular expression/matching mode, matching mode is of course optional, \w represents non-word character (0-9,a-z,a-z,_), + denotes one or more,/ G indicates the use of global matching mode, the global characteristics of each match, the next match subscript is the next bit, so this replacement will be a continuous non-word characters replaced with-, into ' hello-world-woqu-what ';

Re-use replace(/(^\-|\-$)/g, ‘‘) to do a regular replacement, ^\- representing the beginning of the match-the character, the \-$ match end of the-character, | Or, this sentence means if the string starts or ends with--, they are replaced with ", that is, directly deleted, So there is no change in ' hello-world-woqu-what '.

In summary, var headingid = ' Hello-world-woqu-what '.

1.5 vnodes must be unique. The saying is not very clear, in fact, the same vnode can only be used in one place.
Like what

function (createelement) {  var myparagraphvnode = createelement (' P ', ' Hi ')  return createelement (' div ', [    ///  yikes-duplicate vnodes!     Myparagraphvnode, Myparagraphvnode  ])}

The myparagraphvnode here, is used in the ' div ' of the two Vnode, this usage is not, you want to use can only create two identical Vnode objects, instead of pointing to the same Vnode object.

1.6 Render's functional component
That's probably what this means, look at the structure of the 1.5 render,
Render:function (createelement) {} This structure can create vnode, but cannot access external data, what if the vnode you want to create depends on external data? That's what this section is about.

You can access external data by overwriting it in the following ways:

 vue.component (' my-component '  true , // 1  //  //  provides a second argument as context  render: function  (createelement, context) {// 2  Span style= "COLOR: #008000" >//  ...  },})  

With 1 and 22 overrides, the context is used to access the external data, which is equivalent to the context of a component that can access some of the data for that component:
Props: Object that provides props
Children:vnode an array of child nodes
Slots:slots Object
Data: The data object passed to the component
Parent: A reference to the parents component

For example: this. $slots. The default update is Context.children, and then This.level is updated to Context.props.level.
That's almost what it means.

1.7 Template Compilation Process
Here are some examples of how the Vue template Vue.compile in the life cycle compilation phase.
such as templates:

<div>  m a template!

At compile time will be similar to the following processing

You can see the div was created, similar to createelement, passed the vnodes array to him, _m (0) is the first node Vnode after the argument is a choice operator a? B:C, if the message is true, a P node is created, and if False, a P node is created, only good two P-node content is different

Alternatively, you can alias the createelement, which is usually denoted by H

1.7 JSX
This thing as my front-end small white, was not heard before. Check it out, JSX syntax, like writing XML syntax directly in JavaScript code, each XML tag is converted into pure JavaScript code by the JSX conversion tool. Look at the following example:

// you might want to write this without using JSX. function (h) { h ( ' div ', [ H (' span ', ' Hello '), ' world! ')  ]}// using JSX can be written directly like a tag language such as XML or HTML, and is not much more intuitive render (H ) { return ( <div> <span>Hello</span> world! </div> ) };

Using JSX in Vue requires this plugin: Babel plugin. Https://github.com/vuejs/babel-plugin-transform-vue-jsx

Original address: 52910389

"Go" "Html" Vuejs2.0 Learning II (Render function, CREATEELEMENT,VM. $slots, functional components, template compilation, JSX)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.