当前位置: 首页 > wzjs >正文

做网站推广优化哪家好目前最新的营销模式有哪些

做网站推广优化哪家好,目前最新的营销模式有哪些,可以直接用php做网站吗,学电商设计大概多少钱前言 有这么一个业务,主界面点击应用窗口进入声纳显示界面,声纳显示界面再通过按钮进入菜单界面,菜单界面有很多关于该声纳显示界面的设置项,比如量程,增益,时间显示,亮度,对比度等…

前言

有这么一个业务,主界面点击应用窗口进入声纳显示界面,声纳显示界面再通过按钮进入菜单界面,菜单界面有很多关于该声纳显示界面的设置项,比如量程,增益,时间显示,亮度,对比度等等,大概十几个设置。

有些数值类的设置还有子预览菜单,在子预览菜单里面通过滑条去设置数值,回到菜单后,设置会显示子预览菜单设置的数值。

声纳显示界面需要显示一些菜单的设置,比如量程,增益等等。

也就是大概这么一个页面关系,其中后面三个页面之间还有数据依赖的关系。

image-20250412120317482

由于菜单的设置项非常多,用传统的基于控件树的方法写起来代码量很大,而且美工时常改动菜单UI,容易影响界面代码,我当时自然而然的选择了AWTK特有的MVVM框架来完成菜单设置的显示逻辑。

一开始由于赶项目时间,我就直接在界面上使用了mvvm的app_conf功能,app_conf在AWTK-MVVM还有专门的model,使得不用写代码就能完成配置文件与多个界面间的数据联动与设置保存,十分贴心。

虽然这种方法能够快速实现功能,但是后期维护性极差,因为业务的配置key都写死在xml中,跟xml耦合。

比如这样的一个设置项:

<window v-model="m_home" name="filter_color"><view name="v_setting_color" x="175" y="0" w="387" h="183"><label name="title" x="9" y="10" w="58" h="28" text="Color"/><view name="view" x="34" y="58" w="359" h="112" children_layout="default(c=3,r=3)"><radio_button name="radio_button" v-data:value="{A.color==1}" text="color1"/><radio_button name="radio_button" v-data:value="{A.color==2}" text="color2"/><radio_button name="radio_button" v-data:value="{A.color==3}" text="color3"/><radio_button name="radio_button" v-data:value="{A.color==4}" text="color4"/><radio_button name="radio_button" v-data:value="{A.color==5}" text="color5"/><radio_button name="radio_button" v-data:value="{A.color==6}" text="color6"/><radio_button name="radio_button" v-data:value="{A.color==7}" text="color7"/><radio_button name="radio_button" v-data:value="{A.color==8}" text="color8"/></view></view>
</window>

实际业务是三种不同的声纳模式的设置菜单A, B, C, 三个设置菜单每个界面都有十几个行十几个设置项,加起来就是三十几个设置项,而且这些设置项的UI大都重复。

每个声纳的大部分属性还是各自独立的,也就是不同菜单的同一个设置,上面的color,A,B,C菜单都在用,A用A.color, B就是B.color,同样的key,父路径不同,这就导致没法用AWTK的component机制将这些设置项UI抽象出来复用,变成这样:

<window v-model="m_home" name="filter_color"><?include filename="comp_setting_color.xml" ?>
</window>

(话说AWTK的这个组件机制真的鸡肋,就是单纯的include替换,连个內部slot, 组件通信也没有)

如果用上述的绑死app_conf key的方式来做,后面一旦加了什么影响UI的新功能或者菜单风格更改,又要一个个菜单的去照着美工原型图去改,十分痛苦。

而且app_conf模型自身的命令绑定十分有限,稍微复杂一点的需求(比如点击按钮发送MQTT)就做不了,还是要结合自定义model的命令绑定或者传统的基于控件名索引的widget_on, 自己写函数

等到项目周期开始放缓,我决心把之前写死了配置key的几个菜单页面给重构了,改成用自定义model的自定义的属性来做数据绑定,在代码层面实现具体的选择菜单A,B,C的逻辑。

