vue3学习教程第二十五节(h()函数的应用)

1、前言:

为什么vue 中已经有 template 模板语法,以及JSX了,还要使用 h()渲染函数;

vue 中选择默认使用template 静态模板分析,有利于DMO性能的提升,而且更接近真实的HTML便于开发设计人员理解修改,特别是对于熟练使用 HTML、CSS、JS的前端人员来说,更容易上手;

vue 中使用 h() 函数,可以更加方便的处理高度动态复杂渲染逻辑,相比而言比使用 template 模板 更加方便;但是由于渲染函数的性能消耗较大,所以一般不建议在开发中直接使用 h() 函数;并且在里面标签 属性 class 事件等杂糅一起,会难以理解;

2、定义:

h() 是一种能生成HTML的JavaScript
h() 函数 用于创建Vnodes 节点

用法:

接收三个参数
h(type, propsOrChildren, children)
type: 节点类型 字符串、对象、函数
propsOrChildren: 属性或子节点
children: 子节点

如:

// 除类型之外的所有参数都是可选的
h('div')
h('div', { id: 'foo' })
 
//属性和属性都可以在道具中使用
//Vue会自动选择正确的分配方式
h('div', { class: 'bar', innerHTML: 'hello' })
 
// props modifiers such as .prop and .attr can be added
// with '.' and `^' prefixes respectively
h('div', { '.name': 'some-name', '^width': '100' })
 
// class 和 style 可以是对象或者数组
h('div', { class: [foo, { bar }], style: { color: 'red' } })
 
// 定义事件需要加on 如 onXxx
h('div', { onClick: () => {} })
 
// 子集可以字符串
h('div', { id: 'foo' }, 'hello')
 
//如果没有props是可以省略props 的
h('div', 'hello')
h('div', [h('span', 'hello')])
 
// 子数组可以包含混合的VNode和字符串
h('div', ['hello', h('span', 'hello')])
const Vnode = h('div', { class: 'my-div' }, 'h() 渲染内容')
渲染之后得到
<div class="my-div">h() 渲染内容</div>

具体如下:

<template>
<div class="my-h">
This is a h() demo .
<hr></hr>
<vnodeDiv></vnodeDiv>
</div>
</template>
<script setup>
import { ref, h } from 'vue'
const vnodeDiv = () => {
  return h('div', { class: 'my-div' }, 'h() 渲染内容')
}
</script>

3、h() 函数 渲染多层DOM

const vnodeDiv = () => {
  return h('div', { class: 'my-div', dataType:"ces" }, [
    h('p', [h('span', 'h()1 渲染内容')]),
    h('p', 'h()2 渲染内容'),
    h('p', 'h()3 渲染内容'),
  ])
}

4、h() 函数 接收 props 中数据

<template>
<div class="my-h">
This is a h() demo .
<hr></hr>
<vnodeDiv :name="name"></vnodeDiv>
</div>
</template>
<script setup>
import { ref, h } from 'vue'
const name = ref('Andy')
// 这里与 setup() {} 一样,可以接收 props, context
// context.attrs, context.emit, context.slots
const vnodeDiv = (props, {attrs, emit, slots}) => {
  console.log('---props-', props)
  return h('div', { class: 'my-div', dataType:"ces" }, [
    h('p', [h('span', props.name)]), // Andy
    h('p', 'h()2 渲染内容'),
    h('p', 'h()3 渲染内容'),
  ])
}
</script>

5、h() 函数 接收emit 事件

事件以驼峰方式命名onXxx 如:onClick: ()=>{}

<template>
<div class="my-h">
This is a h() demo .
<hr></hr>
<vnodeDiv :name="name" @click="handleClick"></vnodeDiv>
</div>
</template>
<script setup>
import { ref, h } from 'vue'
const name = ref('Andy')
const handleClick = (data) => {
  console.log('====', data) // 这里得到子组件 触发事件 的参数
}
const vnodeDiv = (props, {attrs, emit, slots}) => {
  console.log('---props-', props)
  return h('div', { class: 'my-div', dataType:"ces" }, [
    h('p', {
      onClick: () => {
        // 使用emit 触发父组件事件
        emit('click', props.name)
    }}, 'h()2 渲染内容')
  ])
}
</script>

6、h() 函数 定义插槽 slots

通过 slots.xxx 语法定义插槽
如:匿名插槽 slots.default具名插槽 slots.footer

<div class="my-h">
This is a h() demo .
<hr></hr>
<vnodeDiv :name="name" @click="handleClick">
  <template #default>
    <div class="default-">
      这是默认插槽
    </div>
  </template>
  <template #footer>
    <div class="default-footer">
      这是具名插槽 footer 
          </div>
  </template>
</vnodeDiv>
</div>
</template>
<script setup>
import { ref, h } from 'vue'
const name = ref('Andy')
const handleClick = (data) => {
  console.log('====', data) // 这里得到子组件 触发事件 的参数
}
const vnodeDiv = (props, {attrs, emit, slots}) => {
  console.log('---props-', props)
  return h('div', { class: 'my-div', dataType:"ces" }, [
    h('p', [h('span', props.name)]),
    h('p', {
      onClick: () => {
        emit('click', props.name)
    }}, 'h()2 渲染内容'),
    h('p', 'h()3 渲染内容'),
    // 定义默认插槽  // 具名插槽 footer 这里可以定义多个插槽名称
  ], slots.default(), slots.footer())
}
</script>

7、h() 函数 渲染列表

<template>
<div class="my-h">
This is a h() demo .
<hr></hr>
<vnodeDiv :name="name" @click="handleClick">
  <template #default>
    <div class="default-">
      这是默认插槽
    </div>
  </template>
  <template #footer>
    <div class="default-footer">
      这是具名插槽 footer 
          </div>
  </template>
</vnodeDiv>
</div>
</template>
<script setup>
import { ref, h } from 'vue'
const name = ref('Andy')
const lists = ref([
  { name: 'Andy1', age: 18 },
  { name: 'Andy2', age: 19 },
  { name: 'Andy3', age: 22 },
])
const handleClick = (data) => {
  console.log('====', data) // 这里得到子组件 触发事件 的参数
}
const vnodeDiv = (props, {attrs, emit, slots}) => {
  console.log('---props-', props)
  return h('div', { class: 'my-div', dataType:"ces" }, [
    // 接收 props 中的数据
    h('p', [h('span', props.name)]),
    h('p', {
      onClick: () => {
        emit('click', props.name)
      }
    }, 'h()2 渲染内容'),
    // 循环渲染列表
    h('p', lists.value && lists.value.length && lists.value.map(itm => {
      return h('p', [h('span', itm.name), '~', h('span', itm.age)])
    })),
    // 定义默认插槽
  ], slots.default(), slots.footer())
}
</script>

运行结果如下:
请添加图片描述
对于 h() 函数 与 JSX 语法的使用,个人感觉 JSX 语法更灵活方便。

  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刺客-Andy

努力将爱好变成更有价值的事物

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值