1. Nodes, trees, and virtual DOM<div> <h1>My title</h1> Some text content <!-- TODO: Add tagline --> </div> Each element is a node. Each paragraph of text is also a node. Even comments are nodes. A node is a section of a page. Just like a family tree, each node can have children (that is, each part can contain other parts). Updating all of these nodes efficiently can be difficult, but fortunately you don't have to do it manually. You just need to tell Vue what you want the HTML on the page to be, which can be in a template: <h1>{{ blogTitle }}</h1> Or in a render function: render: function (createElement) { return createElement('h1', this.blogTitle) } In both cases, Vue will automatically keep the page updated even if blogTitle changes. 2. Virtual DOMVue creates a virtual DOM to track how it changes the real DOM. Please look carefully at this line of code: return createElement('h1', this.blogTitle) What exactly does // @returns {VNode} createElement( // {String | Object | Function} // An HTML tag name, component options object, or // an async function that resolves to any of the above. Required field. 'div', // {Object} // A data object corresponding to the attribute in the template. Optional. { // (see next section for details) }, // {String | Array} // Child virtual nodes (VNodes), constructed by `createElement()`, // You can also use strings to generate "text virtual nodes". Optional. [ 'Write some text first', createElement('h1', 'A headline'), createElement(MyComponent, { props: { someProp: 'foobar' } }) ] ) 2.1 Diving into Data Objects In render functions, some template attributes will have top-level fields in the Vnode data object, which also allows binding to normal attributes, as well as { // Same API as `v-bind:class`, // Accepts a string, object, or an array of strings and objects 'class': { foo: true, bar: false }, // Same API as `v-bind:style`, // Accepts a string, object, or array of objects style: { color: 'red', fontSize: '14px' }, // Normal HTML attribute attrs: { id: 'foo' }, // Component prop props: { myProp: 'bar' }, // DOM properties domProps: { innerHTML: 'baz' }, // Event listener is inside `on`, // But modifiers like `v-on:keyup.enter` are no longer supported. // Need to manually check keyCode in the processing function. on: { click: this.clickHandler }, // Only used for components to listen to native events, not events triggered by // `vm.$emit` inside components. nativeOn: { click: this.nativeClickHandler }, // Custom directives. Note that you cannot use `oldValue` in `binding` // Assignment, because Vue has automatically synchronized it for you. directives: [ { name: 'my-custom-directive', value: '2', expression: '1 + 1', arg: 'foo', modifiers: bar: true } } ], // The format of a scoped slot is // { name: props => VNode | Array<VNode> } scopedSlots: { default: props => createElement('span', props.text) }, // If the component is a subcomponent of another component, you need to specify a name for the slot slot: 'name-of-slot', // Other special top-level properties key: 'myKey', ref: 'myRef', // If you apply the same ref name to multiple elements in the rendering function, // Then `$refs.myRef` will become an array. refInFor: true } 2.2 Constraints VNode must be unique All render: function (createElement) { var myParagraphVNode = createElement('p', 'hi') return createElement('div', [ // Error - Duplicate VNode myParagraphVNode, myParagraphVNode ]) } If you really need to repeat an element/component a lot of times, you can use a factory function to do it. For example, the following render function renders 20 identical paragraphs in a perfectly legal way: render: function (createElement) { return createElement('div', Array.apply(null, { length: 20 }).map(function () { return createElement('p', 'hi') }) ) } 3. Template function in Render function3.1 v-if and v-for As long as something can be easily done in native <ul v-if="items.length"> <li v-for="item in items">{{ item.name }}</li> </ul> <p v-else>No items found.</p> These can all be rewritten in the render function using props: ['items'], render: function (createElement) { if (this.items.length) { return createElement('ul', this.items.map(function (item) { return createElement('li', item.name) })) } else { return createElement('p', 'No items found.') } } 3.2 v-model There is no direct counterpart to props: ['value'], render: function (createElement) { var self = this return createElement('input', { domProps: { value: self.value }, on: { input: function (event) { self.$emit('input', event.target.value) } } }) } That’s the price of going low-level, but it gives you much finer control over the details of the interaction than 3.3 Events & Key Modifiers For the . For example: on: { '!click': this.doThisInCapturingMode, '~keyup': this.doThisOnce, '~!mouseover': this.doThisOnceInCapturingMode } For all other modifiers, the private prefix is not necessary, since you can use the event method from within the event handler: Here is an example using all modifiers: on: { keyup: function (event) { // If the element that triggers the event is not the element to which the event is bound // then return if (event.target !== event.currentTarget) return // If the enter key was not pressed or // the shift key was not pressed at the same time // then return if (!event.shiftKey || event.keyCode !== 13) return // Stop event bubbling event.stopPropagation() // Prevent the element's default keyup event event.preventDefault() // ... } } 3.4 Slots You can access the contents of static slots via render: function (createElement) { // `<div><slot></slot></div>` return createElement('div', this.$slots.default) } You can also access scoped slots through props: ['message'], render: function (createElement) { // `<div><slot :text="message"></slot></div>` return createElement('div', [ this.$scopedSlots.default({ text: this.message }) ]) } If you want to pass scoped slots to child components using a render function, you can use the render: function (createElement) { // `<div><child v-slot="props"><span>{{ props.text }}</span></child></div>` return createElement('div', [ createElement('child', { // Pass `scopedSlots` in the data object // The format is { name: props => VNode | Array<VNode> } scopedSlots: { default: function (props) { return createElement('span', props.text) } } }) ]) } 3.5 Examplesimport { CreateElement, RenderContext } from 'vue/types/umd' export default { functional: true, props: { row: Object, render: Function, index: Number, column: { type: Object, default: null } }, render: (h: CreateElement, ctx: RenderContext) => { const params: any = { row: ctx.props.row, index: ctx.props.index } if (ctx.props.column) params.column = ctx.props.column return ctx.props.render(h, params) } } This is the end of this article about You may also be interested in:
|
<<: Why the table file size remains unchanged after deleting data in MySQL
>>: MySQL Practical Experience of Using Insert Statement
1. Introduction to Animate.css Animate.css is a r...
The installation process is basically the same as...
The computer system has been reinstalled, and the...
Table of contents 1. Effect 2. Main code 1. Effec...
Joint Index The definition of the joint index in ...
Table of contents use Install How to use it in ro...
Let's talk about some problems I have encounte...
Payment countdown to return to the home page case...
In Vue, we generally have front-end and back-end ...
difficulty Two mask creation of svg graphics Firs...
1. Find duplicate rows SELECT * FROM blog_user_re...
Preface If someone asks you "What are the ch...
Table of contents Since Vuex uses a single state ...
You can often see articles about CSS drawing, suc...
In the project, you will encounter custom public ...