使用 Vue Composition API 构建电影搜索应用
Vue 3 的首个Alpha 版本发布了!Vue 3 带来了许多激动人心的功能:Vue 在新的 Composition API 背后公开了其响应式系统。如果您还没有听说过它,我建议您阅读描述它的 RFC。起初我有点怀疑,但看到 React 的 Hooks API 与之类似,我决定尝试一下。
在本文中,我们将使用 Composition API 构建一个电影搜索应用程序。我们不会使用基于对象的组件。我将解释新 API 的工作原理以及如何构建应用程序。
当我们完成后,我们将看到类似这样的内容:
该应用程序将能够通过开放电影数据库 API搜索电影并呈现结果。构建此应用程序的原因是,它足够简单,不会分散学习新 API 的注意力,但又足够复杂,能够展示其有效性。
设置项目
对于本教程,我们将使用 Vue CLI,它可以快速生成必要的环境。
npm install -g @vue/cli
vue create movie-search-vue
cd movie-search-vue
npm run serve
我们的应用程序现在在http://localhost:8080上运行,如下所示:
您可以在此处看到默认文件夹结构:
如果你不想在本地电脑上安装所有依赖项,也可以在Codesandbox上启动项目。Codesandbox 为大多数主流框架(包括 Vue)提供了完美的启动项目。
启用新 API
生成的源代码使用的是 Vue 2 和旧 API。要使用 Vue 2 的新 API,我们必须安装Composition 插件。
npm install @vue/composition-api
安装后,我们必须将其添加为插件:
import Vue from 'vue';
import VueCompositionApi from '@vue/composition-api';
Vue.use(VueCompositionApi);
组合插件是附加的:您仍然可以按照旧的方式创建和使用组件,并开始使用 Composition API 创建新的组件。
我们将有四个部分:
- App.vue:父组件。它将处理 API 调用并与其他组件通信。
- Header.vue:接收并显示页面标题的基础组件
- Movie.vue:渲染每部电影。电影对象作为属性传递。
- Search.vue:包含一个带有输入元素和搜索按钮的表单。提交表单时,它会将搜索词传递给应用组件。
创建组件
让我们编写第一个组件,即标题:
<template>
<header class="App-header">
<h2>{{ title }}</h2>
</header>
</template>
<script>
export default {
name: 'Header',
props: ['title'],
setup() {}
}
</script>
组件的props声明方式相同。您可以将期望从父组件获取的变量命名为数组或对象。这些变量将在 template( {{ title }}) 和setup方法中可用。
这里新增的是setup方法。它在初始props解析后运行。该setup方法可以返回一个对象,该对象的属性将被合并到模板上下文中:这意味着它们将在模板中可用。返回的对象也是放置生命周期回调的地方。我们将在搜索组件中看到相关示例。
让我们看一下搜索组件:
<template>
<form class="search">
<input
type="text"
:value="movieTitle"
@keyup="handleChange"
/>
<input @click="handleSubmit" type="submit" value="SEARCH" />
</form>
</template>
<script>
import { ref } from '@vue/composition-api';
export default {
name: 'Search',
props: ['search'],
setup({ search }, { emit }) {
const movieTitle = ref(search);
return {
movieTitle,
handleSubmit(event) {
event.preventDefault();
emit('search', movieTitle.value);
},
handleChange(event) {
movieTitle.value = event.target.value
}
}
}
};
</script>
搜索组件会跟踪键盘输入,并将输入值存储在一个变量中。当我们完成输入并点击提交按钮后,它会将当前搜索词向上发送到父组件。
该setup方法有两个参数。
第一个参数被解析props为一个命名对象。你可以使用对象解构来访问其属性。该参数是响应式的,这意味着setup当输入属性发生变化时,函数将再次运行。
this第二个参数是上下文对象。您可以在这里找到2.x API 中可用的属性列表( attrs、slots、parent、root、emit)。
这里的下一个新元素是ref函数。该ref函数暴露了 Vue 的响应式系统。调用时,它会创建一个具有单个属性的响应式可变变量value。该value属性将具有传递给函数的参数的值ref。它是对原始值的响应式包装器。在模板内部,我们无需引用该value属性,Vue 会为我们解开它。如果我们传入一个对象,它将具有高度的响应性。
反应式意味着当我们修改对象的值(在我们的例子中是value属性)时,Vue 会知道该值已经改变,并且它需要重新渲染连接的模板并重新运行监视的函数。
它的作用类似于从data方法返回的对象属性。
data: function() {
return { movieTitle: 'Joker' };
}
粘合
下一步是引入 Header 和 Search 组件的父组件,即 App 组件。它监听来自 Search 组件的搜索事件,在搜索词发生变化时运行 API,并将找到的电影传递给 Movie 组件列表。
<template>
<div class="App">
<Header :title="'Composition API'" />
<Search :search="state.search" @search="handleSearch" />
<p class="App-intro">Sharing a few of our favourite movies</p>
<div class="movies">
<Movie v-for="movie in state.movies" :movie="movie" :key="movie.imdbID" />
</div>
</div>
</template>
<script>
import { reactive, watch } from '@vue/composition-api';
import Header from './Header.vue';
import Search from './Search.vue';
import Movie from './Movie.vue';
const API_KEY = 'a5549d08';
export default {
name: 'app',
components: {
Header, Search, Movie
},
setup() {
const state = reactive({
search: 'Joker',
loading: true,
movies: [],
errorMessage: null
});
watch(() => {
const MOVIE_API_URL = `https://www.omdbapi.com/?s=${state.search}&apikey=${API_KEY}`;
fetch(MOVIE_API_URL)
.then(response => response.json())
.then(jsonResponse => {
state.movies = jsonResponse.Search;
state.loading = false;
});
});
return {
state,
handleSearch(searchTerm) {
state.loading = true;
state.search = searchTerm;
}
};
}
}
</script>
我们在这里引入两个新元素:reactive和watch。
该reactive函数相当于 Vue 2 中的Vue.observable()。
它使传递的对象具有高度的响应性:获取原始对象并用代理(基于 ES2015 代理的实现)包装它。在从 返回的对象上,我们可以直接访问属性,而不是在需要使用属性时reactive从函数返回的值。如果您想在 Vue 2.x API 中搜索等效方法,该方法将完全匹配。refvaluedata
该对象的一个缺点reactive是我们不能将它传播到从setup方法返回的对象中。
该watch函数需要一个函数作为参数。它会跟踪内部的反应变量,就像组件为模板所做的那样。当我们修改传入函数内部的反应变量时,给定的函数会再次运行。在我们的示例中,每当搜索词发生变化时,它都会获取与搜索词匹配的电影。
剩下一个组件,用于显示每条电影记录:
<template>
<div class="movie">
<h2>{{ movie.Title }}</h2>
<div>
<img width="200" :alt="altText" :src="movie.Poster" />
</div>
<p>{{ movie.Year }}</p>
</div>
</template>
<script>
import { computed } from '@vue/composition-api';
export default {
name: "Movie",
props: ['movie'],
setup({ movie }) {
const altText = computed(() => `The movie titled: ${movie.Title}`);
return { altText };
}
};
</script>
Movie 组件接收要显示的电影,并将其名称与图片一起打印出来。令人兴奋的是,对于alt图片字段,我们使用了基于标题计算的文本。
该computed函数获取一个 getter 函数,并将返回的变量包装成一个响应式函数。返回的变量与函数返回的变量具有相同的接口ref。区别在于它是只读的。当 getter 函数中的某个响应式变量发生变化时,getter 函数将再次运行。如果computed函数返回的是未包装的原始值,则模板将无法跟踪依赖项的变化。
清理组件
目前,App 组件内部有很多业务逻辑。它主要负责两件事:处理 API 调用及其子组件。我们的目标是让每个对象只负责一项职责:App 组件应该只管理组件本身,而不应该处理 API 调用。为了实现这一点,我们必须将 API 调用提取出来。
import { reactive, watch } from '@vue/composition-api';
const API_KEY = 'a5549d08';
export const useMovieApi = () => {
const state = reactive({
search: 'Joker',
loading: true,
movies: []
});
watch(() => {
const MOVIE_API_URL = `https://www.omdbapi.com/?s=${state.search}&apikey=${API_KEY}`;
fetch(MOVIE_API_URL)
.then(response => response.json())
.then(jsonResponse => {
state.movies = jsonResponse.Search;
state.loading = false;
});
});
return state;
};
现在 App 组件缩小仅用于处理与视图相关的操作:
import Header from './Header.vue';
import Search from './Search.vue';
import Movie from './Movie.vue';
import { useMovieApi } from '../hooks/movie-api';
export default {
name: 'app',
components: { Header, Search, Movie },
setup() {
const state = useMovieApi();
return {
state,
handleSearch(searchTerm) {
state.loading = true;
state.search = searchTerm;
}
};
}
}
就是这样;我们用新的 Composition API 完成了一个小应用程序的实现。
总结
自从使用 Vue CLI 生成项目以来,我们已经取得了很大进展。让我们总结一下我们学到的东西。
我们可以将新的 Composition API 与当前稳定的 Vue 2 版本一起使用。为此,我们必须使用@vue/composition-api插件。该 API 是可扩展的:我们可以使用新 API 创建新组件,同时创建旧组件,而现有组件仍可像以前一样工作。
Vue 3 将引入许多不同的功能:
setup:驻留在组件上,并将协调组件的逻辑,在初始props解析后运行,接收props上下文作为参数ref:返回一个反应变量,在改变时触发模板的重新渲染,我们可以通过value属性来操作它的值。reactive:返回一个反应对象(基于代理),在反应变量改变时触发模板的重新渲染,我们可以在不使用value属性的情况下修改其值computed:根据 getter 函数参数返回一个反应变量,跟踪反应变量的变化并在变化时重新评估watch:根据提供的功能处理副作用,跟踪反应变量的变化并在变化时重新运行
我希望这个例子能让您熟悉新的 API,并消除您的怀疑,就像我一样。
文章来源:https://dev.to/sonicoder/build-a-movie-search-app-using-the-vue-composition-api-5218
后端开发教程 - Java、Spring Boot 实战 - msg200.com


