Vue函数式组件处理Props生成CSS类报错,求正确实现方法
问题分析
你遇到的报错TypeError: _vm.classObject is not a function核心原因是函数式组件没有组件实例:你在模板里调用的classObject放在了methods里,但函数式组件不会创建实例,_vm(组件实例对象)根本不存在,自然找不到这个方法。另外你的代码还有两个小问题:重复的<script>标签,以及用vue-class-component写函数式组件——类组件依赖实例,和函数式组件的无实例设计冲突。
解决方案
下面给你三种可行的写法,根据你的习惯选择:
方案1:用Render函数写函数式组件(推荐)
函数式组件的本质就是纯渲染逻辑,用render函数最贴合它的设计,也能避免模板上下文的问题:
<script lang="ts"> import Vue from 'vue'; export default Vue.extend({ // 明确标记为函数式组件 functional: true, props: { xIndex: { type: Number, required: true }, yIndex: { type: Number, required: true } }, render(createElement, context) { // 从context中获取props const { xIndex, yIndex } = context.props; // 计算class对象 const classObject = { normal: true, 'thick-left': xIndex % 10 === 0, 'thick-top': yIndex % 10 === 0, 'thick-right': (xIndex + 1) % 10 === 0, 'thick-bottom': (yIndex + 1) % 10 === 0 }; // 创建并返回div元素 return createElement('div', { class: classObject }); } }); </script>
方案2:模板式函数式组件(内联计算class)
如果偏爱模板写法,可以直接把class的计算逻辑内联到模板中,这样不需要额外的函数:
<template functional> <div :class="{ normal: true, 'thick-left': props.xIndex % 10 === 0, 'thick-top': props.yIndex % 10 === 0, 'thick-right': (props.xIndex + 1) % 10 === 0, 'thick-bottom': (props.yIndex + 1) % 10 === 0 }" ></div> </template> <script lang="ts"> import Vue from 'vue'; export default Vue.extend({ functional: true, props: { xIndex: { type: Number, required: true }, yIndex: { type: Number, required: true } } }); </script>
方案3:模板式+外部工具函数
如果想把计算逻辑抽离成可复用的函数,可以把函数挂载到组件选项上,通过$options访问:
<template functional> <!-- 通过$options访问组件选项上的工具函数 --> <div :class="$options.getClassObject(props)"></div> </template> <script lang="ts"> import Vue from 'vue'; // 抽离纯函数处理props生成class const getClassObject = (props: { xIndex: number; yIndex: number }) => { const { xIndex, yIndex } = props; return { normal: true, 'thick-left': xIndex % 10 === 0, 'thick-top': yIndex % 10 === 0, 'thick-right': (xIndex + 1) % 10 === 0, 'thick-bottom': (yIndex + 1) % 10 === 0 }; }; export default Vue.extend({ functional: true, props: { xIndex: { type: Number, required: true }, yIndex: { type: Number, required: true } }, // 把工具函数挂载到组件选项上 getClassObject }); </script>
注意事项
- 函数式组件不要用
vue-class-component或@Component装饰器,这类工具是为有状态的类组件设计的,和函数式组件的无实例、无状态特性冲突。 - 模板式函数式组件中,模板的上下文是
render函数的参数,你可以直接访问props、children等,但不能访问this或组件实例的方法。
内容的提问来源于stack exchange,提问作者Tagc
相关产品推荐
相关产品推荐

