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

淄博市住房和城乡建设厅网站/平台关键词排名优化

淄博市住房和城乡建设厅网站,平台关键词排名优化,wordpress搭建虚拟主机,个人可以做自媒体网站吗Promise 所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API&#xff0c…

Promise

所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。 —— ECMAScript 6 入门 阮一峰

场景

最近正在做的一个项目,包含"前台"与"后台", 前台是对数据的展示,后台是对用户等相关权限的管理,大到页面级别的权限,小到数据接口与菜单权限。整体是基于Oauth2.0做的一整套权限系统。

用户登录成功后,返回权限列表,一级权限包含当前用户可以访问到的子菜单:如下图:

管理员权限下,7个子系统图标会全部返回,实际情况返回多少菜单取决于当前用户权限。例如普通用户只能看到查看两个子系统,因为是动态可配置的,考虑到后期可能会增加子系统,所以子系统路由、名称、以及图像全部都来源于后台,通过后台管理进行配置。

按照正常的思路,后台获取菜单信息,然后循环渲染

//Home.vue
data() {return: {list:[]}
},
mounted() {this.GetMenuList();
},
methods:{GetMenuList() {...this.list = res.result //后台获取菜单列表}
}
复制代码
<div class='container'><div class="col_item" v-for="(item,index) in list" :key="index"><div class="content_img"><img :src="item.src" alt class="img_item"@click="routerLink(item.url)"></div><div class="content_title">{{ item.descritpion }}</div></div>
</div
复制代码

正常的公司网速下,页面加载效果如下图:

因为是动态获取子系统图标,并且页面响应式,也就是任何屏幕都会一屏显示,所以未知图像的width,height,宽高会自动计算。

谷歌开发工具调制3G网速下,仔细看:

为了模拟网速慢的情况,使用谷歌浏览器network设置了3G网速,可以看到页面加载时,背景的container是一个最小高度(动态计算),当图片加载成功并且循环显示后,块的高度撑搞,并且图片也是从0高度到实际高度,在弱网络情况下,体验一般。

考虑过通过固定宽高来解决,但是用不能满足响应式的一屏幕显示。

问题原因

因为template循环里,动态赋值图片src,所以此时的逻辑是先请求所有的数据列表(其中包含图像src字段),然后动态绑定:src,然后图片根据src才能加载,也就造成了弱网下的“延迟”问题。

根据原因分析,container容器预先写在template标签里,高度由图像撑开,container内部循环完成后,基本的骨架已经渲染完成,然后图像加载完成,container被撑高。

因此,如果先加载完成全部图片,再进行渲染是不是可以解决?

制定方案:

  • 1.通过image对象,用代码初始化load所有图像。
  • 2.通过appedChild一次性将内容插入container容器内

1.利用Promise,异步加载图像

修改代码如下:

//Home.vue
<script>
export default {data () {return {list: [], //存放后台返回的数据}},mounted() {this.GetMenuList();},methods:{GetMenuList() {...this.list = res.result //后台获取菜单列表,不负责渲染,只存储数据this.loadImages();},//图像加载方法loadItemImage(img) {return new Promise(resolve => {const image = new Image();//通过new Image对象 加载图像,本质是一个objectimage.src = img.imgUrl;   //指定srcimage.url = img.url;      //自定义添加一些字段暴漏到外部image.id = img.id;        //自定义添加一些字段暴漏到外部image.name = img.name;image.descritpion = img.descritpion;  //自定义添加一些字段暴漏到外部image.onload = () => resolve(image);  //加载图像image.onerror = () => resolve(image);image.onclick = () => {      //添加跳转点击事件this.routerLink(img.url, img.name, img.id);//跳转函数};image.className = "home_container_img_item";  //添加class属性});},//图像处理函数loadImages() {Promise.all(this.list.map(img => {return this.loadItemImage(img);})).then(imgs => { //imgs是list.map后生成的新数组,其中包含了n个image对象//得到已经加载完成的image数组,准备append到container容器});}}
}
</script>
复制代码

解读代码:首先后台返回数据后调用loadImages,对list进行map操作,每一项执行loadItemImage方法。

loadItemImage方法:return 了一个Promise实例,实例内部通过代码new Image,创建了一个image实例,其中src、onclick、onload、className是image原型上的属性和事件,因为实际需要点击图像跳转,所以在image上新增了一些自定义属性,供跳转使用。当图像load成功后resolve。循环操作后,map返回一个由image对象组成的新数组:

Promise.all当所有的图像加载完成后,准备进行append到container节点。

如何append?

参考了vue的思想,通过虚拟Dom操作映射到真实的Dom下,避免直接循环append操作dom,数据驱动视图:

新建virtualDom.js

//声明Dom类,用工厂方法进行封装:
class Dom {constructor(tags, attribute, children, event) {this.tags = tags;           // html标签字段,div p input..this.attribute = attribute; //class style 等html属性this.children = children;   //子节点数组this.event = event;         //事件对象}
};
// 创建虚拟DOM,返回虚拟节点(object)
export function createElement(tags, attribute, children, event = {}) {return new DOM(tags, attribute, children, event);//少数dom元素可能存在事件,如点击事件等,应对多数情况,设置event默认值{}
}
复制代码

新建render.js :


// render方法虚拟DOM映射到真实DOM
export function render(dom) {// 根据标签创建元素let el = document.createElement(dom.tags);// 遍历添加属性for (let key in dom.attribute) {// 设置属性的方法setAttr(el, key, dom.attribute[key]);}//添加事件for (let key in dom.event) {// 添加事件的方法AddEvent(el, key, dom.event[key]);}//针对于与大多数情况做了判断,本项目的上下文环境中有三种情况dom.children.forEach(child => {if (child instanceof Dom)          //如果子节点是Dom类,那么就继续向下递归child = render(child)else if (typeof child == 'string') //如果是文本那么就是文本节点child = document.createTextNode(child);elsechild = child;                   //其他html元素,本项目中是<img>元素// 添加到对应元素内el.appendChild(child);             //插入元素});return el;
}// 设置属性
export function setAttr(node, key, value) {switch (key) {case 'value':// node是一个input或者textarea就直接设置其value即可if (node.tagName.toLowerCase() === 'input' ||node.tagName.toLowerCase() === 'textarea') {node.value = value;} else {node.setAttribute(key, value);}break;case 'style':// 直接赋值行内样式node.style.cssText = value;break;default:node.setAttribute(key, value);break;}
}
//添加事件
function AddEvent(el, key, funcEvent) {switch (key) {case 'click':     //单击el.onclick = funcEvent;break;case 'dbClick'://..break;//...根据情况添加}
}
// 将元素插入到页面内
export function renderDom(el, target) {target.appendChild(el);
}
复制代码

准备映射虚拟dom:

映射: Object to dom.

或者说是: js to html.

本项目中的dom结果是这样的:

接着上面的代码

//Home.vue
import { createElement} from "common/utils/virtualDom.js";
import { render, renderDom} from "common/utils/render.js";...
//图像处理函数
loadImages() {Promise.all(this.list.map(img => {return this.loadItemImage(img);})).then(imgs => { //imgs是list.map后生成的新数组,其中包含了n个image对象//得到已经加载完成的image数组,准备append到container容器let element = []for(let img of imgs) {element.push(createElement('div', {class: 'home_container_col_item'},[ //创建div,子元素img就是每一个img对象createElement('div',{class: 'home_container_content_img'},[img]), createElement(//创建文本字,添加点击事件'div',{class:'home_container_content_title'},[img.descritpion],{click:()=>{this.routerLink(img.url, img.name, img.id)}}),]))}//createElement的四个参数依次写入//上边的树就是下面这种结构// {//   tags: "div",//   attribute: {//     class: "home_container_col_item"//   },//   children: [//     {//       tags: "div",//       attribute: {//         class: "home_container_content_img"//       },//       children: [image]//     },//     {//       tags: "div",//       attribute: {//         class: "home_container_content_title"//       },//       children: ['xxx子系统']//     },//   ]// };//然后循环push到数组里。//...接上//containerlet virtualDom = createElement("div",{ class: "home_container_menu_row" },element);let el = render(virtualDom); // 渲染虚拟DOM得到真实的DOM结构renderDom(el, document.getElementById("home_container_center"));//挂载dom});
}
复制代码

上面的dom结构只是一个例子,实际情况要根据自己的结构编写。

看实际项目效果:

菜单动态获取,container并没有高度被撑开的情况,页面加载,container为空,后台返回数据后,container呈现

参考文章:

Vue-节点、树以及虚拟-DOM

vue核心之虚拟DOM(vdom)

转载于:https://juejin.im/post/5c9b1c5b518825328474050b

http://www.lbrq.cn/news/764425.html

相关文章:

  • 东莞网站建设上科/商丘seo博客
  • 做期货看那个网站比较专业/赣州seo排名
  • app设计理念怎么写/网站建设网络推广seo
  • 建设网站的技术手段/免费推广平台有哪些
  • 建设银行信用卡网站查询/网络优化公司排名
  • 文章网站后台/西安企业做网站
  • html5开发wap网站/百度网盘客服人工电话
  • 给客户做网站需要提供/安阳企业网站优化外包
  • 网站设计专家/网络优化公司哪家好
  • 怎样靠做网站赚钱吗/下载优化大师安装桌面
  • 做视频网站用什么格式好/网站推广代理
  • 网站建设找谁做/网站优化推广方案
  • 网站建设推广公司哪家权威/如何利用网络广告进行推广
  • 购物网站开发模板/steam交易链接在哪里看
  • 做推广必须知道的网站/注册域名费用一般多少钱
  • 小企业网站建设平台/网站排名优化培训课程
  • 水果零售电子商务网站综合评价与建设研究/推广运营怎么做
  • 做网站要提供什么/推广软件一键发送
  • 企业网站首页设计评价/百度竞价托管靠谱吗
  • 苏州做网站需要多少钱/搜狐财经峰会
  • 宜昌本地网站建设/网络营销公司经营范围
  • 企业做网站上海/营销工具
  • 青岛高端网站开发公司/菏泽seo
  • 微信网站建设热线/网络营销的三种方式
  • 阿里巴巴网站详情页怎么做的/郑州模板网站建设
  • 家庭服务网站的营销策略/常见的网络营销推广方式有哪些
  • 给网站做导流/宁波网站制作优化服务公司
  • 做网站骗老外的钱/江苏短视频seo搜索
  • 装修公司做推广网站怎么弄/天猫seo搜索优化
  • 做国际网站有用/360搜索推广
  • 亚马逊品牌权力重构:第三方卖家崛起下的竞争生态与系统性应对框架
  • 记录一些奇奇怪怪的面试题
  • week1-[分支嵌套]公因数
  • ZigBee入门与提高(3)—— ZigBee协议初识
  • 【报错解决】Conda - Downloaded bytes did not match Content-Length
  • 搜索引擎核心机制解析