Vue博客搭建(3)响应式基础

144 阅读3分钟

dxf上一篇中的结尾我们讲了组件传递参数的两种参数,但是这些参数都是写死的。我们要如何才能使参数动态变化呢?这就进入到了Vue核心功能——响应式。

响应式数据

我们想要给博客预览组件添加一个新的功能:点赞和显示点赞数。首先我们需要一个点赞按钮和一个点赞函数(虽然不符合一般的博客逻辑,但是这里我们就先这么做了)。在一切的开始,我们需要给预览组件添加一个属性来表示点赞数。这里的属性不是一般的属性,而是Vue中可以进行双向绑定的属性。

在Vue3中,我们可以使用reactive函数来创建一个响应式对象。

<script setup>
import { reactive } from 'vue';

defineProps(['mainText']);

let state = reactive({like: 0});
function likeUp(){
    state.like++;
}
</script>

但是reactive函数拥有自己的局限性。首先是因为其只能传入复杂数据类型,而对基本数据类型无能为力。其次,Vue响应式是通过属性访问器进行追踪的,也就是说如果使用重新定义的方式来进行属性修改的话,那么前后会被Vue视为两个响应式属性。因此下面的代码将不会起作用。

<script setup>
import { reactive } from 'vue';

defineProps(['mainText']);

let state = reactive({like: 0});
function likeUp(){
    state = reactive({like:1})
}
</script>

如果要解决上述问题,我们可以使用ref函数代替reactive函数,就像下面这样。

<script setup>
import { ref } from 'vue';

defineProps(['mainText']);

let like = ref(0);
function likeUp(){
    like.value++
}
</script>

v-on

你会想,这应该很简单,我们直接使用on-click属性不就可以了吗。是这样,但是Vue给我们了一个可以自定义事件的替代方案,也就是v-on指令。完整的博客点赞组件如下:

<script setup>
<script setup>
import { ref } from 'vue';

defineProps(['mainText']);

let like = ref(0);
function likeUp(){
    like.value++
}
</script>

<template>
    <div>
        <slot/>
        {{ mainText }}
        <button @click="likeUp">点赞数:{{ like }}</button>
    </div>
</template>

<style>
</style>

注意,通过ref函数创建的变量在JavaScript代码中被访问的话需要使用value(毕竟ref还承担着响应式的任务,不可能只有一个属性),而在template中则不需要,Vue会自动将其解包(当然这种解包并不会嵌套,只能解包一层)。

运行项目,我们会发现按钮在每次点击之后点赞数都会加一,说明我们成功地构建了响应式操作。其实@v-on的简写,我们把@click改成v-on:click也可以达到同样的效果。

v-bind

回到App.vue,如果我们想通过JavaScript代码来控制博客预览中的正文,也就是通过JavaScript代码响应式地绑定元素的属性,应该怎么办?这就需要使用v-bind指令了。

<script setup>

import { ref } from 'vue';
import ArticlePreview from './components/ArticlePreview.vue';

let mainText= ref(0);
setTimeout(()=>{
    mainText.value = 1;
},1000)
</script>

<template>
  <header>
    <img alt="Vue logo" class="logo" src="./assets/logo.svg" width="125" height="125" />
    <ArticlePreview :main-text="mainText">1</ArticlePreview>
    <ArticlePreview :main-text="mainText">2</ArticlePreview>
    <div class="wrapper">
    </div>
  </header>

  <main>
  </main>
</template>

运行项目,会发现博客的正文在一秒钟后都从0变成了1。和上一个指令一样,:main-text也是简写,是v-bind:main-text的简写。

v-for

在真正的生产环境中,我们的博客列表一般都是一个可迭代的形式,比如数组。而且我们事先可能不知道数组的长度。那我们怎么样才能灵活控制博客预览元素的个数呢?这就需要用到v-for指令了。

<script setup>
import ArticlePreview from './components/ArticlePreview.vue';

let blogTitles = [1,2,3,4,5,6,7,8,9]
</script>

<template>
  <header>
    <img alt="Vue logo" class="logo" src="./assets/logo.svg" width="125" height="125" />
    <div v-for="blogTitle in blogTitles">
      <ArticlePreview>{{ blogTitle }}</ArticlePreview>
    </div>
    <div class="wrapper">
    </div>
  </header>

  <main>
  </main>
</template>