Home > Article > Web Front-end > Using Vue render from scratch
This time I will bring you the use of Vue render from scratch. What are the precautions for using Vue render from scratch? The following is a practical case, let's take a look.
Introduction
When using Vue for development, in most cases, template is used for development. Using template is simple, convenient and fast, but sometimes it is necessary It is not very suitable to use template in special scenarios. So in order to make good use of the render function, I decided to take a closer look. If you feel that what is written below is incorrect, please point it out. Your interaction with me is the biggest motivation for writing.
Scenario
The scenario described on the official website When we start to write a component that dynamically generates a heading tag through level prop, you may quickly think of implementing it like this:
<script type="text/x-template" id="anchored-heading-template"> <h1 v-if="level === 1"> <slot></slot> </h1> <h2 v-else-if="level === 2"> <slot></slot> </h2> <h3 v-else-if="level === 3"> <slot></slot> </h3> <h4 v-else-if="level === 4"> <slot></slot> </h4> <h5 v-else-if="level === 5"> <slot></slot> </h5> <h6 v-else-if="level === 6"> <slot></slot> </h6> </script>
Vue.component('anchored-heading', { template: '#anchored-heading-template', props: { level: { type: Number, required: true } } })
Using template in this scenario is not the best choice: first of all, the code is verbose, and in order to insert anchor elements in different levels of headers, we need to use
Although templates are very useful in most components, they are not very concise here. So, let’s try to rewrite the above example using the render function:
Vue.component('anchored-heading', { render: function (createElement) { return createElement( 'h' + this.level, // tag name 标签名称 this.$slots.default // 子组件中的阵列 ) }, props: { level: { type: Number, required: true } } })
It’s much simpler and clearer! To put it simply, this code is much simpler, but it requires being very familiar with Vue's instance properties. In this example, you need to know that when you pass content to a component without using the slot attribute, such as Hello world! in anchored-heading, those child elements are stored in $slots.default in the component instance.
Introduction to createElement parameters
The next thing you need to be familiar with is how to generate a template in the createElement function. Here are the parameters accepted by createElement:
createElement( // {String | Object | Function} // 一个 HTML 标签字符串,组件选项对象,或者 // 解析上述任何一种的一个 async 异步函数,必要参数。 'p', // {Object} // 一个包含模板相关属性的数据对象 // 这样,您可以在 template 中使用这些属性。可选参数。 { // (详情见下一节) }, // {String | Array} // 子节点 (VNodes),由 `createElement()` 构建而成, // 或使用字符串来生成“文本节点”。可选参数。 [ '先写一些文字', createElement('h1', '一则头条'), createElement(MyComponent, { props: { someProp: 'foobar' } }) ] )
Deep into the data object
One thing to note: as in the template syntax, v-bind:class and v-bind :style will be treated specially. In the VNode data object, the following attribute names are the highest-level fields. This object also allows you to bind normal HTML attributes, like DOM properties, such as innerHTML (this replaces the v-html directive).
{ // 和`v-bind:class`一样的 API 'class': { foo: true, bar: false }, // 和`v-bind:style`一样的 API style: { color: 'red', fontSize: '14px' }, // 正常的 HTML 特性 attrs: { id: 'foo' }, // 组件 props props: { myProp: 'bar' }, // DOM 属性 domProps: { innerHTML: 'baz' }, // 事件监听器基于 `on` // 所以不再支持如 `v-on:keyup.enter` 修饰器 // 需要手动匹配 keyCode。 on: { click: this.clickHandler }, // 仅对于组件,用于监听原生事件,而不是组件内部使用 // `vm.$emit` 触发的事件。 nativeOn: { click: this.nativeClickHandler }, // 自定义指令。注意,你无法对 `binding` 中的 `oldValue` // 赋值,因为 Vue 已经自动为你进行了同步。 directives: [ { name: 'my-custom-directive', value: '2', expression: '1 + 1', arg: 'foo', modifiers: { bar: true } } ], // Scoped slots in the form of // { name: props => VNode | Array<VNode> } scopedSlots: { default: props => createElement('span', props.text) }, // 如果组件是其他组件的子组件,需为插槽指定名称 slot: 'name-of-slot', // 其他特殊顶层属性 key: 'myKey', ref: 'myRef' }
Conditional rendering
Now that we are familiar with the above API, let’s do some practical combat.
Write like this before
//HTML <p id="app"> <p v-if="isShow">我被你发现啦!!!</p> </p> <vv-isshow :show="isShow"></vv-isshow> //js //组件形式 Vue.component('vv-isshow', { props:['show'], template:'<p v-if="show">我被你发现啦2!!!</p>', }); var vm = new Vue({ el: "#app", data: { isShow:true } });
renderWrite like this
//HTML <p id="app"> <vv-isshow :show="isShow"><slot>我被你发现啦3!!!</slot></vv-isshow> </p> //js //组件形式 Vue.component('vv-isshow', { props:{ show:{ type: Boolean, default: true } }, render:function(h){ if(this.show ) return h('p',this.$slots.default); }, }); var vm = new Vue({ el: "#app", data: { isShow:true } });
List rendering
It was written like this before, and when v-for, the template must be wrapped by a label
//HTML <p id="app"> <vv-aside v-bind:list="list"></vv-aside> </p> //js //组件形式 Vue.component('vv-aside', { props:['list'], methods:{ handelClick(item){ console.log(item); } }, template:'<p>\ <p v-for="item in list" @click="handelClick(item)" :class="{odd:item.odd}">{{item.txt}}</p>\ </p>', //template:'<p v-for="item in list" @click="handelClick(item)" :class="{odd:item.odd}">{{item.txt}}</p>',错误 }); var vm = new Vue({ el: "#app", data: { list: [{ id: 1, txt: 'javaScript', odd: true }, { id: 2, txt: 'Vue', odd: false }, { id: 3, txt: 'React', odd: true }] } });
render is written like this
//HTML <p id="app"> <vv-aside v-bind:list="list"></vv-aside> </p> //js //侧边栏 Vue.component('vv-aside', { render: function(h) { var _this = this, ayy = this.list.map((v) => { return h('p', { 'class': { odd: v.odd }, attrs: { title: v.txt }, on: { click: function() { return _this.handelClick(v); } } }, v.txt); }); return h('p', ayy); }, props: { list: { type: Array, default: () => { return this.list || []; } } }, methods: { handelClick: function(item) { console.log(item, "item"); } } }); var vm = new Vue({ el: "#app", data: { list: [{ id: 1, txt: 'javaScript', odd: true }, { id: 2, txt: 'Vue', odd: false }, { id: 3, txt: 'React', odd: true }] } });
v-model
Previous writing method
//HTML <p id="app"> <vv-models v-model="txt" :txt="txt"></vv-models> </p> //js //input Vue.component('vv-models', { props: ['txt'], template: '<p>\ <p>看官你输入的是:{{txtcout}}</p>\ <input v-model="txtcout" type="text" />\ </p>', computed: { txtcout:{ get(){ return this.txt; }, set(val){ this.$emit('input', val); } } } }); var vm = new Vue({ el: "#app", data: { txt: '', } });
render is written like this
//HTML <p id="app"> <vv-models v-model="txt" :txt="txt"></vv-models> </p> //js //input Vue.component('vv-models', { props: { txt: { type: String, default: '' } }, render: function(h) { var self=this; return h('p',[h('p','你猜我输入的是啥:'+this.txt),h('input',{ on:{ input(event){ self.$emit('input', event.target.value); } } })] ); }, }); var vm = new Vue({ el: "#app", data: { txt: '', } });
Summary
Render function usage What's more, JavaScript's complete programming ability has an absolute advantage in performance. The editor is just analyzing it. As for the actual project, which method you choose for rendering still needs to be determined based on your project and actual conditions.
I believe you have mastered the method after reading the case in this article. For more exciting information, please pay attention to other related articles on the php Chinese website!
Recommended reading:
How json-server creates back-end data
Detailed explanation of the use of vuex state management
The above is the detailed content of Using Vue render from scratch. For more information, please follow other related articles on the PHP Chinese website!