vue02

目录

v-for更新监测

改变数组方法:

虚拟dom

diff算法

diff算法-key

动态class

动态style

vue过滤器

传参和多过滤器

vue计算属性-computed

vue计算属性-完整写法

 vue侦听器-watch

vue侦听器-深度侦听和立即执行


v-for更新监测

目标: 当v-for遍历的目标结构改变, Vue触发v-for的更新

case1: 数组翻转

case2: 数组截取

case3: 更新值

口诀:

改变数组方法, 就会导致v-for更新, 页面更新;

改变数组方法:

pop( 删除数组的最后一个元素)

push(在尾部添加元素,返回的是更新后数组的长度)

shift(删除数组的第一个元素)

unshift(数组第一位元素前面添加元素,返回更新后数组的长度)

splice(替换/添加/删除)

根据不同的参数,有不同的功能:

eg1:删除功能;根据索引删除

用法:array.splice(index,1)

eg2:添加功能:['插入位置',0,’插入的项‘]

用法:array.splice(index,0,insertValue) 

eg3:替换功能 ['起始位置',“删除的项数”,’插入的项‘]

用法:array.splice(index,num,insertValue) 

reverse(翻转)

sort(排序)按字符ASCII进行排序

非改变数组方法, 返回新数组, 就不会导致v-for更新, 可采用覆盖数组或this.$set()

<template>
  <div>
    <ul>
      <li v-for="(item, index) in arr" :key="index">
        {{ item }}
      </li>
    </ul>
    <button @click="fn">reverse</button>
    <button @click="fn1">slice</button>
    <button @click="update">update</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      arr: [1, 2, 3, 4, 5, 6, 7, 8, 9],
    }
  },
  methods: {
    fn() {
      //数组反转改变原数组,触发v-for更新
      this.arr.reverse()
    },
    fn1() {
      //slice不会触发v-for更新,没有改变原数组
      const res = this.arr.slice(1, 3)
      this.arr = res
    },
    update() {
      //索引改变数组,不能触发页面刷新,vue是检测不到的
      this.arr[0] = 66
      //参数1:改变的目标
      //参数2:要更新的位置(对于数组就是下标,对于对象就是key)
      //参数3:要更新的值
      this.$set(this.arr, 0, 666)
     
    },
  },
}
</script>

虚拟dom

.vue文件中的template里写的标签, 都是模板, 都要被vue处理成虚拟DOM对象, 才会渲染显示到真实DOM页面上

  1. 内存中生成一样的虚拟DOM结构(本质是个JS对象)因为真实的DOM属性好几百个, 没办法快速的知道哪个属性改变了比如template里标签结构:

<template>
    <div id="box">
        <p class="my_p">123</p>
    </div>
</template>

对应的虚拟DOM结构

const dom = {
    type: 'div',
    attributes: [{id: 'box'}],
    children: {
        type: 'p',
        attributes: [{class: 'my_p'}],
        text: '123'
    }
}
  1. vue数据更新

    • 生成新的虚拟DOM结构

    • 和旧的虚拟DOM结构对比

    • 利用diff算法, 找不同, 只更新变化的部分(重绘/回流)到页面 , 也叫打补丁

好处1: 提高了更新DOM的性能(不用把页面全删除重新渲染)

好处2: 虚拟DOM只包含必要的属性(没有真实DOM上百个属性)

总结: 虚拟DOM保存在内存中, 只记录dom关键信息, 配合diff算法提高DOM更新的性能

在内存中比较差异, 然后给真实DOM打补丁更新上

diff算法

情况1: 根元素变了, 删除重建

情况2: 根元素没变, 属性改变, ==元素复用==, 更新属性

diff算法-key

情况3: 根元素没变, 子元素没变, 元素内容改变

无key - 就地更新

v-for不会移动DOM, 而是尝试复用, 就地更新,如果需要v-for移动DOM, 你需要用特殊 attribute key 来提供一个排序提示

注意:性能不高, 从第二个li往后都更新了

有key - 值为索引

  • 还是就地更新

因为新旧虚拟DOM对比, key存在就复用此标签更新内容, 如果不存在就直接建立一个新的

  1. v-for先循环产生新的DOM结构, key是连续的, 和数据对应

  2. 然后比较新旧DOM结构, 找到区别, 打补丁到页面上;最后补一个li, 然后从第二个往后, 都要更新内容

有key - 值为id(常用)

