认识h函数

 vue推荐在绝大多数情况下使用模板来创建html,但是在一些特殊的场景,需要JavaScript的完全编程的能力,这个时候就可以使用渲染函数,比模板更接近编译器

 vue在生成真实的DOM之前,会将所有的节点转换成VNode,而VNode组合在一起形成一颗树结构,就是虚拟DOM(VDOM)

template中的html最终也会使用渲染函数生成对应的VNode

可以使用JavaScript编写createVNode函数,生成对应的VNode

 

 

 

 h()函数是一个用于创建vnode的一个函数

 h()函数怎么使用?

h()函数接收三个参数

第一个参数:是标签的名称、组件、异步组件或者函数式组件

第二个参数:标签的属性,

 第三参数:标签中的内容 

 注意:如果没有props,那么通常可以将children作为第二参数传入

如果产生歧义,可以将numm作为第二个参数传入,将children作为第三个参数传入

 如果使用render函数的话,就不需要写template标签了

<script>
import {h} from "vue"
export default {
  render() {
      return h('h2',{
          class:'text'
      },'hello word')
  },
};
</script>

 

 

 使用·h函数实现一个计数器

<script>
import {h} from "vue"
export default {
  data(){
    return {
      counter:0
    }
  },
  render() {
      return h('div',{
          class:'app'
      },[
        h('h2',null,`当前计数:${this.counter}`),
        h('button',{
          onClick:()=>this.counter++
        },'+1'),
        h('button',{
           onClick:()=>this.counter--
        },'-1')  
      ])
  },
};
</script>

 

 

 也可以使用setup替代data使用

<script>
import {h,ref} from "vue"
export default {
  setup(){
    const counter=ref(0)
    return {counter}
  },
  render() {
      return h('div',{
          class:'app'
      },[
        h('h2',null,`当前计数:${this.counter}`),
        h('button',{
          onClick:()=>this.counter++
        },'+1'),
        h('button',{
           onClick:()=>this.counter--
        },'-1')  
      ])
  },
};
</script>

也可以在setup中写render函数

<script>
import {h,ref} from "vue"
export default {
  setup(){
    const counter=ref(0)
    return ()=>{
      
      return h('div',{
          class:'app'
      },[
        h('h2',null,`当前计数:${counter.value}`),
        h('button',{
          onClick:()=>counter.value++
        },'+1'),
        h('button',{
           onClick:()=>counter.value--
        },'-1')  
      ])
    }
  },

};
</script>

接收的参数第一个是组件的情况

hellowrd.vue

<script>
import {h} from 'vue'
export default {
   render(){
       return h("h2",null,'hello word')
   }
}
</script>

app.vue

<script>
import { h } from "vue";
import helloword from "./1/helloword.vue";
export default {
  render() {
    return h(helloword, null, "");
  },
};
</script>

 

 

 也可以传入插槽

app.vue

<script>
import { h } from "vue";
import helloword from "./1/helloword.vue";
export default {
  render() {
    return h(helloword, null, {
      default:props=>h('span',null,'传到helloword的内容')
    });
  },
};
</script>

helloword.vue

<script>
import {h} from 'vue'
export default {
   render(){
       return h("div",null,[
           h('h2',null,'helloword'),
           this.$slots.default ? this.$slots.default() :  h('span',null,'插槽默认值'),
       ])
   }
}
</script>

 

 

 

再看jsx

如果要在项目中使用jsx,就需要添加对jsx的支持

jsx通过babel来进行转换,在vue中配置对应的插件即可

安装插件

npm install @vue/babel-plugin-jsx

在bable.config.js配置插件

module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset'
  ],
  plugins:[
    '@vue/babel-plugin-jsx'
  ]
}

 

 

<script>
  export default {
    data(){
      return {
        counter:0
      }
    },
    render(){
      const increment=()=>this.counter++
      const decrement=()=>this.counter--
      return (
        <div>
        <h2>当前计数:{this.counter}</h2>
        <button onClick={increment}>+</button>
        <button onClick={decrement}>-</button>
        </div>
      )
    }
  }
</script>

 

 也可以使用组件的时候传入一个插槽

<script>
import helloword from "./helloword.vue"
  export default {
    data(){
      return {
        counter:0
      }
    },
    render(){
      const increment=()=>this.counter++
      const decrement=()=>this.counter--
      return (
        <div>
        <h2>当前计数:{this.counter}</h2>
        <button onClick={increment}>+</button>
        <button onClick={decrement}>-</button>
        <helloword>
          {{default:props=><button>按钮</button>}}
        </helloword>
        </div>
      )
    }
  }
</script>

helloword.vue

<script>
export default {
   render(){
       return (
           <div>
           <h2>hello word</h2>
           {this.$slots.default ? this.$slots.default():<span>hello</span>}
           </div>
       )
   }
}
</script>

 

posted @ 2022-04-05 16:58  keyeking  阅读(2389)  评论(0编辑  收藏  举报