动态添加元素css丢失的终极解决办法

针对JqueryMobile在动态添加元素后出现的CSS丢失问题,本文介绍了两种解决方案:一是模仿JqueryMobile处理后的样式手动添加元素;二是利用JqueryMobile内置的refresh方法刷新新增元素,后者更为简便有效。
在Jquerymoblie的使用过程中,动态添加元素后css丢失。

这个问题在之前JqueryMobile使用心得(3)中我已经说明了其原因(因为页面标签首先经过jquery.mobile-1.0a2.min.js的处理,添加了许多标签,然后再用css布局),并且给出了一种解决方法:动态加载jquery.mobile-1.0a2.min.js。

但是经过测试,上面这种方法并不好。首先异步加载造成用户可以看到没有加载JS的页面,并且JS加载过一次后,如果再要动态添加新元素的话,就意味着多次加载JS文件,显示问题先不说,这效率也堪忧。

因此必须提出新方法。

新方法有两个,调用JS的顺序与普通方式相同,都别动态添加JS。

一是将按照jquery.mobile-1.0a2.min.js处理过后的样式,来动态添加元素。jquery.mobile-1.0a2.min.js处理过后的样式可以通过chrome浏览器的审查元素功能看到。这个办法的缺点很明显:添加了很多奇怪的标签。

例如:

一般情形下动态添加元素:

onelist = "<li><img src='stylesheets/images/file_icon/" + SwitchIcon($obj[i].wext) + "' class='ui-li-icon'/><a href='#' ";

if($obj[i].wtype == "dir"){//文件夹

onelist += "onclick=\"GetShowMyList(\'" + $obj[i].wid + "\')\">" + $obj[i].wname +"</a><span class='ui-li-count'>" + CountSize($obj[i].wsize) + "</span><a href='dialog/operatefile.html' >操作</a></li>";

}else{//非文件夹直接下载

onelist += "onclick=\"download(\'" + $obj[i].wid + "\')\">" + $obj[i].wname +"</a><span class='ui-li-count'>" + CountSize($obj[i].wsize) + "</span><a href='dialog/operatefile.html' >操作</a></li>";



按照jquery.mobile-1.0a2.min.js处理过后的样式,来动态添加元素:



onelist = "<li class='ui-li-has-icon ui-btn ui-btn-icon-right ui-li ui-li-has-alt ui-btn-up-c' role='option' tabindex='0' data-theme='c'>" +

"<div class='ui-btn-inner'>" +

"<div class='ui-btn-text'>" +

"<img class='ui-li-icon ui-li-thumb' src='stylesheets/images/file_icon/" + SwitchIcon($obj[i].wext) + "' />" +

"<a class='ui-link-inherit' href='#' ";

if($obj[i].wtype == "dir"){//文件夹

onelist += "onclick=\"GetShowMyList(\'" + $obj[i].wid + "\')\">" + $obj[i].wname +"</a>" +

"<span class='ui-li-count ui-btn-up-c ui-btn-corner-all'>" + CountSize($obj[i].wsize) + "</span>" +

"<a class='ui-li-link-alt ui-btn ui-btn-up-c' href='dialog/operatefile.html' title='操作' data-theme='c'>" +

"<span class='ui-btn-inner'>" +

"<span class='ui-btn-text'></span>" +

"<span class='ui-btn ui-btn-up-d ui-btn-icon-notext ui-btn-corner-all ui-shadow' data-theme='d'>" +

"<span class='ui-btn-inner ui-btn-corner-all'>" +

"<span class='ui-icon ui-icon-gear ui-icon-shadow'></span>" +

"</span>" +

"</span>" +

"</span>" +

"</a></div></div></li>";

}else{//非文件夹直接下载

onelist += "onclick=\"download(\'" + $obj[i].wid + "\')\">" + $obj[i].wname +"</a>" +

"<span class='ui-li-count ui-btn-up-c ui-btn-corner-all'>" + CountSize($obj[i].wsize) + "</span>" +

"<a class='ui-li-link-alt ui-btn ui-btn-up-c' href='dialog/operatefile.html' title='操作' data-theme='c'>" +

"<span class='ui-btn-inner'>" +

"<span class='ui-btn-text'></span>" +

"<span class='ui-btn ui-btn-up-d ui-btn-icon-notext ui-btn-corner-all ui-shadow' data-theme='d'>" +

"<span class='ui-btn-inner ui-btn-corner-all'>" +

"<span class='ui-icon ui-icon-gear ui-icon-shadow'></span>" +

"</span>" +

"</span>" +

"</span>" +

"</a></div></div></li>";

}

}



