渲染函数和JSX(二)函数式组件

函数式组件

在components文件夹中新建list.vue和index.js文件进行配置(新建一个组件)

<template>
  <div>
    <ul>
      <li v-for="(item, index) in list" :key="`item_${index}`"></li>
    </ul>
  </div>
</template>
<script>
export default {
  name: 'List',
  props: {
    list: {
      type: Array,
      //数组设置默认值时需要设置参数
      default: () => []
    }
  }
}
</script>

import List from './list.vue'
export default List

在views中的render-page页面引入并注册

import List from '_c/list'
components: {
    List
  }
<template>
  <div>
    <list :list='list'></list>
  </div>
</template>

如果追求个性化,不想用span标签包裹数据,则可以在父组件中(views中的render-page页面)传入自定义的render(我们在后面将其在子组件注册)

<template>
  <div>
    <list :list='list' :render='renderFunc'></list>
  </div>
</template>
methods: {
    renderFunc (h) {
      return h('i', {
        style: {
          color: 'pink'
        }
        //这里传入第三个参数
      }, )
    }
  }

接下来我们需要使用到函数式组件
函数式组件没有正常组件的钩子函数,生命周期,只是用来接收参数的函数
在components文件夹下定义render-dom.js文件用来配置函数式组件

export default {
  //  设置为true,意味着这个组件没有状态和实例
  // 引入到其他页面时vue会对其进行处理,将render函数里面的虚拟节点进行渲染
  functional: true,
  props: {
    name: String,
    renderFunc () {}
  },
  render: (h, ctx) => {
    //  h参数为渲染函数
    //  第二个参数是一个实例,指代当前导出的对象
    return ctx.props.renderFunc(h, ctx.props.name)
  }
}

在子组件(list.vue)中配置函数式组件

<template>
  <div>
    <ul>
      <li v-for="(item, index) in list" :key="`item_${index}`">
        <!-- 如果用户没用使用自定义render -->
        <span v-if='!render'>{{ item.name }}</span>
        <!-- 这里我们将在render-dom.js定义的属性写成驼峰式 -->
        <render-dom v-else :render-func='render' :name='item.name'></render-dom>
      </li>
    </ul>
  </div>
</template>
<script>
import RenderDom from '_c/render-dom'
export default {
  name: 'List',
  components: {
    RenderDom
  },
  props: {
    list: {
      type: Array,
      default: () => []
    },
    render: {
      type: Function,
      default: () => {}
    }
  }
}
</script>

接下来在父组件(views中的render-page.vue)中进行配置

methods: {
    // 第一个参数为渲染函数,第二个参数为render-dom的name
    renderFunc (h, name) {
      return h('i', {
        style: {
          color: 'pink'
        }
      }, name)
    }
  }

效果图
在这里插入图片描述

3.JSX

jsx是在js中写html标签还有特定的语法,最后把其转换成js并且用render渲染
下面我们使用jsx
在之前步骤的基础上,在render-page(父组件中)改动

methods: {
    // 使用jsx这里必须使用h
    // 在jsx中变量首先要用一个花括号包起来
    // 花括号里是一个对象,对象里面也有一个花括号,然后定义属性
    renderFunc (h, name) {
      return (
        <i style={{ color: 'red' }}>{name}</i>
      )
    }
  }

3.1在jsx中如何给标签绑定事件

methods: {
    renderFunc (h, name) {
      return (
        <i on-click={this.handleClick} style={{ color: 'red' }}>{name}</i>
      )
    },
    handleClick (event) {
      console.log(event)
    }
  }

3.2在jsx中如何渲染组件
首先在父组件(views中render-page)中引入组件(这里我们以countTo组件为例)
在render和jsx中使用组件不需要在components中注册

import CountTo from '_c/count-to'

将render-dom.js、list.vue、render-page.vue中的name全部改为num,同时将render-dom.js中的props属性下的name值由String换为Number

methods: {
    renderFunc (h, number) {
      return (
        <CountTo endVal={number} on-click={this.handleClick} style={{ color: 'red' }}>{number}</CountTo>
      )
    },
    handleClick (event) {
      console.log(event)
    }
  }

3.3在jsx中如何给引用的组件绑定自定义事件和原生事件
绑定自定义事件

methods: {
    renderFunc (h, name) {
      return (
        // 使用on绑定自定义事件
        // 使用nativeOn绑定原生事件
        // on-animation-end为我们在countTo组件中定义的事件
        <CountTo  nativeOn-click={this.handleClick} on-on-animation-end={this.handleEnd} endVal={name} style={{ color: 'red' }}>{name}</CountTo>
      )
    },
    handleClick (event) {
      console.log(event)
    },
    handleEnd () {
      console.log('end!')
    }
  }

3.4在render和jsx中如何阻止鼠标选中
还有很多在template中的修饰符在render中使用不了的需要查阅文档
在子组件中进行配置

      <li @mousemove="handleMove" v-for="(item, index) in list" :key="`item_${index}`">

调用事件对象的preventDefault方法阻止鼠标移动事件的默认行为

methods: {
    handleMove (event) {
      event.preventDefault()
    }
  }
4.作用域插槽

我们通过作用域插槽来实现自定义内容的渲染
在list.vue子组件中

<template>
  <div>
    <ul>
      <li @mousemove="handleMove" v-for="(item, index) in list" :key="`item_${index}`">
        <slot :number='item.number'></slot>
      </li>
    </ul>
  </div>
</template>

在父组件中删去render属性,由于我们要在template中使用countTo组件,所以要在components中注册

<template>
  <div>
    <list :list='list' >
      <!-- 使用slot-scope属性并且随便定一个名称值,这个名称是一个包含了子组件插槽中的属性以及值的对象-->
      <count-to slot-scope="count" :end-val='count.number'></count-to>
    </list>
  </div>
</template>
components: {
    List,
    CountTo
  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值