使用 Vue、Bulma 和 Airtable 构建作品集网站
离开全栈训练营已经三年了,这是我第一次需要搭建一个作品集网站。我想做一个相对简单、易于更新、并且随着时间的推移易于扩展和改进的网站。
这个教程完美吗?当然完美!这是我写的第一篇教程,而且我一直在自学 Vue,所以有些部分我肯定可以改进(如果你觉得有什么不同,请在评论区告诉我)。不过,我知道这篇文章可能会对某些人有所帮助!
您可以在 github 上看到我的整个投资组合的代码,这些代码是从这个起点创建的,网址为:https://github.com/markjohnson303/portfolio
完成的示例位于hellomark.dev,但这是一个正在进行的工作,您可能会看到一些与此处描述的不同之处。
工具
Vue.js:我选择 Vue 来做这个项目,是因为它是我最熟悉的框架。有人可能会说,对于像这样的小项目来说,它有点大材小用,对你来说可能确实如此。它对我来说很合适,因为它使用起来很顺手,而且足够灵活,足以应付我将来的各种需求。我也希望在下一个职位上使用它,所以何乐而不为呢!
Bulma:在这个项目之前我从未使用过 Bulma,但我希望它能让我快速上线网站,并随着时间的推移轻松改进样式。Bulma 易于学习,但易于构建。它没有世界上最大的组件库,但它的组件库构建得非常扎实。
Airtable:我一直想在一个项目中使用 Airtable。据 Airtable 介绍,它“一半是电子表格,一半是数据库”,设计灵活,适用于各种用途。我在这里将它用作内容管理系统 (CMS),因为它非常易于使用,并且拥有强大的 API 和完善的文档(可根据您的数据库进行定制)。现在它已经设置好了,我可以在整个网站上使用它来做各种有趣的事情。而且它是免费的!
入门
首先需要设置你的 Vue 项目。我们将使用 Vue CLI 来搭建项目。请确保你已经安装了 Vue 和 Vue CLI:
$ npm install -g vue$ npm install -g @vue/cli
然后创建你的项目:$ vue create portfolio
然后启动它:$ npm run serve
Vue CLI 提供了一个非常有用的起点,其中包含我们需要的大量文件和文件夹。我们将以此为基础进行构建。
现在让我们添加我们的 CSS 框架 Bulma。$ npm install --s bulma
并将 Sass 样式表添加到我们的App.vue文件中
<style lang="sass">
@import "~bulma/bulma.sass"
</style>
您可以在此处(导入上方)对 Bulma 默认值进行任何调整。
我们将安装 Axios(用于与我们的 Airtable API 配合使用)$ npm install --s axios
我们需要VueSimpleMarkdown,这样我们就可以用 markdown 撰写和设计我们的帖子。
$ npm install -s vue-simple-markdown
我们main.js将输入:
import VueSimpleMarkdown from 'vue-simple-markdown'
import 'vue-simple-markdown/dist/vue-simple-markdown.css'
Vue.use(VueSimpleMarkdown)
设置我们的路线
我们将为该网站设置 5 个主要路由:关于、联系、主页、项目和项目。让我们在 In 中设置它们src/router.js。
import Vue from "vue";
import Router from "vue-router";
import Home from "./views/Home.vue";
import About from "./views/About.vue";
import Contacts from "./views/Contact.vue";
import Projects from "./views/Projects.vue"
import Project from "./views/Project.vue"
Vue.use(Router);
export default new Router({
  mode: "history",
  base: process.env.BASE_URL,
  routes: [
    {
      path: "/",
      name: "home",
      component: Home
    },
    {
      path: "/about",
      name: "about",
      component: About
    },
    {
      path: "/contact",
      name: "contact",
      component: Contact
    },
    {
      path: "/projects",
      name: "projects",
      component: Projects
    },
    {
      path: "/project/:slug",
      name: "project",
      component: Project
    }
  ]
});
}
奇怪的是path: "/project/:slug"。稍后我们将使用此路线根据 slug 显示来自 Airtable 的单个项目。
我们还将为每个 创建一个空组件src/views,例如这里Contact.vue。我们稍后会填充它们。
<template>
  <div>
  </div>