key的值只能是唯一不重复的, 字符串或数值

v-for不会移动DOM, 而是尝试复用, 就地更新,如果需要v-for移动DOM, 你需要用特殊 attribute key 来提供一个排序提示

新DOM里数据的key存在, 去旧的虚拟DOM结构里找到key标记的标签, 复用标签

新DOM里数据的key存在, 去旧的虚拟DOM结构里没有找到key标签的标签, 创建

旧DOM结构的key, 在新的DOM结构里没有了, 则移除key所在的标签

<template>
  <div>
    <!-- :key="item.id"使用key作为唯一表示,
(一般选取一个不会改变的属性,index下标会改变,所以这里用id不会改变)
    最大限度的复用原来的标签,提高性能 -->
    <li v-for="item in userList" :key="item.id">
      {{ item.name }}<input type="text" />
    </li>
    <button @click="add">索引为1地方添加元素</button>
  </div>
</template>

 注意:不用key也不影响功能(就地更新), 添加key可以提高更新的性能

动态class

目标: 用v-bind给标签class设置动态的值

  • 语法:

    • :class="{类名: 布尔值}"

  •  使用场景: vue变量控制标签是否应该有类名

<template>
  <div>
    <h2 :class="{ color: bool ,size:bool1}">you see</h2>
  </div>
</template>

<script>
export default {
  data() {
    return {
      bool: true,
      bool1: true,
    }
  },
}
</script>

<style>
.color {
  color: aquamarine;
}
</style>

动态style

语法

  • :style="{css属性: 值}"

  • 动态style的key都是css属性名

<template>
  <div>
    <h2 :style="{ backgroundColor: color, fontSize: size ,color:'white'}">
      我与春风都是过客
    </h2>
  </div>
</template>

<script>
export default {
  data() {
    return {
      color: 'purple',
      size: '30px',
    }
  },
}
</script>

vue过滤器

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

过滤器只能用在, 插值表达式和v-bind表达式

Vue中的过滤器场景

  • 字母转大写, 输入"hello", 输出"HELLO"

  • 字符串翻转, "输入hello, world", 输出"dlrow ,olleh"

