Vue无代码可视化项目
- 右侧栏配置——配置面板
-
- 右侧栏配置
-
- RightPanel.vue
- TextSetting.vue
- ImageSetting.vue
- ChartSetting.vue
- 右侧栏和中间区域联动
-
- TextSetting.vue
- ImageSetting.vue
- src/blocks/BlockRenderer.vue
- src/blocks/internal/TextBlock.vue
- src/blocks/internal/ImageBlock.vue
- src/types/block.ts
- src/mock/blocks.ts
- vee-validate处理动态表单
-
- package.json
- TextSetting.vue
右侧栏配置——配置面板
右侧栏配置
将components/RightPanel.vue 移到components/RightPanel目录下去
- src
- components
- RightPanel
- RightPanel.vue
- TextSetting.vue
- ChartSetting.vue
- ImageSetting.vue
- RightPanel
- components
RightPanel.vue
<script setup lang="ts">
// import {Lightning, Share } from '@icon-park/vue-next';
import {
storeToRefs} from 'pinia';
import {
computed } from 'vue';
import {
useEditorStore} from "@/stores/editor";
import ChartSetting from './ChartSetting.vue';
import ImageSetting from './ImageSetting.vue';
// import type {Block} from '@/types/block';
import TextSetting from './TextSetting.vue';
const editorStore=useEditorStore()
const {
selectedBlock}=storeToRefs(editorStore)
const blockRightPanel = computed(()=>{
if(!selectedBlock.value) return null;
switch(selectedBlock.value.type){
case 'text':
return TextSetting;
case 'image':
return ImageSetting;
case 'chart':
return ChartSetting;
default:
return null;
}
})
</script>
<template>
<div class="right-panel-wrapper" v-if="selectedBlock">
<div class="right-panel-left">
<!-- selectedBlock存在后才去走props传入数据的逻辑 -->
<!-- <TextRightPanel v-if="selectedBlock" :block="selectedBlock"/> -->
<component :is="blockRightPanel" :block="selectedBlock"/>
</div>
</div>
</template>
<style scoped>
.right-panel-wrapper {
display: flex;
height: 100%;
width: 280px;
background-color: #f5f5f5;
border: 1px solid #e8e8e8;
}
.right-panel-left{
display: flex;
padding:0 10px;
flex-direction: column;
align-items: center;
width: 100%;
height: 100%;
background-color: #e8e8e8;
}
</style>
这里,只有通过computed、watch、将他的api这些语法全部连接起来,它才会有一个响应式的表现,如果不这样做,只会在初始化进来的时候操作一次,后续的话,是不会再走的,这也是跟React很大的一个区别。之前探讨过更细颗粒度的更新,更细粒度的管理,在React中是通过信号的方式来进行状态的维护的。
const blockRightPanel = computed(()=>{
if(!selectedBlock.value) return null;
switch(selectedBlock.value.type){
case 'text':
return TextSetting;
case 'image':
return ImageSetting;
case 'chart':
return ChartSetting;
default:
return null;
}
})
TextSetting.vue
<script setup lang="ts">
import type {
TextBlock} from '@/types/block';
const props=defineProps<{
block:TextBlock
}>()
</script>
<template>
<input class="content" :value="props.block.props.content"/>
</template>
<style scoped>
.content{
width:100%;
}
</style>
ImageSetting.vue
<script setup lang="ts">
import type {
ImageBlock} from '@/types/block';
const props=defineProps<{
block:ImageBlock
}>()
</script>
<template>
<input class="content" :value="props.block.props.src"/>
</template>
<style scoped>
.content{
width:100%;
}
</style>
ChartSetting.vue
<script setup lang="ts"