From 409cc860cfbdd8c9cc1c94ab266ee1aad77d7a37 Mon Sep 17 00:00:00 2001 From: skirtle <65301168+skirtles-code@users.noreply.github.com> Date: Tue, 12 Jan 2021 06:36:56 +0000 Subject: [PATCH] docs: use destructuring to access createApp, etc. in render-function.md --- src/guide/render-function.md | 100 ++++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 43 deletions(-) diff --git a/src/guide/render-function.md b/src/guide/render-function.md index 1c9ac18760..edf783e101 100644 --- a/src/guide/render-function.md +++ b/src/guide/render-function.md @@ -21,7 +21,9 @@ Anchored headings are used very frequently, we should create a component: The component must generate a heading based on the `level` prop, and we quickly arrive at this: ```js -const app = Vue.createApp({}) +const { createApp } = Vue + +const app = createApp({}) app.component('anchored-heading', { template: ` @@ -58,11 +60,13 @@ This template doesn't feel great. It's not only verbose, but we're duplicating ` While templates work great for most components, it's clear that this isn't one of them. So let's try rewriting it with a `render()` function: ```js -const app = Vue.createApp({}) +const { createApp, h } = Vue + +const app = createApp({}) app.component('anchored-heading', { render() { - return Vue.h( + return h( 'h' + this.level, // tag name {}, // props/attributes this.$slots.default() // array of children @@ -109,7 +113,7 @@ Or in a render function: ```js render() { - return Vue.h('h1', {}, this.blogTitle) + return h('h1', {}, this.blogTitle) } ``` @@ -120,7 +124,7 @@ And in both cases, Vue automatically keeps the page updated, even when `blogTitl Vue keeps the page updated by building a **virtual DOM** to keep track of the changes it needs to make to the real DOM. Taking a closer look at this line: ```js -return Vue.h('h1', {}, this.blogTitle) +return h('h1', {}, this.blogTitle) ``` What is the `h()` function returning? It's not _exactly_ a real DOM element. It returns a plain object which contains information describing to Vue what kind of node it should render on the page, including descriptions of any child nodes. We call this node description a "virtual node", usually abbreviated to **VNode**. "Virtual DOM" is what we call the entire tree of VNodes, built by a tree of Vue components. @@ -169,7 +173,9 @@ If there are no props then the children can usually be passed as the second argu With this knowledge, we can now finish the component we started: ```js -const app = Vue.createApp({}) +const { createApp, h } = Vue + +const app = createApp({}) /** Recursively get text from children nodes */ function getChildrenTextContent(children) { @@ -192,8 +198,8 @@ app.component('anchored-heading', { .replace(/\W+/g, '-') // replace non-word characters with dash .replace(/(^-|-$)/g, '') // remove leading and trailing dashes - return Vue.h('h' + this.level, [ - Vue.h( + return h('h' + this.level, [ + h( 'a', { name: headingId, @@ -220,8 +226,8 @@ All VNodes in the component tree must be unique. That means the following render ```js render() { - const myParagraphVNode = Vue.h('p', 'hi') - return Vue.h('div', [ + const myParagraphVNode = h('p', 'hi') + return h('div', [ // Yikes - duplicate VNodes! myParagraphVNode, myParagraphVNode ]) @@ -232,9 +238,9 @@ If you really want to duplicate the same element/component many times, you can d ```js render() { - return Vue.h('div', + return h('div', Array.from({ length: 20 }).map(() => { - return Vue.h('p', 'hi') + return h('p', 'hi') }) ) } @@ -246,16 +252,20 @@ To create a VNode for a component, the first argument passed to `h` should be th ```js render() { - return Vue.h(ButtonCounter) + return h(ButtonCounter) } ``` If we need to resolve a component by name then we can call `resolveComponent`: ```js +const { h, resolveComponent } = Vue + +// ... + render() { - const ButtonCounter = Vue.resolveComponent('ButtonCounter') - return Vue.h(ButtonCounter) + const ButtonCounter = resolveComponent('ButtonCounter') + return h(ButtonCounter) } ``` @@ -269,7 +279,7 @@ components: { ButtonCounter }, render() { - return Vue.h(Vue.resolveComponent('ButtonCounter')) + return h(resolveComponent('ButtonCounter')) } ``` @@ -277,7 +287,7 @@ Rather than registering a component by name and then looking it up we can use it ```js render() { - return Vue.h(ButtonCounter) + return h(ButtonCounter) } ``` @@ -300,11 +310,11 @@ This could be rewritten with JavaScript's `if`/`else` and `map()` in a render fu props: ['items'], render() { if (this.items.length) { - return Vue.h('ul', this.items.map((item) => { - return Vue.h('li', item.name) + return h('ul', this.items.map((item) => { + return h('li', item.name) })) } else { - return Vue.h('p', 'No items found.') + return h('p', 'No items found.') } } ``` @@ -319,7 +329,7 @@ The `v-model` directive is expanded to `modelValue` and `onUpdate:modelValue` pr props: ['modelValue'], emits: ['update:modelValue'], render() { - return Vue.h(SomeComponent, { + return h(SomeComponent, { modelValue: this.modelValue, 'onUpdate:modelValue': value => this.$emit('update:modelValue', value) }) @@ -332,7 +342,7 @@ We have to provide a proper prop name for the event handler, e.g., to handle `cl ```js render() { - return Vue.h('div', { + return h('div', { onClick: $event => console.log('clicked', $event.target) }) } @@ -346,7 +356,7 @@ For example: ```javascript render() { - return Vue.h('input', { + return h('input', { onClickCapture: this.doThisInCapturingMode, onKeyupOnce: this.doThisOnce, onMouseoverOnceCapture: this.doThisOnceInCapturingMode @@ -368,7 +378,7 @@ Here's an example with all of these modifiers used together: ```js render() { - return Vue.h('input', { + return h('input', { onKeyUp: event => { // Abort if the element emitting the event is not // the element the event is bound to @@ -394,7 +404,7 @@ We can access slot contents as arrays of VNodes from [`this.$slots`](../api/inst ```js render() { // `