認識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>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM