vue中key的作用及案例

1、key的作用

假设现在有一个需求,在页面循环data中的数组。

 <div id="app">
    <ul>
      <li v-for="(item, i) in list">
        <input type="checkbox"> {{item.name}}
      </li>
    </ul>
<script>
    var vm = new Vue({
      el: '#app',
      data: {
        list: [
          { id: 1, name: '诡秘之主' },
          { id: 2, name: '诛仙' },
          { id: 3, name: '惊悚乐园' }
        ]
      }
    });
  </script>
  </div>

写完之后,需求进行升级。要求可以手动在列表的头部添加一本书。
HTML中添加如下代码:

<form>
  <input type="text" v-model="name">
  <input type="submit" value="添加" @click.prevent="add">
</form>

因为我们需要获取输入框中输入的书籍名称,所以这里使用了v-model数据双向绑定。

那么就需要在vue实例中的data属性中添加一个name属性

data: {
    list: [
        { id: 1, name: '诡秘之主' },
        { id: 2, name: '诛仙' },
        { id: 3, name: '惊悚乐园' }
    ],
    name:""
}

接下来在vue实例的methods属性中实现添加方法。

methods: {
    add(){
        let newPerson = {name: this.name, id: this.list.length + 1};
        this.list.unshift(newPerson);
        this.name = "";
    }
}

好,需求已经实现完了。不过现在,有一个非常严重的问题出现了。什么问题呢?我们来看一下

首先,因为我们使用的是多选框,是可以有选中状态的,所以我们在添加新书之前,先选中诛仙
在这里插入图片描述

然后再添加新书
在这里插入图片描述

这个时候我们发现,诛仙的状态状态被改变了,变成了未选中,诡秘之主从未选中变成了选中,这是为什么呢?

原因

vue和react都实现了一套虚拟DOM,使我们可以不直接操作DOM元素,只操作数据便可以重新渲染页面。而隐藏在背后的原理便是其高效的Diff算法。

vue为了提高效率,在更新已渲染过的元素列表时,会采用“就地复用”策略。

比如一下这个情况:

img

我们希望可以在B和C之间加一个F,Diff算法默认执行起来是这样的:

img

即把C更新成F,D更新成C,E更新成D,最后再插入E,是不是很没有效率?

所以我们需要使用key来给每个节点做一个唯一标识,Diff算法就可以正确的识别此节点,找到正确的位置区插入新的节点。
所以一句话,key的作用主要是为了高效的更新虚拟DOM
修改HTML中的代码如下,在被v-for循环的标签中添加:key="item.id" 【注意】key一定要是唯一的。

<ul>
      <li v-for="(item, i) in list" :key="item.id">
        <input type="checkbox"> {{item.name}}
      </li>
</ul>

再次尝试选中诛仙,再添加新书,效果如下:
在这里插入图片描述

2、案例:Tab切换

css样式

* {
    margin: 0;
    padding: 0;
}

ul,
li {
    list-style: none;
}

.tab {
    width: 800px;
    border: 1px solid #000;
}

.tab ul {
    display: flex;
}

.tab li {
    width: 200px;
    height: 50px;
    background: #f00;
    border: 1px solid #000;
    line-height: 50px;
    text-align: center;
}

.tab .tabcont div {
    width: 100%;
    border: 1px solid #00f;
}
.tab .tabcont div img{
    width: 100%;
    vertical-align: top;
}

.tab .active {
    background-color: yellow;
}
<div id="app">
        <div class="tab">
            <ul>
                <li v-for="(item,index) of list" :class="isActive(index)" @click="toggle(index)">{{item.title}}</li>
            </ul>
            <div class="tabcont">
                <div v-for="(item,index) of list" v-show="isShow(index)">
                    <img :src="item.path" alt="">
                </div>
            </div>
        </div>
    </div>
 const vm = new Vue({
            el: '#app',
            data: {
                list: [{
                        id: 1,
                        title: '武则天',
                        path: "img/0.jpg",
                    },
                    {
                        id: 2,
                        title: '李白',
                        path: "img/1.jpg",
                    },
                    {
                        id: 3,
                        title: '伽罗',
                        path: "img/2.jpg",
                    },
                    {
                        id: 4,
                        title: '大乔',
                        path: "img/3.jpg",
                    }
                ],
                cur: 0
            },
            methods: {
                isActive(index) {
                    return index == this.cur ? 'active' : ''
                },
                isShow(index) {
                    return index == this.cur ? true : false
                },
                toggle(index) {
                    this.cur = index;
                }
            }
        });

3、案例: TodoList

3.1 线上案例演示

http://www.todolist.cn/

