在图片网站中,通常是应用瀑布流的形式来显示图片,等宽度不等高,这样显得错落有致
明天 应用Vue3
实现一个瀑布流组件,并公布为一个npm
包
grid
布局- 反对响应式
参考自react-plock
1、window.matchMedia
window.matchMedia(mediaQueryString)
办法返回一个MediaQueryList
对象,示意指定css
媒体查问字符串的后果
其中参数mediaQueryString
示意CSS @media
规定的任何媒体查问选项,比方:
min-width
、min-height
、orientation
等
const media = window.matchMedia("(max-width: 850px)")
在MediaQueryList
对象中有两个属性:
matches
:返回查问后果,是一个布尔值media
:媒体查问的字符串
所以,依据matches
咱们就能够晓得是否命中以后的媒体查问选项
并且,咱们还能够通过addEventListener
监听mediaQuery
查问后果的变动
media.removeEventListener('change', () => { console.log(media.matches)});
2、瀑布流组件
响应式管制
依据屏幕大小确定图片的列数
export interface PropConfigType { gap: number[]; // 行列的间距 columns: number[]; // 不同媒体查问选项对应的列数 medias?: number[]; // 媒体查问选项}
import { reactive, onUnmounted } from 'vue';export function useMediaValues(config: PropConfigType) { const info = reactive({ columns: 1, gap: 1 }); const { columns, gap, media } = config; if (!media) { return setInfo(0); } // 循环查问medias const mediaQueries = media.map(media => window.matchMedia(`(min-width: ${media}px)`) ); const onSizeChange = () => { // 记录匹配到的哪一个media let matches = 0; mediaQueries.forEach(mediaQuery => { mediaQuery.matches && matches++; }); // 优先匹配前面的 const idx = Math.min(mediaQueries.length - 1, matches); setInfo(idx); }; onSizeChange(); // 监听查问后果 for (let mediaQuery of mediaQueries) { mediaQuery.addEventListener('change', onSizeChange); } onUnmounted(() => { for (let mediaQuery of mediaQueries) { mediaQuery.removeEventListener('change', onSizeChange); } }); function setInfo(idx: number) { info.columns = columns[idx]; info.gap = gap[idx]; return info; } return info;}
数据结构
info.columns
计算出瀑布流的数据结构,每列为一个数组,并存储到dataColumns
通过for
循环将fall-row
给渲染进去
当屏幕宽度变动时,会从新计算info.columns
,失去一个新的dataColumms
,渲染等到新的瀑布流界面
// fall-row组件<div :style="{ display: 'grid', rowGap: prop.gap, gridTemplateColumns: `minmax(0, 1fr)` }"> // 用户的内容通过插槽的模式增加 <slot></slot></div>
// water-fall 组件<div :style="{ display: 'grid', alignItems: 'start', gridColumnGap: info.gap + 'px', gridTemplateColumns: `repeat(${info.columns}, minmax(0, 1fr))` }"> <fallRow v-for="(columns, index) in dataColumns" :key="index" :gap="info.gap + 'px'" > // 此处为作用域插槽 <slot v-for="(src, index) in columns" :key="index" :src="src" ></slot> </fallRow></div>
- 通过作用域插槽将图片的
src
传递给父组件
3、应用
// 导入组件import { waterFall } from ...<waterFall :data="datasource" :config="{ columns: [1, 2, 3], gap: [24, 12, 6], medias: [640, 1024, 1280] }" v-slot="slotProps"> <img :src="slotProps.src" :style="{ width: '100%', height: 'auto' }" /></waterFall>
v-slot="slotProps"
拜访父组件的作用域,获取到src
进行显示
须要留神的是:columns
、gap
、medias
的个数要统一
公布npm
包
做好工程化后,就能够通过公布为npm
包
地址:vue3-plock
当初能够通过依赖命令来装置了
pnpm add vue3-plock
点击codesandbox查看线上的运行
源码曾经上传github,欢送start
参考:
- https://github.com/askides/react-plock
- https://developer.mozilla.org/zh-CN/docs/Web/API/Window/match...