• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
RatherBe
博客园    首页    新随笔    联系   管理    订阅  订阅

vue笔记

vue笔记(持续更新)

Vue scoped

scoped解决了什么?

模块化编程下,在对应模块的js中import css,这个css仍然是全局。因此会产生css样式之间污染。scoped可以使css样式只作用于当前组件,解决了组件之间样式污染。给每个style都设置上scoped,相当于实现了样式的模块化。

官方解释:当style有scoped属性时,它的CSS只作用于当前组件中元素(解决样式冲突)


<style scoped>
  @media (min-width: 250px) {
    .list-container:hover {
      background: orange;
    }
  }
</style>

<!-- 
scoped 会自动添加一个唯一的 attribute (如 data-v-hash) 为组件内 CSS 指定作用域,编译的时候 .list-container:hover 会被编译成 .list-container[data-v-hash]:hover。
 -->

例如:


<!-- scoped转译前 -->

<style lang="scss" scoped>
    .test {
        background: blue;
        span{
            color:red;
        }
    }
</style>


<!-- scoped转译后 -->

<style lang="css">
    .test[data-v-ff86ae42] {
        background: blue;
    }
    .test span[data-v-ff86ae42]{
        color: red;
    }
</style>

以前有个人在Vue提了个issue,style的scope使一些必要的css无效,然偶后尤大大亲自耐心的回答了,scope的功能是为了让css更规范,能更简单让css仅对本组件的内容起到作用而不影响其他组件,这样也是为了减少各组件之间的样式黏性,可以避免修改单组件样式而影响到整个项目众多组件的问题。反正能用外联css或公共css文件建立共有的css,所以我是非常建议使用scope但别穿透它

穿透scoped

为什么要穿透scoped?

通过scoped,组件的样式是被封装在组件范围内的,也就是说组件样式对外部组件是不可见的。这种封装样式的机制可以防止样式冲突和作用域污染,提高样式的可维护性。然而某些情况下,我们希望通过组件样式去修改或影响子组件内部的样式。

<template>
  <div class="parent">
    <child-component class="custom-class" />
  </div>
</template>

<style scoped>
.parent /deep/ .custom-class {
  /* 修改子组件的样式 */
}
</style>

使用scoped情况

在模板中使用两次style标签

<!-- 使用两次style分别控制 需要覆盖子组件的样式 和 只能本模块使用样式 -->

<style lang="scss">
    /*添加要覆盖的样式*/
</style>

<style lang="scss" scoped>
    /* 本模块样式 */
</style>

<!-- vue官网明确表示一个vue文件可以包含多个style标签 -->

scoped穿透

<!--使用 >>> 或者 /deep/ 操作符(Sass,less 之类的预处理器无法正确解析 >>>,可以使用/deep/)-->

<style lang="scss" scoped>
.box {
  /deep/ input {
    width: 166px;
    text-align: center;
  }
}
</style>

或者

<style lang="scss" scoped>
.box >>> input {
    width: 166px;
    text-align: center;
  }
</style>

不使用scoped情况

  1. 使用全局样式:将样式定义在全局的CSS文件中,这样定义的样式将会被整个应用所共享。

  2. 使用CSS Modules:CSS Modules允许您在每个组件中定义独立的、局部作用域的样式,但仍然可以通过类名选择器来影响其他组件的样式

  3. 使用CSS预处理器:大多数CSS预处理器(如Sass、Less)都支持全局样式和变量。

总结

scoped穿透是一种非正式的语法,不是标准的CSS规范,因此在使用时要谨慎考虑其兼容性和易读性。

总而言之,scoped穿透在一定程度上打破了组件样式的封装性,允许父组件的样式影响到子组件内部的样式,但需要注意合理使用,避免引入样式的混乱和复杂性。

Vue nextTick

为什么会存在nextTick?

vue采用异步更新策略来提高性能,当修改Vue实力数据时,Vue并不会立即更新真实DOM,而是讲DOM更新操作推入一个队列中,在下一个事件循环周期中进行统一的更新。这样做可以有效地合并多次数据变更,避免频繁的DOM操作。然而,这也导致了一个问题:在某些情况下,我们需要在数据更新之后立即访问更新后的DOM。

nextTick作用

通过使用nextTick方法接收一个回调函数作为参数,并讲这个回调函数延迟到下次DOM更新循环结束后执行,确保DOM已经被更新。这样就能够安全地操作更新后的DOM元素,而不用担心获取到旧的值或状态。

nextTick实现原理

将传入的回调函数包装成异步任务,异步任务又分微任务和宏任务,为了尽快执行所以优先选择微任务;

nextTick 提供了四种异步方法 Promise.then、MutationObserver、setImmediate、setTimeout(fn,0)

这四种异步可以阅读nextTick源码解读。


<!-- 例子解释 -->

<script>
console.log('start');

process.nextTick(() => {
  console.log('nextTick callback');
});

console.log('end');
</script>

<!-- 输出结果:
          start
          end
          nextTick callback
 -->

Vue computed

computed解决了什么问题?

computed 的存在是为了提供一种方便、高效地对响应式数据进行计算和处理的机制。

