文章目录
使用Vue CLI新建项目demo启动项目demo改造项目public目录下新增data.jsonsrc目录下新增api目录,api目录下新增repositories.jscomponents目录下删除HelloWorld.vue,新增RepositoriesList.vue修改App.vue启动应用 组合式APIsetup里使用ref()定义响应式变量setup里注册生命周期钩子setup里添加watch 参考文章使用Vue CLI新建项目demo
D:\VueProjects>vue create demoVue CLI v4.5.13? Please pick a preset: (Use arrow keys)Default ([Vue 2] babel, eslint)> Default (Vue 3) ([Vue 3] babel, eslint)Manually select features
启动项目demo
D:\VueProjects>cd demoD:\VueProjects\demo>npm run serve
改造项目
public目录下新增data.json
[{"user":"nicholas","user_id":"123","repositoriesList":[{"id":"n1","name":"repository n1"},{"id":"n2","name":"repository n2"},{"id":"n3","name":"repository n3"}]},{"user":"tom","user_id":"456","repositoriesList":[{"id":"t1","name":"repository t1"},{"id":"t2","name":"repository t2"},{"id":"t3","name":"repository t3"}]},{"user":"jack","user_id":"789","repositoriesList":[{"id":"j1","name":"repository j1"},{"id":"j2","name":"repository j2"},{"id":"j3","name":"repository j3"}]}]
src目录下新增api目录,api目录下新增repositories.js
const fetchUserRepositories = (user) => {return fetch("/data.json").then(response => {return response.json();}).then(res => {let r = [];r = res.filter(item => item.user===user);if(r.length>=1){return r[0].repositoriesList;} return r;})}export {fetchUserRepositories}
components目录下删除HelloWorld.vue,新增RepositoriesList.vue
<template><ul class="list"><li v-for="repo in repositories":key="repo.id">{{repo.name}}</li></ul></template><script>import {fetchUserRepositories} from "../api/repositories.js";export default{name:"RepositoriesList",props:{user:{type:String,required:true}},data(){return {repositories:[]}},// watch:{//user:function(){// this.getUserRepositories();//}// },watch:{user:'getUserRepositories'},methods:{async getUserRepositories(){this.repositories = await fetchUserRepositories(this.user);}},mounted(){this.getUserRepositories();}}</script>
修改App.vue
<template><span id="user">User name:</span><input type="text" for="user" v-model="user"><RepositoriesList :user="user"></RepositoriesList></template><script>import RepositoriesList from "@/components/RepositoriesList";export default {name: 'App',data(){return {user:"nicholas"}},components: {RepositoriesList}}</script><style>#app {font-family: Avenir, Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;color: #2c3e50;margin-top: 60px;}</style>
启动应用
D:\VueProjects\demo>npm run serve> demo@0.1.0 serve D:\VueProjects\demo> vue-cli-service serveINFO Starting development server...98% after emitting CopyPluginDONE Compiled successfully in 2296ms 9:15:32 ├F10: PM┤App running at:- Local: http://localhost:8080/
对于一个简单组件来说,将data
、methods
、watch
、mounted
分离,逻辑清晰,理解起来不难;但对一个复杂组件来说,将它们分离,就意味着需要在不同的代码块之间跳转,代码阅读起来困难,理解起来也不容易。
所以来看看组合式API吧。
组合式API
setup
选项在创建组件之前执行,由于在执行setup
时,组件实例尚未创建,因此在setup
中没有this
,这也意味着,除了props
外,setup
中无法访问组件的状态、计算属性、方法等任何属性。
setup
选项是一个函数,它接受两个参数:props
和context
,返回的内容将暴露给组件模板、计算属性、方法、生命周期钩子等。
在上例的基础上使用组合API,仅需要对RepositoriesList.vue
进行修改,如下,
<template><ul class="list"><li v-for="repo in repositories":key="repo.id">{{repo.name}}</li></ul></template><script>import {fetchUserRepositories} from "../api/repositories.js";import {ref,onMounted,toRefs,watch} from "vue";export default{name:"RepositoriesList",props:{user:{type:String,required:true}},setup(props){const {user} = toRefs(props);let repositories = ref([]);const getUserRepositories = async () => {repositories.value = await fetchUserRepositories(props.user);}onMounted(getUserRepositories);watch(user,getUserRepositories);return {repositories:repositories,getUserRepositories:getUserRepositories}}}</script>
setup里使用ref()定义响应式变量
ref()
接受参数,并将其包裹在一个带有value
属性的对象中返回,然后可以使用value
属性访问或更改响应式变量的值。
<template><ul class="list"><li v-for="repo in repositories":key="repo.id">{{repo.name}}</li></ul><div>count:{{count}}</div><button @click="handleClick">click me</button></template><script>import {fetchUserRepositories} from "../api/repositories.js";import {ref,onMounted,toRefs,watch} from "vue";export default{name:"RepositoriesList",props:{user:{type:String,required:true}},setup(props){const {user} = toRefs(props);let repositories = ref([]);let count = ref(0);console.log(count.value);const handleClick = () => {count.value++;}const getUserRepositories = async () => {repositories.value = await fetchUserRepositories(props.user);}onMounted(getUserRepositories);watch(user,getUserRepositories);return {count,repositories:repositories,getUserRepositories:getUserRepositories,handleClick}}}</script>
setup里注册生命周期钩子
见本例中的onMounted(getUserRepositories)
,onMounted()
接受一个回调作参数,当钩子被组件调用时,该回调将执行。
setup里添加watch
不妨先看下不放在setup
里,watch
选项是怎么使用的。
首先,得说清要监听哪些数据,因此,要指定监听的响应式引用然后,监听数据要干嘛,因此,指定对应的回调函数
<template><ul class="list"><li v-for="repo in repositories":key="repo.id">{{repo.name}}</li></ul><div>count:{{count}}</div><button @click="handleClick">click me</button></template><script>import {fetchUserRepositories} from "../api/repositories.js";import {ref,onMounted,toRefs,watch} from "vue";export default{name:"RepositoriesList",props:{user:{type:String,required:true}},// watch:{//count:function(newValue,oldValue){// console.log(newValue,oldValue);//}// },watch:{count(newValue,oldValue){console.log(newValue,oldValue);}},setup(props){const {user} = toRefs(props);let repositories = ref([]);let count = ref(0);console.log(count.value);const handleClick = () => {count.value++;}const getUserRepositories = async () => {repositories.value = await fetchUserRepositories(props.user);}onMounted(getUserRepositories);watch(user,getUserRepositories);return {count,repositories:repositories,getUserRepositories:getUserRepositories,handleClick}}}</script>
现在把watch
放setup
里,通过toRefs
定义响应式引用,如const {user} = toRefs(props)
,然后监听该引用并指定回调,watch(user,getUserRepositories)
。
参考文章
Vue官网:组合式API
如果觉得《组合式API》对你有帮助,请点赞、收藏,并留下你的观点哦!