web架构师编辑器内容-编辑器组件图层面板功能开发01-锁定隐藏功能的开发

news2024/11/27 21:05:36

我们这一部分主要是对最右侧图层面板功能进行剖析,完成对应的功能的开发:
在这里插入图片描述
每个图层都对应编辑器上面的元素,有多少个元素就对应多少个图层,主要的功能如下:

  1. 锁定功能:点击锁定,在编辑器中没法编辑对应的组件属性,再次点击是取消锁定,恢复到可编辑的模式
  2. 可见化:点击隐藏,在编辑器中消失,再次点击,进行展示
  3. 最外层图层也是可以进行点击,单击图层就是选中的效果。在编辑器上就是自动选中的效果。
  4. 图层的文字也可以进行修改,单击图层的文字,会切换到编辑模式,展示成input输入框,可以进行文字的修改。回车确认,点击esc退出,点击外部区域确定。
  5. 比较复杂的功能:拖动排序,按住这个按钮拖动以后,可以改变图层的顺序。

图层属性需求分析

图层锁定和隐藏/显示以及选中

图层和编辑器中的元素都是一一对应的,

// editor.ts
export interface EditorProps {
  // 供中间编辑器渲染的数组
  components: ComponentData[];
  // 当前编辑的是哪个元素,uuid
  currentElement: string
}

export interface ComponentData {
  // 这个元素的 属性,属性请详见下面
  props: Partial<AllComponentProps>;
  // id,uuid v4 生成
  id: string;
  // 业务组件库名称 l-text,l-image 等等
  name: 'l-text' | 'l-image' | 'l-shape';
}

在editor.ts中,components其实就是对应的图层,有对应的一些属性ComponentData,对于不同的状态,我们来添加对应的标识符来添加特定的标识符来表示他的状态即可。

  • 在editor.ts的store中的components添加更多的标识符

{

isLocked: boolean;
isHidden: boolean;
}

  • 点击按钮切换为不同的值,使用这个值在页面上做判断
  • 点击选中,设置 currentElement的值

图层名称编辑

  • 添加更多属性 - layerName
  • 点击图层名称的时候,在input和普通标签之间切换
  • 添加按钮响应 - 对于 esc 和 enter 键的响应
    • 可能抽象一个通用的 hooks函数 - useKeyPress,可以处理与键盘相关的事件
  • 点击到input外部区域的响应
    • 可能抽象一个通用的 hooks函数 - useClickOutside

拖动改变顺序

  • 最有难度的一个需求,涉及到一个较复杂的交互
  • 最终目的其实就是改变store中components数组的顺序

代码实现

// LayerList.vue
<ul :list="list" class="ant-list-items ant-list-border">
  <li class="ant-list-item" v-for="item in list" :key="item.id">
    <a-tooltip :title="item.isHidden ? '显示' : '隐藏'">
      <a-button shape="circle">
        <template v-slot:icon v-if="item.isHidden"
          ><EyeInvisibleOutlined />
        </template>
        <template v-slot:icon v-else><EyeOutlined /> </template>
      </a-button>
    </a-tooltip>
    <a-tooltip :title="item.isLocked ? '解锁' : '锁定'">
      <a-button shape="circle">
        <template v-slot:icon v-if="item.isLocked"
          ><LockOutlined />
        </template>
        <template v-slot:icon v-else><UnlockOutlined /> </template>
      </a-button>
    </a-tooltip>
    <span>{{ item.layerName }}</span>
  </li>
</ul>

// list的数据来源:在点击左侧组件模板库的时候,会在store中发射一个事件:
// Editor.vue
// 右侧图层设置组件(其中components就是store中的components)
//  const components = computed(() => store.state.editor.components);
<layer-list
   :list="components"
   :selectedId="currentElement && currentElement.id"
    @change="handleChange"
    @select="setActive"
 >