解决的问题有:

  • 简化复杂逻辑:当需要进行复杂的数据计算或处理时,使用 computed 可以将这些逻辑封装在一个计算属性中,使代码更易于理解、维护和重用。

  • 避免重复计算:computed 会根据其依赖的响应式数据来进行缓存。只有在依赖发生变化时,才会重新计算计算属性的值。这样可以避免重复计算,提高性能并减少不必要的计算开销。

  • 自动追踪依赖关系:Vue.js 的响应式系统会自动追踪 computed 属性所依赖的响应式数据。当依赖的数据发生改变时,相关的计算属性会自动重新计算,确保计算结果的及时更新。

  • 优化模板渲染:通过在模板中使用 computed,可以将复杂的数据处理逻辑移到计算属性中,简化模板的写法,使模板更易读、清晰。

Vue官方示例computed


<!-- message数据需要展示 -->

<template>
  <div id="app">
    {{message}}
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      message: 'Hello'
    }
  }
}
</script>


<!-- ! 需求:对message反转并展示 -->


<!-- 正确但不合适的做法:直接在模板转化或在methods中定义一个方法调用 -->

<template>
  <div id="app">
    <p>{{message}}</p>
    <p>{{message.split('').reverse().join('')}}</p>
  </div>
</template>

<!-- 正确且合适的做法:使用computed -->

<template>
  <div id="app">
    <p>{{message}}</p>
    <p>{{reverseMessage}}</p>
  </div>
</template>

<script>
export default {
  name: 'App',
  computed: {
    reverseMessage: function(){
      return this.message.split('').reverse().join('');
    }
  },
  data() {
    return {
      message: 'Hello'
    }
  }
}
</script>

解析:

当我们使用不合适的直接转换展示时,每次我们需要完成这个需求,都要写一遍处理逻辑。

使用不合适的methods中定义一个方法,方法写上处理逻辑,每次需要完成这个需求时,调用方法。这种方式表面上不需要写很多遍处理逻辑,但是每次调用这个方法时候,都会执行处理逻辑。

使用合适的computed时,computed会保存处理逻辑的值,每次需要完成这个需求时,直接获取computed缓存好的值,不需要反复执行处理逻辑,只有当依赖项改变时才会重新执行处理逻辑,并缓存更新后的值。

Vue Watch

watch作用?

Vue中的watch又名为侦听属性,它主要用于侦听数据的变化,在数据发生变化的时候执行一些操作。

作用有:

  • 响应式数据的监控:通过 watch,您可以监听指定的数据(包括响应式数据和计算属性),一旦这些数据发生变化,就会触发相应的回调函数。这使得您可以实时捕捉数据的改变并做出相应的处理。

  • 复杂依赖关系的处理:有时候,数据之间存在复杂的依赖关系,一个数据的改变可能会影响到其他相关的数据。使用 watch,您可以轻松地处理这种复杂的依赖关系,监听多个数据,并在其中一个数据发生变化时进行相应的处理。

  • 异步操作的触发:watch 支持异步处理逻辑在回调函数中执行,这对于需要进行异步操作的场景非常有用。例如,当某个数据发生变化后,您可以在回调函数中发送网络请求或执行其他异步任务。

  • 避免不必要的计算开销:由于 watch 会立即执行回调函数来响应数据的变化,因此您可以根据需要选择性地监听特定的数据,避免无谓的计算开销和性能浪费。

Vue 官方示例

Vue官网很明确的建议我们这样使用watch侦听属性:当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。

<template>
<p>
  Ask a yes/no question:
  <input v-model="question" />
</p>
<p>{{ answer }}</p>
</template>

<script>
export default {
  data() {
    return {
      question: '',
      answer: 'Questions usually contain a question mark. ;-)'
    }
  },
  watch: {
    // 每当 question 改变时,这个函数就会执行
    // newQuestion更新后的值,oldQuestion更新前的值
    question(newQuestion, oldQuestion) {
      if (newQuestion.includes('?')) {
        this.getAnswer()
      }
    }
  },
  methods: {
    async getAnswer() {
      this.answer = 'Thinking...'
      try {
        const res = await fetch('https://yesno.wtf/api')
        this.answer = (await res.json()).answer
      } catch (error) {
        this.answer = 'Error! Could not reach the API. ' + error
      }
    }
  }
}
</script>

解析:

以上定义了一个input框收集用户输入的问题,一个p标签回答用户问题,每当input框的question发生改变时,都会触发watch中的question方法执行处理逻辑,判断是否有?,有则执行methods中的getAnswer方法

computed 和 watch如何选择?

Vue官网的示例


<script>
// 使用computed实现
// 定义计算属性fullName,将firstName和lastName的值进行拼接并返回。
computed: {
  fullName: function() {
    return this.firstName + ' ' + this.lastName;
  }
}, 

// 使用watch实现
// watch侦听firstName和lastName,当这两个数据发生变化时更新fullName的值。
watch: {
  firstName: function(newValue) {
    this.fullName = newValue + ' ' + this.lastName;
  },
  lastName: function(newValue){
    this.fullName = this.firstName + ' ' + newValue;
  }
}
</script>

解析:

两个方法效率都差不多,每次firstName,lastName都会,而computed实现方式更加简洁。

computed应用场景:模板中有复杂的计算。

watch应用场景:当数据发生变化时执行 异步操作 或者 开销较大的操作。

注意:

当多个数据影响一个数据时,会导致watch多次被调用,这个时候尽量使用computed。

posted @ 2023-06-14 22:05  泡椒不辣  阅读(29)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3