QFramework (v0.1.x)入门学习(九)MVP入门(1)

MVC:

 

 

MVP: 绑定  model 层和 view 层

 

1.  model 层定义 ReactiveProperty 变量

public class TodoItem
{
    public BoolReactiveProperty Completed = new BoolReactiveProperty (false);
    public StringReactiveProperty Content = new StringReactiveProperty (string.Empty);
}

2. view 层使用 ,更新 Content 的值


            BtnUpdate.onClick.AddListener(() =>
            {
                mSelectedItemModel.Content.Value = InputField.text;
            });

3.订阅,例如 mModel.Content.Value 值发生变化 ,view层 随即更新

    mModel.Content.Subscribe(content =>
            {
                Content.text = content;
            });

 

代码示例:

using QF;
using QF.Extensions;
using QF.Res;
using QFramework;
using QFramework.Afra;
using System.Collections;
using System.Collections.Generic;
using UniRx;
using UnityEngine;

/// <summary>
/// TodoApp
/// 1. 完成,未完成
/// 2. 列表/待办事项
/// 3. 增加,删除,更改待办事项
/// 
/// 有一个列表,列表里多个待办事项, 待办事项能够完成未完成 ,内容
/// </summary>
public class TodoListApp : MonoBehaviour
{
    public TodoList mModel;
    void Start()
    {
        ResMgr.Init();
        UIMgr.SetResolution(1080, 1920, 0);
        mModel = TodoList.Load();
        // 打开 panel
        UIMgr.OpenPanel<UITodoList>(new UITodoListData()
        {
            // 将Model层数据 传递到 UIPanel 控制层
            Model = mModel
        }) ;
    }
    private void OnApplicationQuit()
    {
        mModel.Save();
    }
}

public class TodoList
{
    public List<TodoItem> m_TodoItems = new List<TodoItem>() {};
    // Json 反序列化(读取)
    public static  TodoList Load()
    {
        var jsonContent = PlayerPrefs.GetString("TodoListData1", string.Empty);
        return jsonContent.IsNullOrEmpty() ? new TodoList(): jsonContent.FromJson<TodoList>();
    }
    //Json  序列化(写入)
    public void Save()
    {
        PlayerPrefs.SetString("TodoListData1", this.ToJson());
    }

}
public class TodoItem
{
    public BoolReactiveProperty Completed = new BoolReactiveProperty (false);
    public StringReactiveProperty Content = new StringReactiveProperty (string.Empty);
}
/****************************************************************************
 * 2019.10 DESKTOP-SF453R4
 ****************************************************************************/

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using QFramework;
using QF.Extensions;
using UniRx;

namespace QFramework.Afra
{

    public enum UIInputContentState
    {
        Create,
        Modify,
    }

    public partial class UIInputContent : UIElement
    {
        public ReactiveProperty<UIInputContentState> State = new UniRx.ReactiveProperty<UIInputContentState>(UIInputContentState.Create);
 
        TodoItem mSelectedItemModel;
        TodoList mTodoListModel;
        public void Init(TodoList todoListModel)
        {
            mTodoListModel = todoListModel;
        }
        public void ModifyState(TodoItem selectedItemModel)
        {
            mSelectedItemModel = selectedItemModel;
            State.Value = UIInputContentState.Modify;
            InputField.text = selectedItemModel.Content.Value;
           
        }

        private void Awake()
        {
            State.Subscribe(State =>
            {
                if(State == UIInputContentState.Create)
                {
                    BtnUpdate.Hide();
                    BtnCancel.Hide();
                    InputField.text = string.Empty;
                }
                else
                {
                    BtnUpdate.Show();
                    BtnUpdate.interactable = false;
                    BtnCancel.Show();
                }
            });



            BtnUpdate.onClick.AddListener(() =>
            {
                mSelectedItemModel.Content.Value = InputField.text;
                State.Value = UIInputContentState.Create;
            });

            BtnCancel.onClick.AddListener(()=>{ 
                State.Value = UIInputContentState.Create; 
            });

            InputField.onValueChanged.AddListener(content =>
            {
                if (State.Value == UIInputContentState.Modify)
                {
                    if (BtnUpdate.interactable && content == mSelectedItemModel.Content.Value)
                    {
                        BtnUpdate.interactable = false;
                    }
                    else if (!BtnUpdate.interactable && content != mSelectedItemModel.Content.Value)
                    {
                        BtnUpdate.interactable = true;
                    }
                }

            });
            // 监听输入完成
            InputField.onEndEdit.AddListener(content =>
            {
                if (State.Value == UIInputContentState.Create)
                {
                    if (Input.GetKeyDown(KeyCode.Return))
                    {
                        var addedItem = new TodoItem();
                        addedItem.Content.Value = content;
                        addedItem.Completed.Value = false;
                        SendMsg(new OnTodoItemAddedMsg(addedItem));
                    }
                    InputField.text = string.Empty;
                }
            });
        }

        protected override void OnBeforeDestroy()
        {
        }
    }
}
/****************************************************************************
 * 2019.10 PS2019HINRKUYZ
 ****************************************************************************/

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using QFramework;
using QF.Extensions;
using UniRx;

namespace QFramework.Afra
{
	public partial class UITodoItem : UIElement
	{
        TodoItem mModel;

        // 控制层到显示层
        public void Init(TodoItem model)
        {
            mModel = model;

            Completed.isOn = mModel.Completed.Value;

            Completed.onValueChanged.AddListener(on=> {
                if (on)
                {
                    mModel.Completed.Value = on;
                    this.DestroyGameObj();
                }
            });
            Button.onClick.AddListener(() =>
            {
                Debug.Log("clicked");
                SendMsg(new OnTodoItemSelectedMsg(mModel));
            });

            mModel.Content.Subscribe(content =>
            {
                Content.text = content;

            });

        }
        private void Awake()
		{
		}