</template>
<script>
export default {
  name: "contact",
};
</script>
添加页眉和页脚
让我们添加页眉(带导航)和页脚,添加一些样式,并运用一些 Vue 的魔法,让它在移动设备上运行。我们将这段代码添加到App.vue每个视图中,以便它能够显示出来。
<template>
  <div id="app">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <nav class="navbar" role="navigation" aria-label="main navigation">
      <div class="navbar-brand">
        <router-link class="navbar-item" to="/">
          <img src="./assets/name-mark.jpg" width="112" height="28">
        </router-link>
        <a role="button" class="navbar-burger burger" aria-label="menu" aria-expanded="false" data-target="navbarBasicExample" :class="{ 'is-active': showNav }" @click="showNav = !showNav">
          <span aria-hidden="true"></span>
          <span aria-hidden="true"></span>
          <span aria-hidden="true"></span>
        </a>
      </div>
      <div id="navbarBasicExample" class="navbar-menu" :class="{ 'is-active': showNav }">
        <div class="navbar-start">
        </div>
        <div class="navbar-end">
          <router-link to="/" class="navbar-item">
            Home
          </router-link>
          <router-link to="/about" class="navbar-item">
           About
          </router-link>
          <router-link to="/projects" class="navbar-item">
           Projects
          </router-link>
          <router-link to="/contact" class="navbar-item">
           Contact
          </router-link>
       </div>
     </div>
   </nav>
   <router-view />
   <footer class="footer">
    <div class="content has-text-centered">
      <p>
        Built by Mark Johnson with Vue.js, Bulma, and Airtable.
      </p>
    </div>
  </footer>
</div>
</template>
<script>
  export default {
    name: "App",
    data() {
      return{
        showNav: false
      }
    },
  };
</script>
<style type="text/css">
#app {
  min-height: 100vh;
  overflow: hidden;
  display: block;
  position: relative;
  padding-bottom: 168px; /* height of your footer */
}
footer {
 position: absolute;
 bottom: 0;
 width: 100%;
}
</style>
<style lang="sass">
@import "~bulma/bulma.sass"
</style>
静态页面
“关于”、“主页”和“联系”页面没有任何动态内容,您可以随意添加任何您喜欢的内容。例如,以下是我在主页上所做的。我在这里保持了简洁,但您可以根据自己的喜好进行修饰。
<template>
  <div>
    <div class="hero is-cover is-relative is-fullheight-with-navbar is-primary">
        <div class="hero-body">
            <div class="container">
                <h1 class="title is-1">Hello, I'm Mark.</h1>
                <h2 class="subtitle is-3">A customer focused, entrepreneurially minded web developer.</h2>
            </div>
        </div>
    </div>
  </div>
</template>
<script>
export default {
  name: "home",
};
</script>
构建项目页面
项目页面开始变得有趣起来。我们将从 Airtable 中提取信息,并为每个项目显示一个摘要卡。
设置 Airtable
在 Airtable 上创建一个名为“项目”的新库。创建以下字段:“标题”(单行文本)、“slug”(单行文本)、“正文”(长文本)、“图片”(附件)、“发布日期”(日期)、“已发布”(复选框)、“摘录”(单行文本)。
瞧!一个简单的 CMS 就完成了!只需在其中填充几行虚拟数据,就能清楚地看到正在处理的内容。确保“slug”是唯一的!我们将在后续步骤中使用它来构建 URL。
构建用于展示项目的卡片
我们将创建一个组件来显示项目摘要。它可重复使用,以便您以后可以用它创建博客!
在src/components新建一个文件,命名为PostCard.vue。填写如下内容:
<template>
    <div class="post-card">
        <div class="card">
            <div class="card-image">
                <figure class="image is-square">
                    <img :src="image" alt="Placeholder image">
                </figure>
            </div>
            <div class="card-content">
                <div class="media">
                    <div class="media-content">
                        <p class="title is-4">{{title}}</p>
                        <p class="subtitle is-6">{{date}}</p>
                    </div>
                </div>
                <div class="content">
                    <p>{{snippet}}</p>
                    <router-link :to="'/project/'+slug" class="button is-fullwidth">View Project</router-link>
                </div>
            </div>
        </div>
    </div>
