Vue第二天(一些指令,v-for和Key概念,案例与练习)

485 阅读4分钟

Vue

Vue指令

V-text/html

作用:修改标签内容

区别

​ 1.text 内容作为字符串显示

​ 2. html内容作为HTML解析

注意:根据需求,只需要文本就不要用html

V-show/if

作用:控制标签显示隐藏

区别

​ 1.通过CSS的display来控制属性的显示与隐藏

​ 2.控制显示,不满足条件,删除整个标签。满足条件就加回来

<template>
  <div>
    <!-- v-show="表达式" -->
    <h2>v-show</h2>
    <p v-show="age >= 18">成年</p>
    <p v-show="age < 18">未成年</p>

    <!-- v-if="表达式" -->
    <h2>v-if</h2>
    <p v-if="age >= 18">按摩</p>
    <p v-if="age < 18">打机</p>
  </div>
  <!-- 区别:
  1.v-show 控制显示 通过 display 控制标签显示隐藏  
  2.v-if控制显示,不满足条件,删除整个标签。满足条件就加回来-->
</template>
export default {
  data() {
    return {
      age: 18,
    };
  },
};

v-if补充

​ 1.v-if配合v-else使用,必须相邻节点

​ 2.v-if配合v-else-if,可以实现多条件控制,用else结尾,是可选的

<template>
  <div>
    <!-- if else 必须相邻节点  -->
    <h2>if else 配合使用</h2>
    <input type="text" v-model="age">
    <p v-if="age<18">甜甜圈</p>
    <p v-else>快乐水</p>


    <!-- if 配合多个 else-if 搭配使用 实现多条件控制 -->
    <!-- 用else结尾 是可选的 -->
    <h2>IF ELSEIF ELSE配合使用</h2>
    <input type="text" v-model="age">
    <h3 v-if="age<18">甜甜圈</h3>
    <h3 v-else-if="age<50">快乐水</h3>
    <h3 v-else>脑白金</h3>
  </div>
