feat: 在单一vue组件内实现模板复用(非jsx版本)

flex-api
LCJ-MinYa 6 months ago
parent 9d9ff346c7
commit 15908d0543

@ -98,6 +98,10 @@ const titleArr = [
key: 'reg',
title: '正则表达式',
},
{
key: 'templateReuse',
title: '在单一vue组件内实现模板复用非jsx版本',
},
];
// @/views/demo/**/*.vue

@ -0,0 +1,29 @@
export function creatTemplateReuse() {
let render = [];
const DefineTemplate = {
setup(_, { slots }) {
console.log(slots);
// render = slots.default;
for (let key in slots) {
render.push({
slotName: key,
render: slots[key],
});
}
return () => {};
},
};
const useTemplate = (props) => {
console.log(props);
let renderList = [];
props.slotName.forEach((name) => {
let chooseItem = render.find((item) => item.slotName === name);
renderList.push(chooseItem.render(props));
});
return renderList;
};
return [DefineTemplate, useTemplate];
}

@ -0,0 +1,90 @@
<template>
<div
class="markdown-body"
v-html="htmlStr"
/>
<div class="wrap">
<DefineTemplate v-slot:default="{ title, content, onFoo }">
<!-- 方法可以直接使用script中的写法: @click="doClick" -->
<div
class="box"
@click="onFoo()"
>
<p>{{ title }}</p>
<p>{{ content }}</p>
</div>
</DefineTemplate>
<DefineTemplate>
<template v-slot:header="{ title, content, onFoo }">
<div
class="box"
@click="onFoo()"
>
<p>{{ title }}: header</p>
<p>{{ content }}</p>
</div>
</template>
<template v-slot:footer="{ title, content, onFoo }">
<div
class="box"
@click="onFoo()"
>
<p>{{ title }}: footer</p>
<p>{{ content }}</p>
</div>
</template>
</DefineTemplate>
<useTemplate
title="我是默认插槽模板"
content="默认插槽模板内容"
@foo="doClick"
:slotName="['default']"
></useTemplate>
<useTemplate
title="我是包含header和footer的插槽模板"
content="包含header和footer的插槽模板内容"
@foo="doClick"
:slotName="['header', 'footer']"
></useTemplate>
<!-- <div class="box">
<p>标题一</p >
<p>内容一</p >
</div>
<div class="box">
<p>标题二</p >
<p>内容二</p >
</div> -->
</div>
</template>
<script setup>
import { ref } from 'vue';
import { marked } from 'marked';
import { getMarkdownContent } from '@/utils/tools';
const htmlStr = ref('');
getMarkdownContent('./md/templateReuse.md').then((res) => {
htmlStr.value = marked(res);
});
/** 定义模板demo */
import { creatTemplateReuse } from './index';
const [DefineTemplate, useTemplate] = creatTemplateReuse();
const doClick = () => {
console.log('我是点击事件');
};
</script>
<style scoped>
.wrap {
display: flex;
}
.box {
width: 200px;
background: #e1e1e1;
margin-right: 50px;
}
</style>

@ -0,0 +1,71 @@
## 在单一vue组件内实现模板复用非jsx版本
关联文章,[使用jsx](/#/demo/jsx)
### 注意事项
* `定义的模版必须放置在使用之前,遵循代码执行顺序`
* `复杂版本将render渲染的slot存为了一个数组使用的时候必须传入数组类型的slotName这样在使用useTemplate函数时才知道该渲染哪个模版`
* `简单版本可以直接v-slot默认使用defalut`
### 简单版本源代码
```vue
<template>
<DefineTemplate v-slot="{ title, content, onFoo }">
<!-- 方法可以直接使用script中的写法: @click="doClick" -->
<div class="box" @click="onFoo()">
<p>{{ title }}</p >
<p>{{ content }}</p >
</div>
</DefineTemplate>
<useTemplate title="标题一" content="内容一" @foo="doClick"></useTemplate>
<useTemplate title="标题二" content="内容二" @foo="doClick"></useTemplate>
<!-- <div class="box">
<p>标题一</p >
<p>内容一</p >
</div>
<div class="box">
<p>标题二</p >
<p>内容二</p >
</div> -->
</template>
<script setup>
import { creatTemplateReuse } from "./index";
const [DefineTemplate, useTemplate] = creatTemplateReuse();
const doClick = () => {
console.log("我是标题一点击");
};
</script>
<style scoped>
.box {
width: 100px;
height: 100px;
background: #e1e1e1;
margin-right: 50px;
}
</style>
```
```javascript
export function creatTemplateReuse() {
let render;
const DefineTemplate = {
setup(_, { slots }) {
console.log(slots);
render = slots.default;
return () => {};
},
};
const useTemplate = (props) => {
return render(props);
};
return [DefineTemplate, useTemplate];
}
```
## 下面是复杂模版的效果代码请查看vue文件
Loading…
Cancel
Save