3.2 案例需求分析

  • 用户输入待办事项,回车后添加进”正在进行“,并清空文本框

  • 在”正在进行"列表项单击,添加进“已经完成”列表

  • 在”已经完成"列表项单击,添加进“正在进行”列表

  • 在相应列表项中单击“删除”,删除该项目

3.3代码

<div id="app">
    <!-- 输入框 -->
    <h1>ToDoList <input type="text" v-model="thing" @keyup.enter="addNew"></h1>

    <!-- 待办列表 -->
    <h2>正在完成 ---{{pending.length}}</h2>
    <ul>
        <li v-for="(item,index) in pending">
            <button @click="addResolve(index)">添加到已完成</button>
            <span>{{item}}</span>
            <button @click="delPending(index)">删除</button>
        </li>
    </ul>

    <!-- 已完成列表 -->
    <h2>已经完成---{{resolve.length}}</h2>
    <ul>
        <li v-for="(item,index) in resolve">
            <button @click="addPending(index)">添加到未完成</button>
            <span>{{item}}</span>
            <button @click="delResolve(index)">删除</button>
        </li>
    </ul>
</div>
 const vm = new Vue({
        el: '#app', //挂载点
        data: {
            thing: '',
            pending: [],
            resolve: []
        },
        methods: {
            // 添加待办事项
            addNew() {
                this.pending.push(this.thing);
                this.thing = ''
            },
            // 单击正在完成项目,切换到已经完成
            addResolve(index) {
                this.resolve.push(this.pending[index]);
                this.pending.splice(index, 1);
            },
            // 单击已经完成项目,切换到正在完成
            addPending(index) {
                this.pending.push(this.resolve[index]);
                this.resolve.splice(index, 1);
            },
            //删除正在完成项目
            delPending(index) {
                this.pending.splice(index, 1);
            },
            // 删除已经完成项目 
            delResolve(index) {
                this.resolve.splice(index, 1);
            }
        }
    });
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue 使用 Swiper 可以实现各种轮播图效果,包括异形轮播图。以下是一个简单的示例: 首先,安装 Swiper: ``` npm install swiper --save ``` 然后,在需要使用轮播图的组件引入 Swiper: ```javascript import Swiper from 'swiper' import 'swiper/css/swiper.css' ``` 接着,在组件的 `mounted` 钩子初始化 Swiper: ```javascript mounted () { const mySwiper = new Swiper('.swiper-container', { // Swiper 的配置项 }) } ``` 最后,在模板添加轮播图元素: ```html <div class="swiper-container"> <div class="swiper-wrapper"> <div class="swiper-slide" v-for="(item, index) in items" :key="index"> <!-- 轮播图内容 --> </div> </div> <div class="swiper-pagination"></div> </div> ``` 其,`.swiper-container` 表示容器元素,`.swiper-wrapper` 表示轮播图的内容区域,`.swiper-slide` 表示单个轮播图元素,`.swiper-pagination` 表示轮播图的分页器。 如果要实现异形轮播图,可以在 Swiper 的配置项设置 `slidesPerView` 和 `spaceBetween`,例如: ```javascript const mySwiper = new Swiper('.swiper-container', { slidesPerView: 'auto', spaceBetween: 30, // 其他配置项 }) ``` 其,`slidesPerView` 表示每个轮播图元素的宽度,`spaceBetween` 表示元素之间的间距。通过设置这两个参数,可以实现异形轮播图的效果。 完整的代码示例可以参考下面的代码片段: ```html <template> <div class="swiper-container"> <div class="swiper-wrapper"> <div class="swiper-slide" v-for="(item, index) in items" :key="index"> <div class="item" :style="{ backgroundImage: `url(${item.imgUrl})` }"></div> </div> </div> <div class="swiper-pagination"></div> </div> </template> <script> import Swiper from 'swiper' import 'swiper/css/swiper.css' export default { data () { return { items: [ { imgUrl: 'https://picsum.photos/800/600?random=1' }, { imgUrl: 'https://picsum.photos/800/600?random=2' }, { imgUrl: 'https://picsum.photos/800/600?random=3' }, { imgUrl: 'https://picsum.photos/800/600?random=4' }, { imgUrl: 'https://picsum.photos/800/600?random=5' }, { imgUrl: 'https://picsum.photos/800/600?random=6' }, { imgUrl: 'https://picsum.photos/800/600?random=7' }, { imgUrl: 'https://picsum.photos/800/600?random=8' } ] } }, mounted () { const mySwiper = new Swiper('.swiper-container', { slidesPerView: 'auto', spaceBetween: 30, pagination: { el: '.swiper-pagination' }, navigation: { nextEl: '.swiper-button-next', prevEl: '.swiper-button-prev' } }) } } </script> <style scoped> .item { height: 300px; background-size: cover; background-position: center; } </style> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值