Vue2 —— 学习(三)

时间:2024-04-09 13:30:58

 shsh一、绑定 class 样式

(一)字符串写法

1.流程介绍

适用于样式的类名不确定 需要动态指定

通过 指令绑定的形式,在模板中的类标签绑定 Vue 实例中的数据 mood

    <div class="basic" :class="mood" @click="changeMood">test</div>

在实例对象的 data 加入 mood 属性并且 用对应的类名赋值 

data: {
          name: '一个人',
          mood: 'normal'
        },

根据以上原理 我们能设计出 一个点击切换样式的效果

点击切换成 happy 类名 中的样式

2.代码实现
<body>
  <div id="root">
    <div class="basic" :class="mood" @click="changeMood">test</div>
    <script>
      new Vue({
        el: '#root',
        data: {
          name: '一个人',
          mood: 'normal'
        },
        methods: {
          changeMood() {
            this.mood = 'happy'
          }
        },
      })
    </script>
  </div>
</body>

随机显示背景颜色函数设计,把三个类名存到数组中,然后随机取下标,进行读取就行 

 methods: {
        changeMood() {
          const arr = ['happy', 'sad', 'normal']
          const index = Math.floor(Math.random() * 3)
          this.mood = arr[index]
        }
      },

(二)数组写法 

1.流程介绍

适用于绑定的样式个数不确定,名字也不确定

想要随时添加样式删除样式 就在模板中 插值一个数组类型的数据

    <div class="basic" :class="arr" @click="changeMood">test</div>

然后在 data 中添加一个数组类型的数据,在数组里面放入我们要展示的类名  ,我们还能通过操作数组进行,增加和删除样式

data: {
        name: '一个人',
        mood: 'normal',
        arr:['normal','happy','bianhua'],
      },

删除

vm.arr.shift()

增加 

vm.arr.push('增加的类名')

2.代码实现
<body>
  <div id="root">
    <div class="basic" :class="arr" @click="changeMood">test</div>
  </div>
  <script>
    new Vue({
      el: '#root',
      data: {
        arr:['normal','happy','bianhua'],
      },
    })
  </script>
  </div>
</body>

(三)对象写法  

1.流程介绍

适用于绑定的样式确定 名字也确定 要动态决定用不用

先绑定对象 

    <div class="basic" :class="Obj" @click="changeMood">test</div>

 在实例对象 vm 中的 data 对象中写一个对象类型数据 里面放着样式类名 通过 true 和 false 来判断使用不使用这个样式

  data: {
        name: '一个人',
        mood: 'normal',
        arr:['normal','happy','bianhua'],
        Obj:{
         happy:true,
         bianhua:true
        }
      },
      method
2.代码实现
<body>
  <div id="root">
    <div class="basic" :class="Obj" @click="changeMood">test</div>
  </div>
  <script>
    new Vue({
      el: '#root',
      data: {
        Obj:{
         happy:true,
         bianhua:true
        }
      },
    })
  </script>
  </div>
</body>

二、绑定 style 样式(了解)

除了可以用 class 绑定样式  我们还可以通过内联 style 来绑定样式

(一)对象写法  

先绑定对象

    <div class="basic" :style="Obj" @click="changeMood">test</div>

 在实例对象 vm 中的 data 对象中写一个样式对象,里面的属性就是我们要设置的样式,属性名不能随便写,得遵循 css 中的属性名

  Obj: {
          fontSize: '40px'
        }

(二)数组写法  

不常用,如果要写很多的样式 我们能分开写

    <div class="basic" :style="Obj" @click="changeMood">test</div>
   styleArr:[
          { 
            fontSize: '40px' 
          },
          {
            backgroundColor: 'blue'
          }
        ]

三、条件渲染

(一)v-show 渲染

变化频率高的时候使用v-show

隐藏标签的内容,节点还在但是被隐藏了

v-show=‘false’ 内容隐藏 true 就是显示

    <h2 v-show="false">欢迎来到{{name}}</h2>

引号里面可以写表达式,还有 vm 中的数据 ,比如 v-show='a' 在 vm 实例的数据中添加 a 的具体值 实现动态的显示和隐藏

还能写 v-show=‘a=1’ 判断布尔值 具体是什么 为真则显示 假则隐藏

(二)v-if 渲染

变化频率低的时候使用v-if 因为很暴力不展示的元素直接删除 

1.v-if

判断里面是否为真为真就显示 为假就删除

    <h2 v-if="false">欢迎来到{{name}}</h2>
2.v-else-if 

 和 if 和 elseif 使用方法类似 先判断 if 如果不符合 再依次往下判断 但是一旦为真 就不再判断下面的了,如果同时三个 v-if 则每行语句都需要重新判断。

  <div v-if="n===1">n=1</div>
    <div v-else-if="n===2">n=2</div>
    <div v-else-if="n===3">n=3</div>