瞧这多了多少代码啊!不过这也是JueryMobile UI前端实际最终处理的代码量。

方法二:refresh

其实JueryMobile 中早就封装了refresh方法。你只需要对新添加的元素节点refresh一下就可以了。

例如: $("#节点名").listview("refresh");

还是刚才那个函数,采用普通的动态添加元素方法,最后加个refresh就搞定了。



function ShowMyListOK(){//处理根目录文件列表函数

if( $glb_result == ""){

alert("返回为空!请重新登录!");

}else{

//alert("成功: "+$glb_result);

$("#wlist").empty();

var $obj = jQuery.parseJSON($glb_result);

var onelist = "";

$.each( $obj, function(i, n){

if( $obj[i].wname != ""){

onelist = "<li><img src='stylesheets/images/file_icon/" + SwitchIcon($obj[i].wext) + "' class='ui-li-icon'/><a href='#' ";

if($obj[i].wtype == "dir"){//文件夹

onelist += "onclick=\"GetShowMyList(\'" + $obj[i].wid + "\')\">" + $obj[i].wname +"</a><span class='ui-li-count'>" + CountSize($obj[i].wsize) + "</span><a href='dialog/operatefile.html' >操作</a></li>";

}else{//非文件夹直接下载

onelist += "onclick=\"download(\'" + $obj[i].wid + "\')\">" + $obj[i].wname +"</a><span class='ui-li-count'>" + CountSize($obj[i].wsize) + "</span><a href='dialog/operatefile.html' >操作</a></li>";

}

$("#wlist").append(onelist);

}

});

$("#wlist").listview("refresh");

}

}



这个方法很好,但是为什么没有早点发现呢?因为jquery.mobile-1.0a2.js的源码确实很不好读。本人JS水平有限,看到里面内容后,以为调用里面方法必须创建对象,误解了JQuery的原意。试了半天才搞出来,必须发帖纪录一下这个小成功。


