渲染函数render
在vue中我们除了可以用template来进行模板化的渲染输出,还可以用render方法进行编程式的渲染
模板有着看起来更易于阅读,更直接的优点,而render方法有着更好的灵活性,但是在vue3中依然保留了这个功能,而且还为Composition Api的编程理念做了调整。
在vue2中,render函数自动接收一个h函数,h作为参数传递进来
<body> <div id="app"> <ren></ren> </div> <script> Vue.component("ren",{ render(h){ // h()其实就是createElement函数的简写 //第一个是标签名,第二个是标签属性,,第三个是内容 return h('div',{ // 给div添加了一个id的属性值为foo attrs:{id:'foo'}, style:{color:'red'}, //添加一个行内样式 on:{click:this.onClick}//添加一个事件 },'hello') }, methods:{ onClick(){ console.log("我是render函数渲染") } } }) new Vue({ el:"#app" }) </script>
点击之后也会触发onClick方法
还可以在添加一个domProps属性
render(h){
// h()其实就是createElement函数的简写
//第一个是标签名,第二个是标签属性,,第三个是内容
return h('div',{
// 给div添加了一个id的属性值为foo
attrs:{id:'foo'},
style:{color:'red'}, //添加一个行内样式
on:{click:this.onClick},//添加一个事件
domProps:{innerHTML:'word'} //domProps是虚拟dom属性中的一个嵌套链表
},'hello')
},
h函数的三个参数:
- 第一个参数:类型,组件类型,字符串代表原生节点,对象或者方法表示自定义组件
- 第二个参数:props 组件(原生节点)的属性,通过对象传入
- 第三个参数:插槽 slots 组件插槽内容,原生节点的内容
在vue3中渲染函数会变得简单好用,主要的更改有:
- h是全局导入,而不是作为参数传递给渲染函数
- 渲染函数参数更改为在有状态组件和函数式组件之间更加一致
- vnode现在有一个扁平的prop结构
由于render函数不再接收任何参数,它将主要用于setup函数内部,可以访问作用域中声明的响应式状态和函数,以及传递给setup的参数
ren.vue
<script> import {h, reactive} from 'vue' export default { setup(props,{slots,emit,attrs}){ const state=reactive({ count:0 }) function fun(){ state.count++ } // 返回render函数 return ()=> h('div',{ //在vue3中,整个vnode props的结构是扁平的 onClick:fun, class:['box'], style:{color:'#555'}, },state.count) } } </script>
案例:实现一个计数器
count.vue
<script> import {h,ref} from 'vue' function useCount(){ const count=ref(0) const increase=()=>{ count.value++ } const reset=()=>{count.value=0} return {count,increase,reset} } export default { setup(props,{attrs,emit,slots}){ const {count,increase,reset} =useCount() return ()=> h('div',{class:'count'},[ h('h4',null,'计数器'), h('div',{class:'count-main'},[ h('span',{class:'count-label'},'已经点击了'), h('span',{class:'count-text'},count.value), h('span',{class:'count-label'},'下') ]), h('div',{class:'count-btns'},[ h('button',{class:'btn',onClick:increase},'计数'), h('button',{class:'btn',onClick:reset},'清零') ]) ]) } } </script>