</template>
<script>
    export default {
        name: "PostCard",
        props: {
            title: String,
            date: String,
            snippet: String,
            image: String,
            slug: String
        }
    };
</script>
从 Airtable 的 API 获取项目后,我们将从“项目”页面引入道具。它们会将内容和完整项目视图的链接填充到模板中。
创建服务来引入项目
让我们建立与 Airtable API 的连接。在 创建一个目录src/services,并在其中放置一个名为 的文件ProjectsService.js。
在项目服务中,我们将使用 Axios 调用 Airtable API 并获取所有项目。您的文件应如下所示:
import axios from 'axios'
const Axios = axios.create({
  baseURL: "https://api.airtable.com/v0/[YOUR APP ID]/Projects"
});
Axios.defaults.headers.common = {'Authorization': `Bearer ` + process.env.VUE_APP_AIRTABLEKEY}
export default{
  getProjects() {
    return Axios.get()
  }
}
您需要设置baseURLAirtable 基础的 ID。您可以在 Airtable 的 URL 中找到它。
您还需要从 Airtable 添加您的 API 密钥。我将我的密钥放在.env.localVue 项目根目录中名为 的文件中。此文件已列在 .gitignore 中,因此您无需担心它被暴露。文件中的内容如下VUE_APP_AIRTABLEKEY=[YOUR API KEY]:
最后,我们导出一个在 baseURL 中调用 API 端点的 get 函数。
显示项目卡
我们将在“项目”视图中显示项目的卡片。在您的Projects.vue模板中:
<template>
    <div>
        <section class="hero is-medium is-primary is-bold">
            <div class="hero-body">
                <div class="container">
                    <h1 class="title is-2">
                        Projects that I have built
                    </h1>
                </div>
            </div>
        </section>
        <section class="section">
            <div class="container is-fluid">
                <div class="columns is-multiline">
                        <div class="column is-one-third" v-for="project in projects">
                            <post-card v-bind="project"></post-card>
                        </div>              
                </div>
            </div>
        </section>
    </div>
</template>
这里要注意的是,v-for="project in projects"我们post-card为每个项目创建一个实例,并使用传递项目详细信息v-bind。
模板的脚本部分如下所示:
<script>
    import ProjectsService from '@/services/ProjectsService'
    import PostCard from '@/components/PostCard'
    export default {
        name: "projects",
        components: {
            PostCard
        },
        data() {
            return{
                airtableResponse: []
            }
        },
        mounted: function () {
            let self = this
            async function getProjects() {
                try{
                    const response = await ProjectsService.getProjects()
                    console.log(response)
                    self.airtableResponse = response.data.records
                }catch(err){
                    console.log(err)
                }
                }
              getProjects()         
        },
        computed: {
            projects(){
                let self = this
                let projectList = []
                for (var i = 0; i < self.airtableResponse.length; i++) {
                    if (self.airtableResponse[i].fields.Published){
                        let project = {
                            title: self.airtableResponse[i].fields.Title,
                            date: self.airtableResponse[i].fields["Date Published"],
                            snippet: self.airtableResponse[i].fields.Excerpt,
                            image: self.airtableResponse[i].fields.Image[0].url,
                            slug: self.airtableResponse[i].fields.slug
                        }
                        projectList.push(project)
                    }
                }
                return projectList
            }
        }
    };