</template>
export default {
  data () {
    return {
      age:18
    }
  }

折叠案例

​ 1.给标签设置v-show,值为Vue变量

​ 2.绑定点击事件,拿vue变量做取反

​ 3.收起,隐藏文字用插值表达式,配合三元运算符

<template>
  <div>
    <h2>折叠案例</h2>
    <h3>静夜思 <button @click="toogle">{{show?"收起":"显示"}}</button></h3>
    <ul v-show="show">
      <li v-for="value in list">{{ value }}</li>
    </ul>
  </div>
</template>
<script>
export default {
  data() {
    return {
      list: [`床前明月光`, `疑是地上霜`, `举头望明月`, `低头思故乡`],
      show: true,
    };
  },
  methods: {
    toogle() {
      this.show = !this.show;
    },
  },
};
</script>

v-for和KEY的一些理论概念

第一个问题

​ 1.当v-for数组变化,页面会更新吗?

​ 2.所有数组方法都会造成v-for更新吗?

结论:有些会,有一些不会

本质

​ 1.数组方法只要修改了原数组,就会触发页面的刷新

1652599388639

​ 2.如果数组方法不会修改原始数组而是返回新数组,就不会触发页面更新,采用this.$set()方法

1652599395926

第二个问题

​ 1.当数组变化了,v-for是如何更新DOM的?

​ 2.和原生的JS有什么区别

结论

​ 1.v-for采用的是一种就地更新机制(Vue在数组中会把数组修改后,直接把整个列表拿出来,在原来的基础上修改数据,原地修改)

​ 2.造成了元素没动过位置,数据改了而已

本质:每次渲染之前,Vue生成虚拟DOM,描述结构,当数据变化再生成一个虚拟DOM进行对比

1652599681716

1652599697239

作用

​ 1**.虚拟DOM是一个JS对象**,保存DOM信息,这样就能提高DOM更新的性能。

​ 2.不频繁操作真实DOM,在内存中找到变化部分,再更新真实DOM

第三个问题

​ 1.v-for中的key有什么作用?

结论

​ 1.性能提升

​ 2.当key值为索引时,还是就地更新机制

​ 3.当key值为id(唯一不重复的字符串或数字)时,不采用就地更新机制

动态设置类名

语法:class"{类型:布尔值}",true就添加类,false去除类

细节

​ 1.布尔值灵活,可以是变量

​ 2.如果类型想要用横杆的形式,要加双引号

    <p :class="{ color: false }">虹色</p>
    <p :class="{ 'backgorund-color': ison }">变量控制</p>
    <button @click="ck">点击控制</button>

动态设置样式

语法:style"{属性名='值'}"

细节

​ 1.属性名是横杆样式时,用小驼峰,如果还想用横杆,用双引号

​ 2.值是灵活的

	<p :style="{ color: 'red' }">红色</p>
    <p :style="{ color: blue }">红色</p>
    <p :style="{backgroundColor:'pink'}">粉色背景</p>
    <p :style="{'font-size':'40px'}">我用横杆引起来的</p>

过滤器

作用:转换格式,过滤器就是一个函数,传入值返回处理后的值

<template>
  <div>
    <p>{{ msg | reverseFn(`$`) }}</p>
    <p :title="`翻转一下` | reverseAA">可以翻转吗</p>
  </div>
</template>
<script>
export default {
  data() {
    return {
      msg: "HELLO WORLD",
    };
  },
  filters: {
    reverseFn(value, unit=``) {
      return value.split("").reverse().join("") + `${unit}`;
    },
  },
};
</script>

细节

​ 1.过滤器只能用在: 插值表达式和v-bind动态属性里

​ 2.声明的是方法,生命在data方法同级的filters对象中

​ 3.value指的就是表达式的值,后面参数可以继续拼接

​ 4.全局设置过滤器:Vue.filert(''过滤器名'',方法(value))注意return返回值

​ 5.可以同时使用多个过滤器

补充

​ 1.过滤器使用与数组翻转,会导致原数组变化,然后表达式中 再翻转 无限递归

​ 2.加slice 不会修改原数组 就不会无限递归

计算属性

作用

​ 1.元素JS计算求和,当计算值改变,和不会随之变化。Vue给出了一种方法

​ 2.根据一些数据计算出一个属性

1652600968908

<input type="text" v-model.number="a">
    <h1>{{sum}}={{a}}+{{b}}</h1>
<script>
export default {
  data () {
    return {
      a:10,
      b:20
    }
  },
  computed: {
   sum(){
     return this.a + this.b
   }
  }
}
</script>

细节

​ 1.计算属性依赖数据的变化,数据变化,计算属性就会重新运行

​ 2.如果计算属性不依赖数据的变化,就会读取缓存中的数据

​ 3.计算属性也是Vue变量,不要和data里重名

​ 4.变量作为一个方法,声明在于data同级的computed对象里

​ 5.记得要return 一个值

好处

​ 计算属性带数据缓存

1652601282750

使用场景:当变量值,其他变量计算而得来的

品牌管理系统案例

1.安装bootstrap,导入包

import 'bootstrap/dist/css/bootstrap.css'

2.数据驱动视图

<tr v-for="(value, index) in list" :key="value.id">
      <th scope="row">{{ value.id }}</th>
      <td>{{ value.name }}</td>
      <td>{{ value.price }}</td>
      <td>{{ value.time | momentFix }}</td>
      <td>
        <button type="button" class="btn btn-link">
                  删除
        </button>
      </td>
 </tr>

3.大于100显示红色字体价格

<td :class="{ onColor: value.price > 100 }">{{ value.price }}</td>

4.绑定点击事件,数组插入数据

<button type="submit" class="btn btn-primary" @click.prevent="add">
          添加资产
        </button>
add() {
     if (!this.placeholderName || !this.placeholderPrice) {
        return;
      }
      this.list.push({
        id:this.list[this.list.length - 1].id + 1
        name: this.placeholderName,
        price: this.placeholderPrice,
        time: new Date(),
      });

5.绑定事件,点击删除(获取索引下标,删除数组)

<button type="button" class="btn btn-link" @click="del(index)">删除</button>
del(index) {
      this.list.splice(index, 1);
    },

6.删除完,显示一个暂无数据标签(v-show)

<tfoot  v-show="list.length===0">
            <tr>
              <td class="text-center" colspan="5">暂无数据</td>
            </tr>
          </tfoot>

7.删除完,添加报错(id是依赖数组长度,现在数组长度为undefined),做判断

let id 
      if(this.list,length>0){
        id=this.list[this.list.length - 1].id + 1
      }else{
        id=100
      }

8.计算总价,均价

 <td colspan="2">总价:{{ allSum }}</td>
 <td colspan="2">均价:{{ avg }}</td>
computed: {
    allSum() {
      let sum = 0;
      this.list.forEach((value) => {
        sum += value.price;
      });
      return sum;
    },
    avg() {
      let avg = 0;
      // 这里拿的是 allSum 不是 sum
      avg = this.allSum / this.list.length
      return avg
    },
  },

9.格式化事件(导入moment模块包),使用过滤

import moment from "moment";
filters: {
    momentFix(value) {
      return moment(value).format(`YYYY-MM-DD HH:mm:ss`);
    },
  },

练习

导航项目

​ 1.动态添加类名,以index作为判断条件

​ 2.遍历数据,渲染列表

​ 3.点击传入index

​ 4.声明一个变量,关联index 与index做判断

 <span
          @click="add(index)"
          :class="{ active: index===checkindex }"
          v-for="(value, index) in arr"
          :key="value.first_id"
          >{{ value.first_name }}</span>
<script>
export default {
  data() {
    return {
      checkindex: 0,
      arr: [...],
    };
  },
  methods: {
    add(index) {
      console.log(index);
      this.checkindex = index;
    },
  },
};
</script>

学员管理

​ 1.双向绑定表单值

​ 2.添加空数组,渲染列表

​ 3.绑定点击事件,数组插入新数据

​ 4.删除功能,获取下标

5.编辑功能,声明两个变量 一个判断按钮是添加或编辑 一个获取选中下标

<input type="text" v-model="userName" />
<input type="number" v-model="age" />
<select v-model="sex">
        <option value="男"></option>
        <option value="女"></option>
<select>
    
<button @click="add(indexAdd)">添加/修改</button>
    
<tr v-for="(value, index) in arr" :key="value.id">
          <td>{{ value.id }}</td>
          <td>{{ value.userName }}</td>
          <td>{{ value.age }}</td>
          <td>{{ value.sex }}</td>
          <td>
            <button @click="del(index)">删除</button>
            <button @click="updata(index)">编辑</button>
          </td>
        </tr>
        <tr v-show="arr.length === 0">
          <td class="text-center" colspan="5">暂无数据</td>
</tr>
<script>
export default {
  data() {
    return {
      indexAdd: 0,
      checkUpdata: false,
      // 编辑想要联系 声明的变量 要在data返回对象中设置
      userName: "",
      age: "",
      sex: "男",
      arr: [],
    };
  },
  methods: {
    add(indexAdd) {
      if (!this.userName || !this.age || !this.sex) {
        alert(`请输入内容`);
        return;
      }
      let id;
      if (this.arr.length > 0) {
        id = this.arr[this.arr.length - 1].id + 1;
      } else {
        id = 1;
      }
      if (this.checkUpdata === false) {
        this.arr.push({
          id,
          userName: this.userName,
          age: this.age,
          sex: this.sex,
        });
        this.userName = "";
        this.age = "";
        this.sex = "";
      } else {
        this.checkUpdata = false;
        this.arr[indexAdd].userName = this.userName;
        this.arr[indexAdd].age = this.age;
        this.arr[indexAdd].sex = this.sex;
        this.userName = "";
        this.age = "";
        this.sex = "";
      }
    },
    del(index) {
      this.arr.splice(index, 1);
    },
    updata(index) {
      this.indexAdd = index;
      this.checkUpdata = true;
      this.userName = this.arr[index].userName;
      this.age = this.arr[index].age;
      this.sex = this.arr[index].sex;
    },
  },
};
</script>

报错总结

一、类值

661fbb2ca18bd8808b6dc25ab344a40

690de62f73f5dc29140e4baa9621eb1

二、过滤器传参

1652601985966

1652601989468

三、过滤器return

1652602000019

1652602004234

四、转数字

1652602017964

1652602022201

五、计算属性声明

1652602039461

1652602045447

六、需求

1652602065968

1652602068062

七、过滤器传参

1652602080519

1652602082958

八、this取值

1652602091911

1652602096065