前言
Isotope是一个用于网格布局的JavaScript库,它可以帮助你创建漂亮的、动态的网格布局。Isotope支持过滤、排序和动画效果,可以让你的网站更加生动有趣。目前,不仅JQuery支持Isotope,还有Vue、React、Angular等这些框架也有对其进行封装,做成了组件,方便引入项目并使用。但是随着Vue等框架版本的升级,这些组件许多没有继续更新,不支持高版本的前端框架。也就是说在高版本前端框架的项目中引入许多年前的组件,或多或少会出现报错导致无法使用。于是,UP在此实现如何在Vue2或Vue3项目中使用 Isotope(同位素)神器,挺简单的,全网独家实现。
Isotope官网:Isotope · Filter & sort magical layouts
一、示例代码
1.Vue2.X写法
(1)/src/views/Example/Isotope/index_vue2.vue
<template>
<div class="isotope_container">
<div class="isotope_filter_navbar">
<span data-filter="*" class="actived">All</span>
<span data-filter=".Vue">Vue</span>
<span data-filter=".React">React</span>
<span data-filter=".Angular">Angular</span>
</div>
<div class="isotope_filter_grid">
<div class="isotope_filter_grid_item Vue">
<img src="/images/404.png" alt="" />
<h1>HelloWorld! 1</h1>
</div>
<div class="isotope_filter_grid_item Vue">
<img src="/images/404.png" alt="" />
<h1>HelloWorld! 2</h1>
</div>
<div class="isotope_filter_grid_item Vue React">
<img src="/images/404.png" alt="" />
<h1>HelloWorld! 3</h1>
</div>
<div class="isotope_filter_grid_item Vue React">
<img src="/images/404.png" alt="" />
<h1>HelloWorld! 4</h1>
</div>
<div class="isotope_filter_grid_item React">
<img src="/images/404.png" alt="" />
<h1>HelloWorld! 5</h1>
</div>
<div class="isotope_filter_grid_item React">
<img src="/images/404.png" alt="" />
<h1>HelloWorld! 6</h1>
</div>
<div class="isotope_filter_grid_item Angular">
<img src="/images/404.png" alt="" />
<h1>HelloWorld! 7</h1>
</div>
<div class="isotope_filter_grid_item Angular">
<img src="/images/404.png" alt="" />
<h1>HelloWorld! 8</h1>
</div>
</div>
</div>
</template>
<script>
import Isotope from 'isotope-layout'
export default {
data() {
return {
// ...
}
},
mounted() {
this.handleInitIsotope()
},
methods: {
/**
* 初始化 Isotope 组件
*/
async handleInitIsotope() {
// 1.获取 isotope 导航条
const navbar = await document.querySelector('.isotope_filter_navbar')
// 2.实例化 isotope 对象
const isotope = await new Isotope(
'.isotope_filter_grid', // 容器
{
layoutMode: 'fitRows', // 布局模式
itemSelector: '.isotope_filter_grid_item', // 元素
}
)
// 3.为导航条注册点击事件
navbar.addEventListener('click', (e) => {
const {
target } = e
const filterOption = target.getAttribute('data-filter') // 筛选的类别
if (filterOption) {
// 给元素移除 actived 样式
navbar
.querySelectorAll('span')
.forEach(
(btn) => btn.classList.remove('actived')
)
// 给目标元素加上 actived 样式
target.classList.add('actived')
// 筛选
isotope.arrange({
filter: filterOption })
}
})
},
},
}
</script>
<style lang="less" scoped>
.isotope_container {
position: relative;
.isotope_filter_navbar {
display: flex;
align-items: center;
padding: 20px 20px 10px 20px;
span {
display: inline-block;
color: #999999;
font-family: gotham-book;
font-size: 24px;
font-weight: bold;
text-transform: uppercase;
margin: 0px 30px 0 0;
text-decoration: none;
transition: all 0.4s ease-in-out;
text-transform: capitalize; // 首字母大写
cursor: pointer;
&.actived {
color: #000;
}
&:hover {
color: #000;
}
}
}
.isotope_filter_grid {
.isotope_filter_grid_item {
display: flex;
width: 25vw;
height: 20vw;
img {
display: block;
flex: 1;
margin: 20px;
object-fit: cover;
background-color: #000;
}
h1 {
display: grid;
align-items: center;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
color: #fff;
font-weight: lighter;
}
}
}
}
</style>
2.Vue3.X写法
(1)/src/views/Example/Isotope/index_vue3.vue
<template>
<div class="isotope_container">
<div class="isotope_filter_navbar">
<span data-filter="*" class="actived">All</span>
<span data-filter=".Vue">Vue</span>
<span data-filter=".React">React</span>
<span data-filter=".Angular">Angular</span>
</div>
<div class="isotope_filter_grid">
<div class="isotope_filter_grid_item Vue">
<img src="/images/clients/404.png" alt="" />
<h1>HelloWorld! 1</h1>
</div>
<div class="isotope_filter_grid_item Vue">
<img src="/images/clients/404.png" alt="" />
<h1>HelloWorld! 2</h1>
</div>
<div class="isotope_filter_grid_item Vue React">
<img src="/images/clients/404.png" alt="" />
<h1>HelloWorld! 3</h1>
</div>
<div class="isotope_filter_grid_item Vue React">
<img src="/images/clients/404.png" alt="" />
<h1>HelloWorld! 4</h1>
</div>
<div class="isotope_filter_grid_item React">
<img src="/images/clients/404.png" alt="" />
<h1>HelloWorld! 5</h1>
</div>
<div class="isotope_filter_grid_item React">
<img src="/images/clients/404.png" alt="" />
<h1>HelloWorld! 6</h1>
</div>
<div class="isotope_filter_grid_item Angular">
<img src="/images/clients/404.png" alt="" />
<h1>HelloWorld! 7</h1>
</div>
<div class="isotope_filter_grid_item Angular">
<img src="/images/clients/404.png" alt="" />
<h1>HelloWorld! 8</h1>
</div>
</div>
</div>
</template>
<script>
import Isotope from 'isotope-layout'
export default {
data() {
return {
// ...
}
},
mounted() {
this.handleInitIsotope()
},
methods: {
async handleInitIsotope() {
// 1.获取 isotope 导航条
const navbar = await document.querySelector('.isotope_filter_navbar')
console.log('navbar =>', navbar)
// 2.实例化 isotope 对象
const isotope = await new Isotope(
'.isotope_filter_grid', // 容器
{
layoutMode: 'fitRows', // 布局模式
itemSelector: '.isotope_filter_grid_item', // 元素
}
)
console.log('isotope =>', isotope)
// 3.为导航条注册点击事件
navbar.addEventListener('click', (e) => {
const {
target } = e
console.log('target =>', target)
const filterOption = target.getAttribute('data-filter') // 筛选的类别
if (filterOption) {
// 给元素移除 actived 样式
navbar
.querySelectorAll('span')
.forEach(
(btn) => btn.classList.remove('actived')
)
// 给目标元素加上 actived 样式
target.classList.add('actived')
// 筛选
isotope.arrange({
filter: filterOption })
}
})
},
},
}
</script>
<style lang="less" scoped>
.isotope_container {
position: relative;
.isotope_filter_navbar {
display: flex;
align-items: center;
padding: 20px 20px 10px 20px;
span {
display: inline-block;
color: #999999;
font-family: gotham-book;
font-size: 24px;
font-weight: bold;
text-transform: uppercase;
margin: 0px 30px 0 0;
text-decoration: none;
transition: all 0.4s ease-in-out;
text-transform: capitalize; // 首字母大写
cursor: pointer;
&.actived {
color: #000;
}
&:hover {
color: #000;
}
}
}
.isotope_filter_grid {
.isotope_filter_grid_item {
position: relative;
display: flex;
width: 25vw;
height: 25vw;
text-align: center;
img {
display: block;
flex: 1;
margin: 20px;
object-fit: cover;
background-color: #000;
}
h1 {
display: grid;
align-items: center;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
color: #fff;
font-weight: lighter;
}
}
}
}
</style>
二、运行效果
(1)以上效果都是一样的