引出
在vue的日常开发当中,我们可能会遇到这样的一种情况:
某一部分的模版需要重复利用, 但又不至于到新开1个组件的地步。
比如:
js
复制代码
<template>
<div v-for="item in list">
// 条件渲染
<div v-if="isCase1(item.id)" class="case1Class ...">
<h2>{{ item.title }}</h2>
<p class="...">{{ item.content }}</p>
<span> {{ item.cases }} </span>
</div>
<p v-else-if="isCase2(item.id)" class="case2Class ...">{{ item.content }}</p>
<span v-else> {{ item.cases }} </span>
// 条件可能有更多....
</div>
</template>
这里面的<p>
<span>
都是可以复用的,但为此新开俩组件又没有必要。
那么又有什么解决方案呢?
来自react的提示
在react 当中啊,碰到这种情况,可以定义1个 局部的函数式组件
示例:
jsx
复制代码
function Com () {
// 局部组件
const ReuseP = ({content,className})=> (<p className={`${className} ...其余复用class`}>{ content }</p> )
return (
list.map(i=>{
if(isCase1(i.id)){
return (
<div>
{/* ... */}
{/* 在这里去复用 */}
<ReuseP {...i} className="case2Class" />
</div>
)
}
})
)
}
回到vue
那么在Vue当中能不能实现呢? 答案显然是可以的
其实在Vue3当中,可以支持在.vue
文件即SFC
当中去使用jsx/tsx
语法的
看看文档
是不是很熟悉,这不就是react当中的函数式组件么
也就是说,可以将上面的例子改写成这样
diff
复制代码
<template>
<div v-for="item in list">
// 条件渲染
<div v-if="isCase1(item.id)" class="case1Class ...">
<h2>{{ item.title }}</h2>
- <p class="...">{{ item.content }}</p>
+ <reuseP v-bind="item"/>
<span> {{ item.cases }} </span>
</div>
- <p v-else-if="isCase2(item.id)" class="case2Class ...">{{ item.content }}</p>
+ <reuseP v-else-if="isCase2(item.id)" v-bind:content="item.content" v-bind:your-class="'case2Class'" ></reuseP>
<span v-else> {{ item.cases }} </span>
// 条件可能有更多....
</div>
</template>
+ // ⚠️ 注意这里的lang
+ <script setup lang="jsx">
+ const reuseP = ({ content }) => (
+ <p className={`${args['your-class']} ...其余复用class`}>{ content }</p>
+ )
+ </script>
可以清晰的看到在.vue文件即Vue但文件组件(SFC)
里面通过jsx去实现了一个组件内的小组件
,进而达到了组件内模版复用的效果。
ps: 当然这里只是举例了可以复用
<p>
的例子,你也可以更加优雅的去实现,比如把整个v-for都用jsx写一下
大概的代码结构会是这样
当然,这里只是给大家提供一个思路,jsx与template的结合是相当灵活的,不过相信聪明的看官们能够轻松应对。
也许有看官还不了解jsx
回顾
首先回顾一下vue模版语法的编译产物
它其实是将模版也解析成渲染函数
的形式
这里的createElementVNode
其实就是h函数
,作用是创建VNode
那么整一个渲染函数的作用就是结合 上下文对象
生成VNode
VNode就是用对象去描述DOM节点(WEB端)
比如这样一个真实DOM
对应的虚拟VNode的核心描述
js
复制代码
const vnode = {
tag: 'div', // 标签名为 'div'
data: {}, // 无属性、样式和事件等信息
children: [
{
tag: undefined, // 文本节点没有标签名
data: {}, // 无属性、样式和事件等信息
children: undefined,
text: 'Hello JetTsang' // 文本内容为 'Hello JetTsang'
}
],
text: undefined,
//。。。省略
};
当然,在Vue和React中,对于VNode结构的描述存在一些区别,包括不同的属性等等。然而,它们的本质都是以一种数据结构来描述真实节点。
这例子当中VNode就是外面的这个div(当然忽略_openBlock
这个块级容器 )
jsx
其实JSX和模版语法一样,借助@vue/babel-plugin-jsx,也能转换成渲染函数
拿一个最简单的例子
标签:Vue,模版,解锁,复用,content,item,vue,组件,jsx From: https://blog.51cto.com/u_15723831/7741126