		protected override void OnBeforeDestroy()
		{
		}
    }
}

 

<think>好的,我现在需要解决用户提出的关于Lucky Excel行高自适应不生效的问题。首先,我需要了解Lucky Excel的基本情况,它是什么,主要功能有哪些。Lucky Excel是一个开源的JavaScript库,用于在网页中嵌入类似Excel的电子表格功能,支持导入导出Excel文件,并且提供一些交互功能。用户可能在使用过程中遇到了行高无法根据内容自动调整的问题。 接下来,我应该考虑可能的原因。根据经验,类似的问题可能有多种原因,比如配置错误、内容特殊性、版本问题、浏览器兼容性或者事件处理未正确触发等。我需要逐一分析这些可能性,并给出相应的解决方案。 首先,配置问题。用户是否正确地启用了自动行高配置?我需要查阅Lucky Excel的文档,确认是否有相关的配置项,比如autoRowHeight或类似的参数。如果用户没有正确配置,可能需要指导他们如何设置。 其次,内容特殊性。如果单元格内容包含换行符、特殊符或者过长的文本,可能导致自动行高计算不准确。这时候可能需要手动调整行高,或者检查内容是否合理。 版本问题也是一个常见因素。用户可能在使用旧版本的Lucky Excel,而自动行高的功能在后续版本中才被修复或优化。建议用户升级到最新版本,查看问题是否解决。 浏览器兼容性方面,不同的浏览器对CSS和JavaScript的支持可能有差异,导致行高计算错误。用户需要测试不同的浏览器,确认是否存在兼容性问题,并检查控制台是否有报错信息。 事件触发的问题:自动行高可能需要用户执行某些操作(如双击行边栏)才会触发。用户是否进行了正确的操作?或者是否需要调用API来手动触发自适应功能? 另外,可能还需要考虑CSS样式的冲突。如果父容器或相关元素的CSS限制了行高,比如设置了固定的高度或overflow属性,可能会影响自适应效果。用户需要检查CSS样式,确保没有冲突。 还有,异步加载数据的情况。如果数据是动态加载的,可能在渲染时数据还未完全加载,导致行高计算不准确。这时候需要在数据加载完成后,手动触发自适应功能。 最后,如果以上方法都无法解决,建议用户查阅官方文档、GitHub issues或者社区讨论,看看是否有其他用户遇到类似问题,或者直接向开发者提交问题报告。 现在需要将这些思路整理成结构化的回答,分步骤帮助用户排查问题。需要确保语言清晰,步骤明确,用户能够逐步检查和尝试解决。同时,要使用中文,避免技术术语过于复杂,让用户容易理解。</think>关于Lucky Excel行高自适应不生效的问题,以下是逐步排查与解决方案: --- ### 一、检查配置参数 1. **确认是否启用自适应** Lucky Excel需通过配置项开启行高自适应。检查代码中是否设置: ```javascript luckysheet.create({ container: 'container', autoRowHeight: true // 确保此参数为true }); ``` 2. **动态更新配置(若初始化未设置)** 若已初始化表格,可通过API更新: ```javascript luckysheet.setConfig({ autoRowHeight: true }); ``` --- ### 二、内容特殊性排查 1. **换行符与长文本** - 单元格内容含`\n`时,需设置允许换行: ```javascript luckysheet.setCellValue(row, col, { v: "文本\n换行", m: "文本\n换行", ct: { fa: "@", t: "s" } }); ``` - 若文本过长超出容器宽度,需同时检查列宽是否足够。 2. **富文本或公式影响** 单元格包含富文本(如混合体样式)或公式时,可能干扰计算。尝试使用纯文本测试。 --- ### 三、版本与兼容性 1. **升级到最新版本** 旧版本可能存在行高计算Bug。通过npm或CDN更新: ```bash npm install luckyexcel ``` 2. **浏览器控制台检查** - 打开浏览器开发者工具(F12),查看Console是否有报错(如`autoRowHeight is not a function`)。 - 测试Chrome/Firefox/Edge等主流浏览器,排除兼容性问题。 --- ### 四、手动触发自适应 1. **通过API强制刷新行高** 调用以下方法尝试: ```javascript luckysheet.refreshRowHeight(row); // 刷新单行 luckysheet.refreshRowHeightAll(); // 刷新所有行 ``` 2. **模拟用户操作** 双击行号右侧的分隔线(类似Excel行为),观察是否能触发自适应。 --- ### 五、CSS样式冲突 1. **检查父容器样式** 确保表格容器未限制高度或设置`overflow:hidden`: ```css #container { width: 100%; height: 600px; /* 需明确高度 */ overflow: visible; /* 允许内容扩展 */ } ``` 2. **覆盖默认行高样式** 若存在`!important`标记的CSS,可能覆盖计算值。例如: ```css .luckysheet .row-header { height: auto !important; /* 移除固定行高 */ } ``` --- ### 六、异步数据处理 1. **延迟加载后刷新** 若数据通过Ajax异步加载,在回调中触发自适应: ```javascript fetchData().then(data => { luckysheet.loadData(data); luckysheet.refreshRowHeightAll(); }); ``` --- ### 七、官方资源与社区支持 1. **查阅文档与Issues** - [LuckySheet官方文档](https://mengshukeji.github.io/LuckysheetDocs/guide/) - [GitHub Issues](https://github.com/mengshukeji/Luckysheet/issues) 搜索“autoRowHeight”。 2. **提交问题反馈** 提供复现代码、版本号、浏览器环境及错误截图,加速问题定位。 --- 通过以上步骤排查,90%以上的行高问题可解决。若仍无效,建议提供具体代码片段和复现步骤,进一步分析。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值