3.v-else 

和  else 用法差不多 但是后面不要接数值了 ,如果 v-if 和v-else-if 中的语句都为假 就显示 v-else 中的语句

 <div v-if="n===1">n=1</div>
    <div v-else-if="n===2">n=2</div>
    <div v-else-if="n===3">n=3</div>
    <div v-else>n是个厉害</div>
4.注意事项 
v-if 不允许被打断

如果在v-else-if 中间添加了其他的标签,就不会执行后面的语句。下面只能输出 n=1 和 n=2 其它找不到了

    <div v-if="n===1">n=1</div>
    <div v-else-if="n===2">n=2</div>
    <div>@</div>
    <div v-else-if="n===3">n=3</div>
    <div v-else>n是个厉害</div>
模板标签 tempalate

如果想让下面几个 h2 标签都在 a=1 时显示出来

我们可能会想到每个标签都加一个 v-if 判断条件的写法 但是太复杂

    <h2 v-if="true">你好</h2>
    <h2 v-if="true">您好</h2>
    <h2 v-if="true">我们好</h2>

 我们可以用一个模板 template 来包裹这些都要显示的标签,然后给这个模板一个 v-if=’n===1‘,就可以控制所有的标签的显示了,而且使用模板不会影响标签结构,当展示出来的时候模板会自动脱落,记住不能和 v-show 使用

 <template v-if="n === 1 ">
      <h2>你好</h2>
      <h2>您好</h2>
      <h2>我们好</h2>
    </template>

四、列表渲染

(一)v-for 遍历

1.遍历数组

数组信息:

 persons:[
          {
            id: '001',
            name: '张三',
            age: 18
          },
          {
            id: '002',
            name: '李四',
            age: 19
          },
          {
            id: '003',
            name: '王五',
            age: 20
          },
        ],

遍历生成相同 的 结构标签 前面一个变量 代表后面的数组每次遍历的当前元素

in 可以换成 of

 <li v-for="p in persons">
        {{p.name}}-{{p.age}}
      </li>

里面最好写上每个生成的 li 标签的 key 值就是每个生成出的标签独特的标识 ,每个生成的 li 的 key 值应该不同 切忌写成 :key='1' 这样每个生成的 li 标签的 key 值相同就会报错,就和身份证不能一样类比。

<li v-for="p in persons" :key='p.id'>
        {{p.name}}-{{p.age}}
      </li>

其 v-for=‘p in persons’ in 前面可以有两个变量,完整写法是 v-for=‘(p,index) in persons’ 

括号里面第一个变量代表后面的数组每次遍历的当前元素,第二代表当前元素的下标

所以我们 的 key 值还有第二种写法

<li v-for="(p,index) in persons" :key='index'>
        {{p.name}}-{{p.age}}
      </li>
2.遍历对象

对象信息:

 car:{
          name:'小汽车',
          price:'100万',
          color:'白色'
        }

遍历对象

和遍历数组类似,在遍历对象时前面也会收到两个数据 第一个是 value 就是当前属性的属性值

key 是当前属性的属性名

  <li v-for="(value,k) in car" :key="k">
        {{k}}-{{value}}
      </li>
3.遍历字符串 少见

str:'hello'

和前面类似 v-for 里面也会收到两个数据 一个是 当前字符 另一个是当前字符的下标

  <li v-for="(char,index) in str" :key="index">
        {{char}}-{{index}}
      </li>
4.遍历指定次数 特别少见

下面是只当遍历 5 次

number 是从1开始的数字 1 2 3 4 5 index 是从 0 开始的下标 0 1 2 3 4 

  <li v-for="(number,index) in 5" :key="index">
        {{number}}-{{index}}
      </li>

(二)v-for 中 key 的原理

1.简单介绍

key 如果不写默认是 下标就是 index

key 的作用就是给节点进行标识 类似于人类的身份证号,在页面中查看真实 dom 结构发现 li 没有 key 属性 因为key 被 Vue 内部使用,当 Vue 把 li 转化成真实 dom 节点时就把 key 这个特殊属性征用了,给 Vue 自己用 不给别人显示,如果换成别的属性名就显示了

      <li v-for="(p,index) in persons" :key="index">
        {{p.name}}-{{p.age}}
      </li>
2.常见错误 

但是如果使用 index 作为 key 的 值使用 一定情况下会发生错误,比如我们想三个人前面加一个王五,但是我们先在每个人后面添加一个文本框,然后输入三个人的信息,然后再添加这个王五,我们发现信息篡位了,具体流程如下:通过虚拟 dom 节点的(diff)对比算法 进行更新

效率较低,因为复用的比较少

 我们可以通过使用 id 来作为 key 的值来使用来解决这个问题,数据不会错位也提高了代码的效率

3.总结

1.可能产生的问题:

逆序添加数据,删除数据 破坏顺序的行为 会产生没有必要的真实dom 的更新,界面效果没问题,但是效率低。

如果结构中包含输入类的dom 会产生错误的 dom 更新 界面有问题  

2.如何选择 key :

使用每一条数据的唯一标识符为 key ,比如 id 手机号 身份证号唯一值

如果不存在逆序增加 删除 破坏顺序的操作,仅用于渲染列表用于展示,使用 index 作为 key 是没问题的

(三)列表信息过滤

1.使用 watch 监听实现

过滤器返回值是过滤数组的条件

空字符串包含在任何字符串之中,返回值是 0 不是 -1 所以能返回过滤数组

<body>
  <div id="root">
    <h2>人员列表</h2>
    <input type="" placeholder="请输入名字" v-model="keyword">
    <ul>
      <li v-for="(p,index) in filPersons" :key="index">
        {{p.name}}-{{p.age}}-{{p.sex}}
      </li>
    </ul>
  </div>
  <script>
    new Vue({
      el: '#root',
      data: {
        keyword: '',
        persons: [
          { id: '001', name: '李三', age: 18, sex: '女' },
          { id: '002', name: '李四', age: 19, sex: '男' },
          { id: '003', name: '王四', age: 20, sex: '男' },
        ],
        filPersons:[]
      },
      watch: {
        keyword:{
          immediate:true,
          handler(val) {
            this.filPersons = this.persons.filter((p) => {
              return p.name.indexOf(val) !== -1
            })
          }
        }
      }
    })
  </script>
</body>
2.使用 计算属性 监听实现 

计算属性中 return 中才是返回的新的数组,不用在 data 中新创建一个空的数组来存最后的数据,不用给数组重新赋值

<body>
  <div id="root">
    <h2>人员列表</h2>
    <input type="" placeholder="请输入名字" v-model="keyword">
    <ul>
      <li v-for="(p,index) in filPersons" :key="index">
        {{p.name}}-{{p.age}}-{{p.sex}}
      </li>
    </ul>
  </div>
  <script>
    new Vue({
      el: '#root',
      data: {
        keyword: '',
        persons: [
          { id: '001', name: '李三', age: 18, sex: '女' },
          { id: '002', name: '李四', age: 19, sex: '男' },
          { id: '003', name: '王四', age: 20, sex: '男' },
        ],
      },
      computed: {
        filPersons() {
          return this.persons.filter((p) => {
            return p.name.indexOf(this.keyword) !== -1
          })
        }
      }
    })
  </script>
</body>

(四)列表排序

在过滤后的数组中进行操作,只要里面任何属性发生变化,就会重新调用

<body>
  <div id="root">
    <h2>人员列表</h2>
    <input type="" placeholder="请输入名字" v-model="keyword">
    <button @click="sortType = 2">年龄升序</button>
    <button @click="sortType = 1">年龄降序</button>
    <button @click="sortType = 0">原顺序</button>
    <ul>
      <li v-for="(p,index) in filPersons" :key="index">
        {{p.name}}-{{p.age}}-{{p.sex}}
      </li>
    </ul>
  </div>
  <script>
    new Vue({
      el: '#root',
      data: {
        keyword: '',
        persons: [
          { id: '001', name: '李三', age: 18, sex: '女' },
          { id: '002', name: '李四', age: 50, sex: '男' },
          { id: '003', name: '王四', age: 30, sex: '男' },
        ],
        sortType: 0,
      },
      computed: {
        filPersons() {
          const arr = this.persons.filter((p) => {
            return p.name.indexOf(this.keyword) !== -1
          })
          if (this.sortType) {
            arr.sort((p1, p2) => {
              return this.sortType === 1 ? p2.age - p1.age : p1.age - p2.age
            })
          }
          return arr
        }
      }
    })
  </script>
</body>

五、Vue 检测数据原理

很重要,我们把 data 中的数据更改 vue 会有一个内置的watch监测,然后在页面中更改新的数据,这节我们得明白不是所有的,更改的情况我们 vue 都能监测并认可更改的,有的时候可能数据变了,但是vue 监测不到,数据不会更改

如下 我们想对数组对象中的第一对象中的属性进行修改,使用下面我们构造的方法,挨个属性进行修改,能成功实现更改第一个对象的属性,并成功被 vue 监测到 新的数据在模板中能成功显现出来

 methods: {
        updataZhang() {
          this.persons[0].name = '李一百'
          this.persons[0].age = 20
          this.persons[0].sex = '男'
        }
      },

但是一旦我们换一个方法,我们使用一个新的对象来替换原来的对象的方法,就不能被 vue 监测到数据的变化,在页面中显示的还是原来被替换前的数据,但是数据确实被改变了,只是vue 无法监测而无法改变。

 methods: {
        updataZhang() {
          this.persons[0] = { id: '001', name: '李一百', age: 20, sex: '男' }
        }
      },