重构跟本文的逻辑不大,就不展开了,我在这边引出这些,是因为之前直接用app_conf有一个优点,就是不用关心页面之间数据联动的问题,awtk-mvvm内部代码自己会处理好,如果用自定义model, 就要写代码理清窗口导航的数据流通关系了,确保窗口退出时返回正确的设置数据给上一个页面。

实践

回到这个界面关系中,由于显示界面,设置菜单,子菜单都指向同一个对象的数据,考虑到三个页面后期可能的变动,我索性让三个页面都使用同一个model了。

我的目标是,弄清楚三个页面使用同一个model之后窗口的传参如何处理,才能实现子菜单设置时能够返回保存的数据。

抽象的例子如下,所有界面绑定一个叫m_home的model。

image-20250412170404083

sonar_page有bottom_lock,noise_limiter,pic_advance三个界面,每个界面都是在独立的子菜单中设置,设置完的结果会在sonar_page上显示。

<window v-model="m_home" name="sonar_page"><button name="button" x="272" y="320" w="100" h="36" v-on:click="{mreturn}" text="Back"/><label name="value" x="272" y="49" w="160" h="28" v-data:text="{value_int}"/><label name="key" x="272" y="104" w="160" h="28" v-data:text="{noise_limiter}" text="setting_item"/><label name="key" x="272" y="178" w="160" h="28" v-data:text="{pic_advance}" text="setting_item"/><button name="button1" x="101" y="49" w="100" h="36" text="Button"  v-on:click="{home_navigate, Args=string?page_name=bottom_lock}"/><button name="button1" x="101" y="104" w="100" h="36" text="Button" v-on:click="{home_navigate, Args=string?page_name=noise_limiter}"/><button name="button1" x="101" y="170" w="100" h="36" text="Button" v-on:click="{home_navigate, Args=string?page_name=pic_advance}"/>
</window>

一开始我犯了个错误,感觉一个页面重复建相同的Model,旧Model还要拷贝数据到新Model, 开销比较大,就把Model的创建和销毁搞成了引用计数的模式:

m_home_t *last_page_model = NULL;
m_home_t *g_home_ref = NULL;
static int g_home_ref_count = 0;m_home_t* m_home_create(navigator_request_t* req)
{m_home_t *home = NULL;if(!g_home_ref){home = TKMEM_ZALLOC(m_home_t);str_init(&home->pic_advance, 32);}else{home = g_home_ref;}g_home_ref = home;g_home_ref_count++;home->req = req;printf("m_home=%#x created, value: %d ref_count: %d\r\n", home, home->value_int, g_home_ref_count);return home;
}ret_t m_home_on_return(navigator_request_t* req, const value_t* result)
{m_home_t *home = g_home_ref;printf("set last model %p\r\n", home);emitter_dispatch_simple_event(EMITTER(home), EVT_PROPS_CHANGED);return RET_OK;
}ret_t m_home_mreturn(m_home_t *home)
{value_t v;navigator_request_on_result(home->req, &v);navigator_back();return RET_OK;
}ret_t m_home_destroy(m_home_t* home)
{g_home_ref_count--;if(g_home_ref_count == 0){str_reset(&home->pic_advance);TKMEM_FREE(home);g_home_ref = NULL;}printf("m_home=%#x destroyed\r\n", home);return RET_OK;  
}

但是后面发现子菜单上设置的值返回后无法在sonar_page上显示,查了半天,才发现m_home_on_return设置的其实是只跟当前界面有关的view_model,一旦返回这个页面就销毁了,根本影响不到上一个页面的view model。

image-20250412172638543

只好老实了,乖乖用默认的一个view一个model的传统构建方法,导航到新页面时把旧model作为参数, 传给新model,新model拷贝旧model的参数,退出页面时,旧model从新model加载数据。

实际业务是进页面从app_conf load数据,退页面save 数据到app_conf,然后旧model再从app_conf save数据的,这个例子里面省略了,直接copy对象来表示。

