vue3学习随便记5-计算属性与侦听器、class和style绑定

计算属性和侦听器

计算属性

计算属性可以避免在模板中放入复杂逻辑,维持模板的清晰。计算属性像属性一样被使用,但可能依赖其他属性,而且它是响应式的。

<html>

<head>
    <script src="vue.global.js"></script>
</head>

<body>
    <div id="app">
        <p>已经出版书籍:</p>
        <span>{{ publishedBooksMessage }}</span>
        <p>已经出版书籍:</p>
        <span>{{ calculateBooksMessage() }}</span>
    </div>
    <script>
        const App = {
            data() {
                return {
                    author: {
                        name: '尤雨溪',
                        books: [
                            'Vue 2 高级指南',
                            'Vue 3 基础指南',
                            'Vue 4 探秘'
                        ]
                    }
                }
            },
            methods: {
                calculateBooksMessage() {
                    return this.author.books.length > 0 ? '是' : '否'
                }
            },
            computed: {
                publishedBooksMessage() {
                    return this.author.books.length > 0 ? '是' : '否'
                }
            }
        }
        Vue.createApp(App).mount('#app')
    </script>
</body>

</html>

计算属性是一个对象,其中每个键值通常是getter型函数。上述例子中,publishedBooksMessage 用起来和普通属性没有什么不同,另外,publishedBooksMessage 依赖 vm.author.books,因此,当 vm.author.books 发生改变时,所有依赖 vm.publishedBooksMessage 的绑定也自动更新。

从实现结果看,计算属性 publishedBooksMessage 和 方法 calculateBooksMessage() 一样,差异在于计算属性是支持缓存的。publishedBooksMessage会在计算后缓存起来,下次渲染直接返回缓存结果,除非依赖项发生改变,触发重新计算和缓存。

computed: {
  now() {
    return Date.now()
  }
}

下面的计算属性 now 不会有后续更新,因为没有依赖项。

虽然计算属性通常是 getter型函数,但它的确可以同时支持 setter:

computed: {
  fullName: {
    // getter
    get() {
      return this.firstName + ' ' + this.lastName
    },
    // setter
    set(newValue) {
      const names = newValue.split(' ')
      this.firstName = names[0]
      this.lastName = names[names.length - 1]
    }
  }
}

这样,但运行 vm.fullName = 'Joe Biden' 时,setter 就会被调用,vm.firstName 和 vm.lastName 相应被更新。

对于 B 依赖 A,当 A 变化时 B 自动产生动作的应用场景,通常计算属性是合适的,但类似数据变化时执行异步或开销较大的操作时,使用侦听器会更合适。侦听器主要是侦听谁(source)和变化时作何反应(callback)的问题,callback的参数为源的新值和旧值。侦听器可以在组件中作为watch选项添加(每个侦听器一个ES2015+函数,即函数名对应侦听对象,参数为新值和旧值),也可以用实例API方法 vm.$watch(...)添加。

<html>

<head>
    <script src="vue.global.js"></script>
</head>

<body>
    <div id="app">
        <p>
            Ask a yes/no question:
            <input v-model="question" />
        </p>
        <p>{{ answer }}</p>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
    <script>
        const App = {
            data() {
                return {
                    question: '',
                    answer: 'Question usually contain a question mark'
                }
            },
            watch: {
                question(newQuestion, oldQuestion) {
                    if (newQuestion.indexOf('?') > -1) {
                        this.getAnswer()
                    }
                }
            },
            methods: {
                getAnswer() {
                    this.answer = 'Thinking ...'
                    axios.get('https://yesno.wtf/api').then(response => {
                        this.answer = response.data.answer
                    }).catch(error => {
                        this.answer = 'Error! ' + error
                    })
                }
            }
        }
        Vue.createApp(App).mount('#app')
    </script>
</body>

</html>

 上述例子中,侦听对象是 question 属性,当 question 变化时,question(...) 回调函数就会执行,它判断用户是否输入了英文问号?,如果没有就直接返回了,反之,就发起异步ajax请求,在获得ajax请求结果后调用 getAnswer() 方法,answer 属性被更新,重新渲染视图对应部分。

侦听器比计算属性更通用更强大,但它也更厚重,杀机用牛刀并非好思路,所以,知道它然后在大部分时间忘记它,使用计算属性是合理的做法。

Class与Style绑定

绑定 class

这没啥,容易理解,看一点例子就OK

对象语法:布尔值会决定某个class是否存在。下面是对象表达式

<div
  class="static"
  :class="{ active: isActive, 'text-danger': hasError }"
></div>

渲染结果

<div class="static active"></div>

也可以绑定到对象属性

<div :class="classObject"></div>
data() {
  return {
    classObject: {
      active: true,
      'text-danger': false
    }
  }
}

或者计算属性

data() {
  return {
    isActive: true,
    error: null
  }
},
computed: {
  classObject() {
    return {
      active: this.isActive && !this.error,
      'text-danger': this.error && this.error.type === 'fatal'
    }
  }
}

数组语法:这通常是应用一个class列表

<div :class="[activeClass, errorClass]"></div>
data() {
  return {
    activeClass: 'active',
    errorClass: 'text-danger'
  }
}

数组元素可以是表达式或者对象

<div :class="[isActive ? activeClass : '', errorClass]"></div>
<div :class="[{ active: isActive }, errorClass]"></div>

组件上使用:组件上的class将和组件内模板的class合并

组件 my-component 内部模板带 class:foo 和 bar

const app = Vue.createApp({})

app.component('my-component', {
  template: `<p class="foo bar">Hi!</p>`
})

使用组件时,附加了 class:baz 和 boo

<div id="app">
  <my-component class="baz boo"></my-component>
</div>

最终渲染结果将是

<p class="foo bar baz boo">Hi</p>

对于带数据绑定的 class 也符合合并规则

<my-component :class="{ active: isActive }"></my-component>

当 isActive 等价于true时,渲染结果为

<p class="foo bar active">Hi</p>

绑定内联样式 style

对象语法:CSS属性名称可以用小驼峰(camelCase)写法或者短横分隔(kebab-case,需要引号括起来)写法。下面是绑定到对象表达式

<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
data() {
  return {
    activeColor: 'red',
    fontSize: 30
  }
}

也可以绑定到对象属性(相对更清晰)

<div :style="styleObject"></div>
data() {
  return {
    styleObject: {
      color: 'red',
      fontSize: '13px'
    }
  }
}

数组语法:这个和前面class类似,此处略过

自动添加前缀:有些CSS属性需要vendor prefix(浏览器引擎前缀),如果 :style 中的 CSS属性需要vendor prefix,Vue会自动侦测并添加上前缀,换句话说,一般你不用超心 -webkit-、-moz-、-o-、-ms-,直接写类似 transition 就OK。

多重值:就是浏览器可能支持多个值,这样,提供多个值,最后有效的值会被使用

<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值