</script>
从顶部开始,发生的事情如下:
- 导入我们之前创建的 ProjectsService 和 PostCard
- 设置一个变量来保存来自 Airtable 的响应
- 当组件挂载的时候,调用我们在服务中设置的端点。
- 将我们需要的响应部分放入 airtableResponse 变量中。
- 使用名为“Projects”的数组创建计算属性,其中 Airtable 响应中的每个已发布项目都有一个对象,每张卡片都需要一个变量。
如果一切顺利,您应该能够/projects在网格中加载并查看在 Airtable 中创建的每个项目
克里特岛项目视图
还记得我们路由器设置中的这段代码吗?
{
 path: "/project/:slug",
 name: "project",
 component: Project
}
它将使我们能够访问我们的 Project 组件中的 slug,并将其传递到我们的 Projects Service 中,以便我们可以使用该 slug Airtable 检索该项目的所有信息。
让我们在中添加一个调用ProjectsService.js:
getProject(slug) {
  return Axios.get("?filterByFormula={Slug}='" + slug + "'")
}
我们在这里使用 Airtable 的 API 功能来搜索包含 slug 的帖子并返回它。
现在让我们创建我们的项目视图模板:
<template>
    <div>
        <section class="hero is-medium is-primary is-bold">
            <div class="hero-body">
                <div class="container">
                    <h1 class="title is-2">
                        {{project.title}}
                    </h1>
                    <h2 class="subtitle is-4">
                        {{project.snippet}}
                    </h2>
                </div>
            </div>
        </section>
        <section class="section">
            <div class="container is-fluid">
                <div class="columns">
                    <div class="column is-two-thirds">
                        <vue-simple-markdown :source="project.body"></vue-simple-markdown>
                    </div>
                    <div class="column is-one-third">
                        <div class="columns is-multiline">
                            <div class="column is-full" v-for="image in project.images">
                                <img :src="image.url"/>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </section>
    </div>
</template>
此模板使用了我们之前安装的 VueSimpleMarkdown 插件。这意味着您可以在 Airtable 的 body 字段中使用 markdown 来设置项目样式。我们将 body 显示在左侧的一列中,并将该项目的所有图片显示在右侧。
最后是项目组件的脚本部分:
<script>
    import ProjectsService from '@/services/ProjectsService'
    import PostCard from '@/components/PostCard'
    export default {
        name: "project",
        components: {
            PostCard
        },
        data() {
            return{
                airtableResponse: []
            }
        },
        mounted: function () {
            let self = this
            console.log("here 1")
            async function getProject() {
                try{
                    const response = await ProjectsService.getProject(self.$route.params.slug)
                    console.log(response)
                    self.airtableResponse = response.data.records
                }catch(err){
                    console.log(err)
                }
            }
            getProject()            
        },
        computed: {
            project(){
                let self = this
                if (self.airtableResponse[0]){
                    let thisProject = {
                        title: self.airtableResponse[0].fields.Title,
                        snippet: self.airtableResponse[0].fields.Excerpt,
                        images: self.airtableResponse[0].fields.Image,
                        body: self.airtableResponse[0].fields.Body
                    }
                    return thisProject
                }
            }
        }
    };
</script>
与“项目”视图类似,但这次我们将 slug 传递给调用getProject。如果 slug 是唯一的,我们应该只会收到一个响应。
前往 /projects/[your-slug] 查看您的项目!
结论
呼!好多内容!现在我们完成了,一个用 Vue 构建、用 Bulma 设置样式的简单 CMS 站点,可以实时显示数据。太酷了!
我将尝试各种样式,添加一些新功能,并清理一些东西,所以请关注hellomark.dev看看接下来会发生什么!
请告诉我您对本教程的看法以及您有的任何问题!
文章来源:https://dev.to/markjohnson303/building-a-portfolio-site-with-vue-bulma-and-airtable-5a58 后端开发教程 - Java、Spring Boot 实战 - msg200.com
            后端开发教程 - Java、Spring Boot 实战 - msg200.com