#include "m_home.h"
#include "awtk.h"
#include "mvvm/mvvm.h"
#include "mvvm/base/utils.h"m_home_t *last_page_model = NULL;
m_home_t *g_current_home_ref = NULL;void m_home_data_copy(m_home_t *ahome, m_home_t *bhome)
{ahome->value_int = bhome->value_int;str_set(&ahome->pic_advance, bhome->pic_advance.str);ahome->noise_limiter = bhome->noise_limiter;
}m_home_t* m_home_create(navigator_request_t* req)
{m_home_t *home = NULL;home = TKMEM_ZALLOC(m_home_t);str_init(&home->pic_advance, 32);m_home_t *last_model = tk_object_get_prop_pointer(TK_OBJECT(req), "last_model");if(last_model != NULL){m_home_data_copy(home, last_model);}g_current_home_ref = home;home->req = req;printf("m_home=%p created, value: %d last_model: %p\r\n", home, home->value_int, last_model);return home;
}ret_t m_home_destroy(m_home_t* home)
{str_reset(&home->pic_advance);TKMEM_FREE(home);g_current_home_ref = NULL;printf("m_home=%#x destroyed\r\n", home);return RET_OK;  
}ret_t m_home_on_return(navigator_request_t* req, const value_t* result)
{m_home_t *home = g_current_home_ref;m_home_t *last_model = tk_object_get_prop_pointer(TK_OBJECT(req), "last_model");printf("set last model %p\r\n", last_model);if(last_model != NULL){m_home_data_copy(last_model, home);emitter_dispatch_simple_event(EMITTER(last_model), EVT_PROPS_CHANGED);}return RET_OK;
}ret_t m_home_mreturn(m_home_t *home)
{value_t v;g_current_home_ref = home;navigator_request_on_result(home->req, &v);navigator_back();return RET_OK;
}ret_t m_home_to_navigate(m_home_t *home, const char *args)
{   tk_object_t *obj = object_default_create();tk_command_arguments_to_object(args, obj);const char *page_name = tk_object_get_prop_str(obj, "page_name");navigator_request_t* req = navigator_request_create(page_name, m_home_on_return);tk_object_set_prop_pointer(TK_OBJECT(req), "last_model", home);navigator_to_ex(req);tk_object_unref(TK_OBJECT(req));return RET_OK;
}ret_t m_home_set_prop_int(m_home_t *home, const char *args)
{tk_object_t *obj = object_default_create();tk_command_arguments_to_object(args, obj);const char *key = tk_object_get_prop_str(obj, "key");int32_t value = tk_object_get_prop_int(obj, "value", 0);if(tk_str_eq(key, "noise_limiter")){home->noise_limiter = value;}else{home->value_int = value;}printf("m_home_set_prop_int: %s = %d\r\n", key, value);TK_OBJECT_UNREF(obj);return RET_OBJECT_CHANGED;
}ret_t m_home_set_prop_str(m_home_t *home, const char *args)
{tk_object_t *obj = object_default_create();tk_command_arguments_to_object(args, obj);const char *key = tk_object_get_prop_str(obj, "key");const char *value = tk_object_get_prop_str(obj, "value");if(tk_str_eq(key, "pic_advance")){str_set(&home->pic_advance, value);printf("pic_advance set %s\r\n", home->pic_advance.str);}printf("m_home_set_prop_str: %s = %s\r\n", key, value);TK_OBJECT_UNREF(obj);return RET_OBJECT_CHANGED;
}

逻辑展示如下:

image-20250412174251820

懒得展开了,放上代码:

https://gitee.com/tracker647/awtk-practice/tree/master/awtk_mvvm_shared_model_return_test

效果:

image-20250412182014755

image-20250412182027504

附录:关于sub_view_model

虽然app_conf有一个sub_view_model的功能可以缓解不同object有一样的配置key的问题,但是实际业务里配置既有私有配置也有共通配置,共通配置还是混杂在私有配置里面的,配置文件的结构是这样:

shared_conf:{range_mode:1range_val:10
};
A:{color:1
}
B:{color:2
}
C:{color:3
}

设置项的位置表现上,是这种情况:

私有属性
共有属性
私有属性
共有属性

如果使用sub_view_model,就要另外给相关的配置包上带sub_view_model属性的view标签。

上面的例子就要包两次sub_view_model标签,对于之前业务那种设置项多的情况就是会建立很多个冗余的只用于限定设置作用域的model, 程序上十分不优雅且有不稳定的风险,我找了一圈AWTK库,没有找到在sub_view_model的标签作用域里引用父级model来索引到公共属性的方法,只好放弃。


文章转载自:

http://5HtjcySx.rqLqd.cn
http://1HJ9ttDM.rqLqd.cn
http://GFpW26Pz.rqLqd.cn
http://IFrOg8GL.rqLqd.cn
http://Beal6nr4.rqLqd.cn
http://TEfDogBH.rqLqd.cn
http://Vvta9WLf.rqLqd.cn
http://Og1gJkYe.rqLqd.cn
http://G5YIj0z7.rqLqd.cn
http://LiGFMrhv.rqLqd.cn
http://ehGa8ILX.rqLqd.cn
http://i9RvPMlY.rqLqd.cn
http://zoWntTnC.rqLqd.cn
http://3UGvaZwS.rqLqd.cn
http://rdUQKr4O.rqLqd.cn
http://v4biData.rqLqd.cn
http://O2ljCkpM.rqLqd.cn
http://WCkcZ6dQ.rqLqd.cn
http://j2R4rv7L.rqLqd.cn
http://jGpOrMHR.rqLqd.cn
http://4WnH8k3k.rqLqd.cn
http://ewg2MtWW.rqLqd.cn
http://AjRo4Sn9.rqLqd.cn
http://FnmZDVVK.rqLqd.cn
http://ajLPAkSM.rqLqd.cn
http://hWRSNjko.rqLqd.cn
http://a42ZuNHe.rqLqd.cn
http://2gatPWB1.rqLqd.cn
http://n9qpM8EU.rqLqd.cn
http://gtvZOKaE.rqLqd.cn
http://www.dtcms.com/wzjs/642701.html

相关文章:

  • 网站开发方向和移动开发方向那个好棋牌源码搭建论坛
  • 怀化网站优化加徽信xiala5效果好安卓开发
  • 网站开放培训结构设计网站推荐
  • 自己做返利网站宜春做网站 黑酷seo
  • 2002年做网站多少钱搜狗站长工具平台
  • 备案用的网站建设方案书怎么写电商网店代运营
  • dw做的网站链接wordpress 小米商城主题
  • 深圳网站建设公司企业名录搜索软件下载
  • 九江做网站哪家便宜做网站建设公司怎么选
  • 石大远程在线考试 《网页设计与网站建设》做网站能创业吗
  • 谷歌地图嵌入网站php班级网站建设
  • 网站域名注册地址wordpress副标题怎么写
  • 织梦网站installwordpress设置分享
  • 网站建设三原则清远住房和城乡建设部网站
  • 专业做财务公司网站直接网址登录wordpress
  • 网站建设实施方式wordpress4.7.2写文章
  • 网站推广页面设计中小企业网站建设与推广分析
  • 女生网站开发关于asp sql网站开发的书籍
  • 网站如何留住客户上海搜索引擎优化seo
  • 制作网站的视频教程tomcat做的网站打不开了
  • 网站备案太久了滕州网站建设培训
  • 济宁有做企业网站吗装修公司名字
  • 湖北住房和城乡建设厅官方网站三网合一网站报价
  • 做网站都需要准备什么软件上海网站建设开发哪家
  • 陕西省建设网官网综合服务中心知乎推广优化
  • 怎么在网站添加链接怎样做一个自己的网站
  • 自己做本地视频网站好人有好报
  • 大港油田建设官方网站平台搭建心得
  • 怎么做网站不会被屏蔽网站色彩
  • 服务器做视频网站网站会更改吗