</layer-list>
// 点击左侧模板库某个组件触发的事件
const addItem = (component: any) => {
  store.commit('addComponent', component);
};
// editor.ts
addComponent: setDirtyWrapper((state, component: ComponentData) => {
      component.layerName = '图层' + (state.components.length + 1);
      state.components.push(component);
    }),
 
 // 比如点击大标题,在addItem中对应的参数如下:
 component: {
    // 通过pageUUid生成的唯一主键
 	id: '3c78b476-7a8d-4ad1-b944-9b163993595d',
 	// 动态需要渲染的组件
 	name: "l-text",
 	props: {
 		actionType: "";
		backgroundColor: "";
		borderColor: "#000";
		borderRadius: "0";
		borderStyle: "none";
		borderWidth: "0";
		boxShadow: "0 0 0 #000000";
		color: "#000000";
		fontFamily: "";
		fontSize: "30px";
		fontStyle: "normal";
		fontWeight: "bold";
		height: "";
		left: "0";
		lineHeight: "1";
		opacity: "1";
		paddingBottom: "0px";
		paddingLeft: "0px";
		paddingRight: "0px";
		paddingTop: "0px";
		position: "absolute";
		right: "0";
		tag: "h2";
		text: "大标题";
		textAlign: "left";
		textDecoration: "none";
		top: "0";
		url: "";
		width: "100px";
	}

最开始的样子
在这里插入图片描述
进行锁定隐藏操作

// 隐藏
<a-tooltip :title="item.isHidden ? '显示' : '隐藏'">
  <a-button
    shape="circle"
    @click.stop="handleChange(item.id, 'isHidden', !item.isHidden)"
  >
    <template v-slot:icon v-if="item.isHidden"
      ><EyeInvisibleOutlined />
    </template>
    <template v-slot:icon v-else><EyeOutlined /> </template>
  </a-button>
</a-tooltip>
// 锁定
<a-tooltip :title="item.isLocked ? '解锁' : '锁定'">
  <a-button
    shape="circle"
    @click.stop="handleChange(item.id, 'isLocked', !item.isLocked)"
  >
    <template v-slot:icon v-if="item.isLocked"
      ><LockOutlined />
    </template>
    <template v-slot:icon v-else><UnlockOutlined /> </template>
  </a-button>
</a-tooltip>

const handleChange = (id: string, key: string, value: boolean) => {
  const data = {
    id,
    key,
    value,
    isRoot: true,
  };
  context.emit("change", data);
};

// 最终在子组件中emit chang事件,父组件中触发该方法,
const handleChange = (e: any) => {
  console.log('event', e);
  store.commit('updateComponent', e);
};

// 对store中的updateComponent进行稍微的改造
// 原来的updateComponent
// 这个主要针对于最右侧面板设置区域中的属性设置进行更新的,改变的是props的值。
updateComponent(state, { key, value }) {
  const updatedComponent = state.components.find(
          (component) => component.id === state.currentElement
        ); 
  if(updatedComponent) {
    updatedComponent.props[key as keyof TextComponentProps] = value;
  }
}
// 现在的
updateComponent(state, { key, value, id, isRoot }) {
  const updatedComponent = state.components.find(
          (component) => component.id === (id || state.currentElement)
        ); 
  if(updatedComponent) {
    if(isRoot) {
      (updatedComponent as any)[key as string] = value;
    }
    updatedComponent.props[key as keyof TextComponentProps] = value;
  }
}
// 增加isRoot主要用来判断改变的是否是props中的某一项的值,我们进行的是展示隐藏,锁定不锁定的功能,所以直接改变key值就行:
export interface ComponentData {
  // 这个元素的 属性,属性请详见下面
  props: Partial<AllComponentProps>;
  // id,uuid v4 生成
  id: string;
  // 业务组件库名称 l-text,l-image 等等
  name: 'l-text' | 'l-image' | 'l-shape';
  // 图层是否隐藏
  isHidden?: boolean;
  // 图层是否锁定
  isLocked?: boolean;
  // 图层名称
  layerName?: string;
}

// Editor.vue
// 根据isLocked来判断右侧面板设置区域属性设置是否可以进行编辑
<a-tab-pane key="component" tab="属性设置" class="no-top-radius">
  <div v-if="currentElement">
    <edit-group
      v-if="!currentElement.isLocked"
      :props="currentElement.props"
      @change="handleChange"
    ></edit-group>
    <div v-else>
      <a-empty>
        <template #description>
          该元素已被锁定,无法被编辑
        </template>
      </a-empty>
    </div>
  </div>
  <pre>
    {{ currentElement && currentElement.props }}
  </pre>
</a-tab-pane>

// 根据hidden属性来控制中间画布区域是否可以进行显示与隐藏
// EditorWrapper.vue
:class="{ active: active, hidden: hidden }"

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1392909.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

git 常规操作及设置

git 常规操作及设置 Git是一个分布式版本控制系统&#xff0c;可以用来跟踪文件的修改历史并与其他人进行协作开发。下面是一些常见的Git操作及设置&#xff1a; 初始化仓库&#xff1a;使用命令git init在当前目录创建一个新的Git仓库。 克隆仓库&#xff1a;使用命令git clo…

web terminal - 如何在mac os上运行gotty

gotty可以让你使用web terminal的方式与环境进行交互&#xff0c;实现终端效果 假设你已经配置好了go环境&#xff0c;首先使用go get github.com/yudai/gotty命令获取可执行文件&#xff0c;默认会安装在$GOPATH/bin这个目录下&#xff0c;注意如果你的go版本比较高&#xff…

C++设计模式(李建忠)笔记3

C设计模式&#xff08;李建忠&#xff09; 本文是学习笔记&#xff0c;如有侵权&#xff0c;请联系删除。 参考链接 Youtube: C设计模式 Gtihub源码与PPT&#xff1a;https://github.com/ZachL1/Bilibili-plus 豆瓣: 设计模式–可复用面向对象软件的基础 文章目录 C设计模…

线性代数的学习和整理23:用EXCEL计算 向量/向量组的点乘 (内积) (建设ing)

目录 前言&#xff1a;EXCEL里的的向量相关计算公式 0.1 EXCEL里相关公式 0.2 先说结论&#xff1a;向量组的点乘公式和 向量组的点乘公式不一样 1 向量的点乘 (内积) 1.1 向量的点乘公式 1.2 EXCEL里向量点乘的计算 ​编辑 1.3 向量点乘的性质 1.3.1 内积的公式…

docker环境下mongo副本集的部署及异常修复

最近更换了办公地点。部署在本地docker环境里的mongo数据库不能使用了。原因是本地的ip地址变更。以前的mongo副本集的配置需要更新。处理完后&#xff0c;索性重新记录一下mongo副本集在docker中的部署流程。 mongo的事务及副本集 我们先了解一下什么是事务&#xff0c;事务…

LangChain新发布v0.1.0稳定版本有哪些新功能?

▼最近直播超级多&#xff0c;预约保你有收获 今晚直播&#xff1a;《LangChain 框架案例实战》 —1— 首个稳定版本 LangChain v0.1.0 LangChain v0.1.0 发布后&#xff0c;就不仅仅是一个开发框架了&#xff0c;而是一个开发者平台&#xff08;LLMOps&#xff09;&#xff0c…

css-盒子等样式学习

盒子居中&#xff0c;继承外层盒子的宽高 兼容性&#xff08;border-box&#xff09;将边框收到盒子内部 初始化div 不用管box-setting content-box 还原 创建为一个类 &#xff0c;让所有需要还原的类 进行继承 padding 用法表示margin上下左右边距 body 外边距&…

Python ❀ 使用代码实现API接口调用详解

文章目录 1. 工具准备1.1. requests代码包1.2. BurpSuite抓包工具 2. 操作过程2.1. 一个简单的请求2.1.1. Burp获取响应2.1.2. 转发获取响应 2.2. 构造GET类型URL参数2.3. 构造请求头部2.4. 构造POST类型payload数据 本文主要讲解常用API接口如何使用python实现。 API&#xff…

【白话机器学习的数学】读书笔记(3)学习分类(感知机、逻辑回归)

三、学习分类 1.分类的目的 找到一条线把白点和黑点分开。这条直线是使权重向量成为法线向量的直线。(解释见下图) 直线的表达式为&#xff1a; ω ⋅ x ∑ i 1 n ω i ⋅ x i 0 \omegax \sum_{i1}^n\omega_i x_i 0 ω⋅xi1∑n​ωi​⋅xi​0 ω \omega ω是权重向量权…

IIS 缓存, 更新后前端资源不能更新问题

解决办法: 通常只需要index.html 不缓存即可, 其他文件都是根据index.html 中的引用去加载; 正确的做法是在 站点下增加 web.config 文件, 内容如下: 我这个是因为目录下有个config.js 配置文件, 也不能缓存, 所以加了两个 <?xml version"1.0" encoding&quo…

2018年认证杯SPSSPRO杯数学建模D题(第一阶段)投篮的最佳出手点全过程文档及程序

2018年认证杯SPSSPRO杯数学建模 对于投篮最佳出手点的探究 D题 投篮的最佳出手点 原题再现&#xff1a; 影响投篮命中率的因素不仅仅有出手角度、球感、出手速度&#xff0c;还有出手点的选择。规范的投篮动作包含两膝微屈、重心落在两脚掌上、下肢蹬地发力、身体随之向前上…

迅为RK3588开发板编译 Buildroot单独编译图形化界面(打包镜像)

上面 Kernel/U-Boot/Recovery/Rootfs 各个部分的编译后&#xff0c;将打包要用到的所有固件移动到 rockdev 目录下&#xff0c;然后打包为完整的 update.img 镜像。 首先在 linux 源码目录下输入以下命令进入编译的 UI 界面&#xff0c;进入之后如下所示&#xff1a; ./buil…

nginx+lua配置,一个域名配置https,docker集群使用

没安装kua的先安装lua 没有resty.http模块的&#xff0c;许配置 nginxlua配置&#xff0c;一个域名配置https&#xff0c;docker集群使用&#xff0c;一个域名配置https管理整个集群 lua做转发&#xff08;方向代理&#xff09; 1、ad_load.lua文件 ngx.header.content_typ…

如何录制屏幕视频?让视频制作更简单!

随着数字化时代的来临&#xff0c;录制屏幕视频成为一种常见的传播和教学方式。无论是制作演示文稿、教学视频&#xff0c;还是记录游戏操作&#xff0c;屏幕录制为用户提供了强大而灵活的工具。可是您知道如何录制屏幕视频吗&#xff1f;本文将深入介绍两种常见的屏幕录制方法…

蓝桥杯备赛 day 3 —— 高精度(C/C++,零基础,配图)

目录 &#x1f308;前言&#xff1a; &#x1f4c1; 高精度的概念 &#x1f4c1; 高精度加法和其模板 &#x1f4c1; 高精度减法和其模板 &#x1f4c1; 高精度乘法和其模板 &#x1f4c1; 高精度除法和其模板 &#x1f4c1; 总结 &#x1f308;前言&#xff1a; 这篇文…

web开发学习笔记(8.java web后端开发基础知识)

1.使用spring开发的优势&#xff0c;spring发展到今天已经形成了一种开发生态圈&#xff0c;提供了若干个子项目&#xff0c;每个项目用于完成特定的功能。使用spring全家桶&#xff0c;可以做到很多事情&#xff0c;可以很方便的套用很多的组件。 2.pom构成 指定父工程 <p…

jeecgboot 前端bug or 后端 看图

无法显示文本 只能显示value 很恶心 如果用 varchar 就可以 不知道有没有别的方式 用int 解决 ,可能是我没有发现好的方法

尚无忧【无人共享空间 saas 系统源码】无人共享棋牌室系统源码共享自习室系统源码,共享茶室系统源码

可saas多开&#xff0c;非常方便&#xff0c;大大降低了上线成本 UNIAPPthinkphpmysql 独立开源&#xff01; 1、定位功能&#xff1a;可定位附近是否有店 2、能通过关键字搜索现有的店铺 3、个性轮播图展示&#xff0c;系统公告消息提醒 4、个性化功能展示&#xff0c;智能…

驱动开发--阻塞与非阻塞

一、五种IO模型------读写外设数据的方式 阻塞: 不能操作就睡觉 非阻塞&#xff1a;不能操作就返回错误 多路复用&#xff1a;委托中介监控 信号驱动&#xff1a;让内核如果能操作时发信号&#xff0c;在信号处理函数中操作 异步IO&#xff1a;向内核注册操作请求&#xff…

助力工业焊缝质量检测,基于YOLOv8【n/s/m/l/x】全系列参数模型开发构建工业焊接场景下钢材管道焊缝质量检测识别分析系统

焊接是一个不陌生但是对于开发来说相对小众的场景&#xff0c;在我们前面的博文开发实践中也有一些相关的实践&#xff0c;感兴趣的话可以自行移步阅读即可&#xff1a; 《轻量级模型YOLOv5-Lite基于自己的数据集【焊接质量检测】从零构建模型超详细教程》 《基于DeepLabV3Pl…