语法:

  • 全局过滤器:Vue.filter("过滤器名", (值) => {return "返回处理后的值"})

  • 局部过滤器filters: {过滤器名字: (值) => {return "返回处理后的值"}只在当前页面可以使用

例子:

  • 局部定义字母都大写的过滤器

  • 局部定义字符串翻转的过滤器

<template>
  <div>
    <p>原来的样子: {{ msg }}</p>
    <!-- 2. 过滤器使用
      语法: {{ 值 | 过滤器名字 }}
     -->
    <p>使用翻转过滤器: {{ msg | reverse }}</p>
    <p :title="msg | toUp">鼠标长停</p>
  </div>
</template>

<script>
export default {
  data(){
    return {
      msg: 'Hello, Vue'
    }
  },
  // 方式2: 局部 - 过滤器
  // 只能在当前vue文件内使用
  /*
     语法: 
     filters: {
       过滤器名字 (val) {
         return 处理后的值
       }
     }
  */
  filters: {
    toUp (val) {
      return val.toUpperCase()
    }
  }
}
</script>

注意:全局过滤器需要在main.js里面注册全局过滤器

Vue.filter('reverse', (val, s = '') => {

  return val.split('').reverse().join(s)

})

总结:把值转成另一种形式, 使用过滤器, Vue3用函数替代了过滤器.

全局注册最好在main.js中注册, 一处注册到处使用

传参和多过滤器

语法:

  • 过滤器传参: vue变量 | 过滤器(实参)

  • 多个过滤器: vue变量 | 过滤器1 | 过滤器2

// 方式1: 全局 - 过滤器
// 任意的.vue文件内"直接"使用
// 语法: Vue.filter("过滤器名", 值 => 处理结果)
// Vue.filter("reverse", val => val.split("").reverse().join(""))

// 过滤器接参数
Vue.filter("reverse", (val, s) => {
  return val.split("").reverse().join(s)
})

<template>
  <div>
    <p>原来的样子: {{ msg }}</p>
    <!-- 1.
      给过滤器传值
      语法: vue变量 | 过滤器名(值)
     -->
    <p>使用翻转过滤器: {{ msg | reverse('|') }}</p>
    <!-- 2.
      多个过滤利使用
      语法: vue变量 | 过滤器1 | 过滤器2
     -->
    <p :title="msg | toUp | reverse('|')">鼠标长停</p>
  </div>
</template>

<script>
export default {
  data(){
    return {
      msg: 'Hello, Vue'
    }
  },
  filters: {
    toUp (val) {
      return val.toUpperCase()
    }
  }
}
</script>

定义过滤器, 把时间用moment模块格式化, 返回我们想要的格式

// 1. 下载moment模块
import moment from 'moment'


// 2. 定义过滤器, 编写内部代码
filters: { 
    formatDate (val){
        return moment(val).format('YYYY-MM-DD')
    }
}

<!-- 3. 使用过滤器 -->
<td>{{ obj.time | formatDate }}</td>

vue计算属性-computed

语法:computed: {
    "计算属性名" () {
        return "值"
    }
}

  1. computed有缓存,只要依赖项没有改变,就不会重新计算
  2. 计算属性优势:有缓存。依赖项不变不会重新计算,
  3. 依赖性变化计算出新的值重新缓存

场景: 一个变量的值, 需要用另外变量计算而得来

vue计算属性-完整写法

computed: {
    "属性名": {
        set(值){
            
        },
        get() {
            return "值"
        }
    }
}

<template>
  <div>
    <h1 @click="fn">{{ fullname }}</h1>
    <h3 @click="fn">{{ fullname }}</h3>
    <h2>{{ getfullname() }}</h2>
    <h3>{{ getfullname() }}</h3>
    <button @click="changefir">change</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      firstname: 'gui',
      lastname: 'gui',
    }
  },
  computed: {
    fullName: {
      set(val) {
        // 不能直接改变fullName的值,但是可以通过fullName的依赖项
        // 间接改变fullName
        this.firstName = val.split('-')[0]
        this.lastName = val.split('-')[1]
      },
      get() {
        return this.firstName + '-' + this.lastName
      },
    },
  },
  //   computed: {
  //     fullname() {
  //       //computed有缓存,只要依赖项没有改变,就不会重新计算
  //       //计算属性优势:有缓存。依赖项不变不会重新计算,
  //       //依赖性变化计算出新的值重新缓存
  //       //只要firstname、lastname发生改变 ,fullname会重新计算
  //        set(val){
  // // 不能直接改变fullName的值,但是可以通过fullName的依赖项
  //  // 间接改变fullName
  //      this.firstName = val.split('-')[0]
  //      this.lastName = val.split('-')[1]
  // },
  // get(){
  //  return this.firstName + '-' + this.lastName
  // },

  //     }
  //   },
  methods: {
    //指向当前组件实例对象
    fn() {
      console.log(this)
    },
    getfullname() {
      console.log('getfullname')
      return this.firstname + ' の' + this.lastname
    },
    changefir() {
      this.firstname = '11'
    },
  },
}
</script>

<style></style>

 vue侦听器-watch

目标: 可以侦听data/computed属性值改变

语法:

watch: {
    "被侦听的属性名" (newVal, oldVal){
        
    }
}

vue侦听器-深度侦听和立即执行

目标: 侦听复杂类型, 或者立即执行侦听函数

语法

watch: {
    "要侦听的属性名": {
        immediate: true, // 立即执行
        deep: true, // 深度侦听复杂类型内变化
        handler (newVal, oldVal) {
            
        }
    }
}

<template>
  <div>
    <input type="text " v-model="uname" />
    {{ names }}
  </div>
</template>

<script>
export default {
  data() {
    return {
      uname: 'harry',
      names: '鬼师',
      age: 20,
      user: {
        age: 13,
        sex: '男',
      },
    }
  },
  watch: {
    //key是要监听的属性
    //newvalue当前最新值
    //oldvalue旧的值
    //当被监听的属性发生变化,就会触发此函数
    uname(newvalue, oldvalue) {
      console.log(newvalue, oldvalue)
    },
    age(newvalue, oldvalue) {
      if (newvalue > 25) {
        //当新的age大于25岁,names就会变为kun
        this.names = 'kun'
      }
    },
    user: {
      //监听属性完整写法

      immediate: true, //一进入页面立马执行侦听函数
      deep: true, //深度监听复杂数据类型内部变化
      //属性发生变化时要执行的函数
      handler(newvalue, oldvalue) {
        console.log('change')
      },
    },
  },
}
</script>

<style></style>

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值