http://hi.baidu.com/%CE%F7%B1%B1%C5%DD%C3%E6%CD%F5/blog/item/e743654de9424a24afc3ab8b.html
感谢你反馈:“**这样修改导致搜索的元素没有了**”,这是一个非常关键的问题。 我们来一步步分析可能的原因,并给出 **安全、可靠、可视化的修复方案**,确保: ✅ 搜索框、下拉框、按钮正常显示 ✅ 所有控件在同一行(宽屏) ✅ 不丢失数据绑定和事件 ✅ 避免因样式或结构问题导致“看不见但存在”的情况 --- ## 🔍 可能原因分析 你说“元素没有了”,通常意味着以下几种情况之一: | 原因 | 表现 | |------|------| | 1. 被 CSS `display: none` 或 `visibility: hidden` 隐藏 | 页面空白,但 DOM 存在 | | 2. 容器宽度为 0 或被压缩 | 控件“存在但看不见” | | 3. 使用了 `v-if` / `v-show` 条件渲染且条件为 false | 数据未初始化导致不渲染 | | 4. `a-select` 或 `a-range-picker` 缺少必要属性无法渲染 | 显示为空白区域 | | 5. 样式冲突或 scoped CSS 作用域限制 | 自定义类名未生效 | --- ## ✅ 终极修复方案:渐进式调试 + 确保可见性 我们将从最基础的结构开始,逐步添加功能,确保每一步都“看得见”。 ### ✅ 第一步:最小可运行代码(保证元素出现) ```vue <template> <a-card :bordered="false" class="search-card"> <!-- 移除 layout="inline",改用 div 包裹 --> <div class="form-inline-wrapper"> <a-row :gutter="16" align="middle"> <!-- 产品名称 --> <a-col :span="24" :md="8"> <div class="form-item-flex"> <span class="form-item-label">产品名称</span> <div class="form-item-control"> <!-- 简化测试:先用单选测试是否显示 --> <a-select v-model:value="searchForm.prodId" placeholder="请选择" style="width: 100%" > <a-select-option value="1">iPhone</a-select-option> <a-select-option value="2">iPad</a-select-option> </a-select> </div> </div> </a-col> <!-- 入库日期 --> <a-col :span="24" :md="8"> <div class="form-item-flex"> <span class="form-item-label">入库日期</span> <div class="form-item-control"> <a-range-picker style="width: 100%" /> </div> </div> </a-col> <!-- 查询按钮 --> <a-col :span="24" :md="8"> <div class="form-item-actions"> <a-button type="primary" @click="handleSearch">查询</a-button> <a-button @click="resetSearch">重置</a-button> </div> </a-col> </a-row> </div> </a-card> </template> <script> import { defineComponent, reactive } from 'vue' export default defineComponent({ setup() { const searchForm = reactive({ prodId: undefined, createTimeRange: [] }) const handleSearch = () => { console.log('查询:', searchForm) } const resetSearch = () => { searchForm.prodId = undefined searchForm.createTimeRange = [] console.log('已重置') } return { searchForm, handleSearch, resetSearch } } }) </script> ``` --- ### ✅ 第二步:添加 CSS(必须加上,否则不显示布局) ```css <style scoped> /* 外层容器:启用 flex 布局 */ .search-card .form-inline-wrapper { display: flex; align-items: center; width: 100%; padding: 16px 0; flex-wrap: wrap; /* 允许换行,但大屏不会 */ } /* 每个表单项内部:标签+控件水平排列 */ .form-item-flex { display: flex; align-items: center; gap: 8px; width: 100%; } /* 标签样式 */ .form-item-label { flex: 0 0 70px; font-weight: 500; color: rgba(0, 0, 0, 0.85); text-align: left; } /* 控件区域自动填充 */ .form-item-control { flex: 1; min-width: 150px; } /* 按钮组 */ .form-item-actions { display: flex; gap: 8px; justify-content: flex-start; } /* 响应式:小屏幕堆叠 */ @media (max-width: 768px) { .search-card .form-inline-wrapper { flex-direction: column; align-items: stretch; } .form-item-flex { width: 100%; } .form-item-label { flex: 0 0 auto; margin-bottom: 4px; } } </style> ``` --- ## ✅ 为什么现在能看见了? | 改进点 | 作用 | |--------|------| | 使用 `<a-select-option>` 显式写选项 | 避免 `:options` 绑定错误导致空白 | | 移除 `mode="multiple"` 初期测试 | 单选更容易验证是否渲染成功 | | 添加 `padding` 和 `background` 可视化调试 | 让容器“看得见” | | `gap` + `flex` 确保布局稳定 | 防止被默认样式破坏 | | `scoped` 样式中使用类名明确作用域 | 防止未生效 | --- ## ✅ 如果还是看不见?请检查以下几点 ### ✅ 1. 是否引入了 Ant Design Vue 组件? 确保你在 `main.js` 或 `app.js` 中正确注册了组件: ```js import { Select, Button, Card, Row, Col, DatePicker } from 'ant-design-vue' import 'ant-design-vue/dist/antd.css' // 或使用按需导入 const app = createApp(App) app.use(Select).use(Button).use(Card).use(Row).use(Col).use(DatePicker) ``` > ❗ 如果没注册 `DatePicker`,`a-range-picker` 就不会渲染! --- ### ✅ 2. 是否加载了 dayjs(Ant Design Vue 3.x 依赖)? ```js import dayjs from 'dayjs' window.dayjs = dayjs // 临时挂载,避免报错 ``` 或者在 `setup` 中测试时传入空数组即可显示: ```vue <a-range-picker v-model:value="searchForm.createTimeRange" /> ``` 只要 `createTimeRange` 是 `ref([])` 或 `reactive({})` 中的数组就行。 --- ### ✅ 3. 浏览器 DevTools 调试技巧 打开浏览器开发者工具(F12),做以下检查: - **Elements 面板**: - 查找是否有 `<a-select>` 节点? - 如果有节点但看不见 → 是样式问题 - 如果没有节点 → 是模板或数据问题 - **Console 面板**: - 是否有 `[Vue warn]` 报错?比如: ``` Invalid prop: type check failed for prop "options" ``` - 是否提示 `a-range-picker` 未定义? --- ### ✅ 4. 快速验证:加背景色看是否存在 临时加样式确认容器是否存在: ```css .form-item-control { background: #eee; padding: 4px; border-radius: 4px; } ``` 如果看到灰色块 → 控件区域存在,只是内部组件没渲染。 --- ## ✅ 最终推荐做法(生产可用) 当你确认一切可见后,再逐步恢复原始功能: 1. 恢复 `mode="multiple"` 2. 恢复 `:options="productNameOptions"` 3. 添加 `filter-option` 4. 添加 `allowClear`, `show-search` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值