使用 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 中搜索等效方法,该方法将完全匹配。ref
value
data
该对象的一个缺点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