这个教程里你会学到:
- 如何使用composition API
- 如何使用vue-router
- 如何利用json-server做一个假服务器
- 如何外部化setup方法里面的函数然后引入以便复用
- 如何接收props在组件中并且处理这个数据
1. 创建工程环境
此项目需要nodejs的支持,如果你还没有安装那么就到官网去下载安装下。我们需要用到NPM这个nodejs的依赖管理器。此工程需要用到vue-cli创建,如果你还没有安装,那么就全局安装下。
npm install -g @vue/cli
这样我们就可以用vue cli来创建我们的项目了。
vue create blog
查看下package.json, 确保你安装的vue版本是vuejs 3, 否则利用不了composition API这个特性。接下来我们来安装vue-router和bootstrap:
vue add router
npm install bootstrap
接下来我们通过src/main.js来引入bootstrap css。
import '../node_modules/bootstrap/dist/css/bootstrap.min.css'
这样我们就可以在项目种直接引用bootstrap css了。
接下来我们来做一套Json数据,然后通过json server插件来使其变成一个服务器的API接口,通过这个接口可以请求博客列表和单个的博客内容。
在src目录下创建文件src/data/posts.json,填充下下面的内容:
{
"posts":[
{
"id": 1,
"title": "this is post title 1",
"time": "2021-05-06 15:00:00",
"content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
},
{
"id": 2,
"title": "this is post title 2",
"time": "2021-05-06 17:03:00",
"content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
},
{
"id": 3,
"title": "this is post title 3",
"time": "2021-05-06 18:20:00",
"content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
},
{
"id": 4,
"title": "this is post title 4",
"time": "2021-05-06 19:30:00",
"content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
},
{
"id": 5,
"title": "this is post title 5",
"time": "2021-05-06 20:43:00",
"content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
},
{
"id": 6,
"title": "this is post title 6",
"time": "2021-05-06 21:48:00",
"content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
}
]
}
执行命令:
json-server --watch src/data/posts.json
这样会自动生成API接口,如:
http://localhost:3000/posts --博客列表
http://localhost:3000/posts/1 --单个博文
我们可以请求这个接口来模拟服务器数据。
2. 输出博客列表
首先我们先创建一个vue组件来显示列表种的单个博客,通过把这个组件引入到Home.vue中来显示博客列表。创建组件:
src/components/Singlepost.vue
在Home这个大的组件中引入:
src/views/Home.vue:
<template>
<div class="home container">
<!--如果有大于0个post, 那么就输出,否则显示no posts found 用v-for来直接遍历出单个post-->
<div v-if="posts.length">
<Singlepost v-for="post in posts" :key="post.id" :post="post"></Singlepost>
</div>
<p v-else>no posts found</p>
</div>
</template>
<script>
//把Singlepost组件引入
import Singlepost from "../components/Singlepost";
import {ref} from "vue";
export default {
name: 'Home',
components: {
Singlepost
},
setup(){
const posts = ref([]);
let load = async () => {
//这里其实可以用try和catch来获取可能出现的错误
let res = await fetch('http://localhost:3000/posts')
//ref有个属性叫value,赋值这个value
posts.value = await res.json()
};
load();
return {
posts
}
}
}
</script>
单个博文的视图组件:
src/components/SinglePost.vue
<template>
<div class="container">
<div class="row justify-content-center">
<div class="col-9">
<div class="card mb-4">
<div class="card-header text-start">
<!--注意:to的写法,本人传入的是名称post和一个参数id,模板对应的是src/views/Post.vue-->
<router-link :to="{name:'post', params:{id:post.id}}">{{post.title}}</router-link>-{{post.time}}
</div>
<div class="card-body text-start">
{{excerpt}}
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import {computed} from "vue";
export default {
name: "Singlepost",
props:["post"],
setup(props){
//注意一下props.post这个格式来引入props数据
const excerpt = computed(() => {
//在首页显示的是略文,显示全文的前50个字符,其余用...替代,在单个博文页面的时候再全部显示
return props.post.content.substring(0, 50)+"...";
})
return {
excerpt
}
}
}
</script>
接下来我们修改下src/router/index.js使得单个博文的路由:
在routes = []里面添加:
import Post from "../views/Post.vue";
...
{
path:'/post/:id',
name:'post',
component: () => Post,
//接收props的时候注意下,接收的是id这个prop
props:true
}
...
别忘了创建src/views/Post.vue这个文件。
现在我们看下首页:
3. 编写单个博文组件
现在我们来写src/views/Post.vue
<template>
<div class="container">
<div class="row justify-content-center">
<div class="col-9">
<div class="card mb-4">
<div class="card-header text-start">
{{post.title}}-{{post.time}}
</div>
<div class="card-body text-start">
<!-- 输出博客全文-->
{{post.content}}
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import {ref} from "vue";
export default {
name: "Post",
props:["id"],
setup(props){
//在setup()里引入props
const post = ref({})
const load = async () => {
let res = await fetch("http://localhost:3000/posts/"+props.id)
post.value = await res.json()
}
load()
return {
post
}
}
}
</script>
<style scoped>
</style>
这个文件比较好理解,所以就不详细解释了。
4.外部化setup()里面的方法以便复用
通常情况下我会创建一个composables这个文件夹,创建getPosts.js。
src/composables/getPosts.js
import {ref} from "vue";
const getPosts = () => {
const posts = ref([]);
let load = async () => {
let res = await fetch('http://localhost:3000/posts')
posts.value = await res.json()
console.log(posts.value)
};
return {
posts, load
}
}
export default getPosts
这样我们在home.vue里引入的时候就更简洁了。
<template>
<div class="home container">
<!--如果有大于0个post, 那么就输出,否则显示no posts found 用v-for来直接遍历出单个post-->
<div v-if="posts.length">
<Singlepost v-for="post in posts" :key="post.id" :post="post"></Singlepost>
</div>
<p v-else>no posts found</p>
</div>
</template>
<script>
//把Singlepost组件引入
import Singlepost from "../components/Singlepost";
import getPosts from "../composables/getPosts";
export default {
name: 'Home',
components: {
Singlepost
},
setup(){
const {posts, load} = getPosts();
load();
return {
posts
}
}
}
</script>
如果你的逻辑比较多,就可以用这个方法来外部化众多的逻辑。