まず、アイデアやレンダリングの分析
カスケード効果を達成するVUEを使用すると、ネットワークの画像をロードするには、ドロップダウンリフレッシュしながらECLACには、より多くの機能的効果をアップロードします。そして、これらの効果を実現するために、アイデアを撫で:
- ラベルの効果を示すデータのロードの順序は、順次追加されます。
- 絶対位置モードを選択滝を達成するためにどの方法を選択します。
- 重要な問題:各画像の幅と高さが異なっており、必要なすべての画像幅に一致する滝、幾何学的なスケーリングの幅と高さ。そして絵は、非同期遅延がロードされるため。以下の場合には各項目欄の画像は良好な絶対位置でないピクチャの高さを知りません。これにより、ページをレンダリングする前に、すべての画像の高さをつかむ、問題を解決するための重要なポイントです!ここでは、一時的な変数の高さを介してすべての写真があったか否かを計算するのに加えて、先に幅と高さの絵のために事前に読み込んだ画像を経由して、ImageクラスでJSを使用することを選択しました。すべての画像の高さを取得すると、ページのレンダリングを開始します。
- ページをレンダリングした後、画像は、サイクルは、各ボックス項目の絶対位置を設定を開始するために、ボックスの高さを計算するためにすべてのボックスを取得します。
- ページをレンダリングする場合、現象が点滅。どのようにこの問題を解決するには?ここでは、アニメーションのスタイルを持ちます。最初に読み込まれた場合は、または感情の少しちらつきがあるでしょう。
- 次に、ドロップダウンリフレッシュされ、LAC上でより多くの効果をアップロードし、ここで素晴らしいvant部品PullRefresh一覧や達成するためのコンポーネントの組み合わせがあります。
図効果の動的ルック:
静的なスクリーンショット:
第二に、特定の実装手順
2.1、ページデザイン、テストデータの準備。
ローカルプロジェクトのパブリックフォルダ上のJSONファイルのデータを準備します。vue3.x.ローカルテストデータは、パブリックフォルダに配置する必要があります、データを要求するネットワーク要求、ネットワーク要求に、新しいaxiosの依存関係を追加します。ショットの一部、およびキーコード:
//数据请求 getDataList(){ this.$axios.get("/json/dataList.json").then((res)=>{ let list = res.data.data ? res.data.data: []; if (list.length > 0){ //从list中取pageSize条数据出来 var tempList = []; for (let i = 0; i < this.pageSize; i++){ if (list.length > 0){ let tempIndex = parseInt(Math.random() * 1000) % list.length; tempList.push(list[tempIndex]); list.splice(tempIndex, 1); } } this.loadImagesHeight(tempList); //模拟预加载图片,获取图片高度 } else { this.loadImagesHeight(list); } }).catch((res)=>{ console.log("..fail: ", res); this.$toast.clear(); this.isLoading = false; //下拉刷新请求完成 this.loading = false; //上拉加载更多请求完成 }) },
2.2、预加载图片,存储图片高度
获取数据后,遍历数据数组,预加载图片,计算图片缩放后的高度,存储起来。同时由于图片加载是异步加载,所以用变量计数,当最后一个图片加载完成后,开始渲染页面。
loadImagesHeight(list){ var count = 0; //用来计数,表示是否所有图片高度已经获取 list.forEach((item, index)=>{ //创建图片对象,加载图片,计算图片高度 var img = new Image(); img.src = item.cover; img.onload = img.onerror = (e)=>{ count++; if (e.type == 'load'){ //图片加载成功 //计算图片缩放后的高度:图片原高度/原宽度 = 缩放后高度/缩放后宽度 list[index].imgHeight = Math.round(img.height * this.boxWidth / img.width); // console.log('index: ', index, ', load suc, imgHeiht: ', list[index].imgHeight); } else{ //图片加载失败,给一个默认高度50 list[index].imgHeight = 50; console.log("index: ", index, ", 加载报错:", e); } //加载完成最后一个图片高度,开始下一步数据处理 if (count == list.length){ this.resolveDataList(list); } } }) },
2.3、渲染页面,设置绝对定位
所有图片通过预加载获取图片高度后,开始渲染页面。然后遍历所有图片所在盒子标签,获取盒子高度,设置每个盒子的绝对定位。
resolveDataList(list){ //处理数据 //下拉刷新,清空原数据 if (this.pageIndex <= 1){ this.itemCount = 0; this.dataList = []; this.lastRowHeights = [0, 0]; //存储每列的最后一行高度清0 } if (list.length >= this.pageSize){ this.pageIndex++; //还有下一页 } else{ this.finished = true; //当前tab类型下所有数据已经加载完成 } //合并新老两个数组数据 this.dataList = [...this.dataList, ...list]; //判断页面是否有数据 this.haveData = this.dataList.length > 0 ? 2 : 1; this.isLoading = false; //下拉刷新请求完成 this.loading = false; //上拉加载更多请求完成 console.log("...datalist: ", this.dataList); console.log("...this.isLoading: ", this.isLoading) this.$nextTick(()=>{ setTimeout(()=>{ //渲染完成,计算每个item宽高,设置标签坐标定位 this.setItemElementPosition(); this.isLoading = false; //下拉刷新请求完成 this.loading = false; //上拉加载更多请求完成 }, 1000) }); }, //获取每个item标签高度,设置item的定位 setItemElementPosition(){ let parentEle = document.getElementById('data-list-box'); let boxEles = parentEle.getElementsByClassName("data-item"); for (let i = this.itemCount; i < boxEles.length; i++){ let tempEle = boxEles[i]; //上一个标签最小高度的列索引 let curColIndex = this.getMinHeightIndex(this.lastRowHeights); let boxTop = this.lastRowHeights[curColIndex] + this.boxMargin; let boxLeft = curColIndex * (this.boxWidth + this.boxMargin) + this.boxMargin; tempEle.style.left = boxLeft + 'px'; tempEle.style.top = boxTop + 'px'; this.lastRowHeights[curColIndex] = boxTop + tempEle.offsetHeight; // console.log('i = ', i, ', boxTop: ', boxTop, ', eleHeight: ', tempEle.offsetHeight); } this.itemCount = boxEles.length; //修改父级标签的高度 let maxHeight = Math.max.apply(null, this.lastRowHeights); parentEle.style.height = maxHeight + 'px'; this.$toast.clear(); console.log("...boxEles: ", boxEles.length, ", maxH: ", maxHeight); },
2.4、其他说明
其他页面中如下拉刷新,和上拉加载更多等功能,使用了有赞的组件库中的PullRefresh 和 List这一套组合组件。感觉效果挺棒的,使用步骤也简单。另外就是在页面渲染时,会出现页面闪烁的现象,后面使用了一个css动画处理了这个现象,效果好了很多。但是在第一次加载的时候,还是有轻微的闪烁现象。等后面找到更好的方法,再更新。
完整效果DEMO地址:https://github.com/xiaotanit/tan_vue/blob/master/src/views/PageWaterFall.vue