如何用Vue和Tailwind克隆Twitter主页

211 阅读6分钟

用Vue和Tailwind克隆Twitter主页

如今,Web开发项目经常使用CSS框架,以便对UI进行适当和有效的风格设计。使用这些CSS框架可以节省设计时间,因为大部分的UI元素和类都可以随时使用。然而,一个缺点是,Bootstrap、Bulma等CSS框架的样式是硬性规定的。

几乎没有定制的可能。然而,有一个解决方案是灵活的,轻量级的,可根据需求定制的。这个解决方案就是Tailwind CSS

Tailwind CSS是一个以实用为先的CSS框架,它包含的类可以直接在你的标记中构成任何设计。它很容易定制、适应和构建。因为它是轻量级的,所以不会使项目变得庞大。它是一个低级别的CSS框架,可以适应不断变化的设计实现。

在本教程中,我们将学习如何将Tailwind CSS集成到Vue项目中。我们将通过每个配置,在Vue项目中设置tailwind CSS。然后,我们将使用Tailwind CSS提供的CSS类来创建一个Twitter主页UI克隆。

那么,让我们开始吧

创建Vue项目

首先,我们将使用Vue CLI创建一个Vue项目。如果你还没有安装Vue CLI,你可以通过执行以下命令简单地安装它。

npm install -g @vue/cli
# OR
yarn global add @vue/cli

安装成功后,我们可以用它来创建Vue项目。我们可以通过在终端执行以下命令来创建一个新的Vue项目。

vue create twitter-clone

记住要选择Vue版本3。所有其他配置可以是默认的,也可以根据需求定制。

项目成功创建后,我们可以通过运行以下命令为其服务。

npm serve

整合Tailwind CSS

Tailwind CSS与Vue CLI的整合步骤相当简单。

为了整合Tailwind CSS,我们可以在项目终端简单地执行以下命令。

npm install tailwindcss @tailwindcss/ui

然后,我们需要在项目根目录下创建两个配置文件

首先,我们需要创建一个名为Postcss.config.js的文件。这个文件将保存运行CSS后事件的所有配置。在这里,我们只需要将tailwindcss 包和autoprefixer

下面的代码片段中提供了所需的配置。

const purgecss = require('@fullhuman/postcss-purgecss')({
  // Specify the paths to all of the template files in your project
  content: [
    './src/**/*.html',
    './src/**/*.vue',
    './src/**/*.jsx',
    // etc.
  ],
  // Include any special characters you're using in this regular expression
  defaultExtractor: content => content.match(/[\w-/.:]+(?<!:)/g) || []
});

module.exports = {
  plugins: [
    require('tailwindcss'),
    require('autoprefixer'),
    ...process.env.NODE_ENV == 'production'
      ? [purgecss]
      : []
  ]
};

我们需要创建的另一个配置文件叫做Tailwind.config.js。这个文件将容纳Tailwind CSS的所有配置。该文件将整体主题属性与颜色、字体家族一起导出。Vue项目和tailwindcss 插件之间的连接是由这个配置文件建立的。

这些配置可以在下面的代码段中找到。

const defaultTheme = require('tailwindcss/defaultTheme');

module.exports = {
  theme: {
    container: {
      center: true
    },
    extend: {
      fontFamily: {
        sans: ['Inter var', ...defaultTheme.fontFamily.sans],
      },
      colors: {
        'blue': '#1DA1F2',
        'darkblue': '#2795D9',
        'lightblue': '#EFF9FF',
        'dark': '#657786',
        'light': '#AAB8C2',
        'lighter': '#E1E8ED',
        'lightest': '#F5F8FA',
      }
    },
  },
  plugins: [
    require('@tailwindcss/ui'),
  ]
};

接下来,我们需要在**./assets/styles中创建一个名为tailwind.css**的文件。在该文件中,我们需要包括Tailwind CSS的基本CSS样式、组件和实用样式类,如下面的代码片段所示。

@tailwind  base;
@tailwind  components;
@tailwind  utilities;

因此,我们已经成功地将Tailwind CSS集成到我们的Vue项目中。

由于我们要使用Fontawesome软件包中的一些图标,我们需要将它们添加到我们的项目中。现在,我们只是要在index.js文件中包括Fontawesome图标的CDN,如下面的代码片段所示。

<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
<link rel="stylesheet" href="https://rsms.me/inter/inter.css">

由于我们所有的配置已经完成,项目的要求也已经添加。

现在,我们可以使用Tailwind CSS作为造型组件来实现我们的Twitter克隆用户界面。

实现Twitter主屏幕的克隆UI

创建侧边菜单

首先,我们要创建一个侧面菜单部分。这个部分将包括导航到其他软件包的菜单选项。

App.vue文件中,我们需要用以下代码段的代码替换默认代码。

export default {
  name: 'app',
  components: {
  },
  data() {
    return {
      tabs: [
        {icon: 'fas fa-home', title: 'Home', id:'home'},
        {icon: 'fas fa-hashtag', title: 'Explore', id: 'explore'},
        {icon: 'far fa-bell', title: 'Notifications', id: 'notifications'},
        {icon: 'far fa-envelope', title: 'Messages', id: 'messages'},
        {icon: 'far fa-bookmark', title: 'Bookmarks', id: 'bookmarks'},
        {icon: 'fas fa-clipboard-list', title: 'Lists', id: 'lists'},
        {icon: 'far fa-user', title: 'Profile', id: 'profile'},
        {icon: 'fas fa-ellipsis-h', title: 'More', id: 'more'}
      ],
    }
  }
}

为了轻松地创建菜单选项,我们将循环浏览一个数组。上面代码片断中提供的标签数组包括每个菜单选项的图标名称、标题和ID。

现在,这一部分的UI模板代码在下面的代码片段中提供。

<template>
  <div id="app" class="flex container h-screen w-full">
    <div class="lg:w-1/5 border-r border-lighter px-2 lg:px-6 py-2 flex flex-col justify-between">
      <div>
        <button class="h-12 w-12 hover:bg-lightblue text-3xl rounded-full text-blue">
          <i class="fab fa-twitter"></i>
        </button>
        <div>
          <button v-for="(tab,index) in tabs" :key="index" @click="id = tab.id" :class="`focus:outline-none hover:text-blue flex items-center py-2 px-4 hover:bg-lightblue rounded-full mr-auto mb-3 ${ id === tab.id ? 'text-blue' : ''}`">
            <i :class="`${ tab.icon } text-2xl mr-4 text-left`"></i>
            <p class="text-lg font-semibold text-left hidden lg:block"> {{ tab.title }} </p>
          </button>
        </div>
        <button class="text-white bg-blue rounded-full font-semibold focus:outline-none w-12 h-12 lg:h-auto lg:w-full p-3 hover:bg-darkblue">
          <p class="hidden lg:block">Tweet</p>
          <i class="fas fa-plus lg:hidden"></i>
        </button>
      </div>
    </div>
  </div>  
</template>

这里使用的样式类都是来自Tailwind CSS。循环和逻辑操作是Vue编程生态系统的结果。

我们将得到侧面菜单部分,如下面的截图所示。

side menu section

添加侧边菜单下拉

现在,我们要在侧面菜单部分的底部添加一个下拉菜单。这个下拉菜单将容纳用户信息和一些按钮。

首先,我们需要定义一个布尔变量来处理这个下拉菜单的关闭和打开,如下面的代码片段所示。

dropdown: false,

接下来,我们需要将下拉模板代码添加到上层菜单部分下面,如下面的代码片断所示。

…….Upper Menu Section…
.
.
.
.
<div class="lg:w-full relative">
  <button @click="dropdown = !dropdown" class="flex items-center w-full hover:bg-lightblue rounded-full p-2 focus:outline-none">
    <img src="https://randomuser.me/api/portraits/men/11.jpg" class="w-10 h-10 rounded-full border border-lighter" />
    <div class="hidden lg:block ml-4">
      <p class="text-sm font-bold leading-tight"> Kriss Kawa </p>
      <p class="text-sm leading-tight"> @kriss </p>
    </div>
    <i class="hidden lg:block fas fa-angle-down ml-auto text-lg"></i>
  </button>
  <div v-if="dropdown === true" class="absolute bottom-0 left-0 w-64 rounded-lg shadow-md border-lightest bg-white mb-16">
    <button @click="dropdown = false" class="p-3 flex items-center w-full hover:bg-lightest p-2 focus:outline-none">
      <img src="https://randomuser.me/api/portraits/men/11.jpg" class="w-10 h-10 rounded-full border border-lighter" />
      <div class="ml-4">
        <p class="text-sm font-bold leading-tight"> Kriss Kawa </p>
        <p class="text-sm leading-tight"> @kriss </p>
      </div>
      <i class="fas fa-check ml-auto test-blue"></i>
    </button>
    <button @click="dropdown = false" class="w-full text-left hover:bg-lightest border-t border-lighter p-3 test-sm focus:outline-none">
      Add an existing account
    </button>
    <button @click="dropdown = false" class="w-full text-left hover:bg-lightest border-t border-lighter p-3 test-sm focus:outline-none">
      Log out @kriss
    </button>
  </div>
</div>

我们将得到如下代码片断所示的结果。

add side menu dropdown

创建一个趋势部分

现在,我们要把趋势部分添加到我们的用户界面。这个部分将显示在屏幕的右侧,并显示趋势性的话题。

为了添加这个部分,我们需要添加以下代码片段,就在侧面菜单的下面div

<!-- Tweet Section -->
    <div class="w-full md:w-1/2 h-full overflow-y-scroll">
    </div>
    <!-- Trending Section-->
    <div class="md:block hidden w-1/3 h-full border-l border-lighter py-2 px-6 overflow-y-scroll relative">
      <input class="pl-12 rounded-full w-full p-2 bg-lighter text-sm mb-4" placeholder="Search Twitter" />
      <i class="fas fa-search absolute left-0 top-0 mt-5 ml-12 text-sm text-light"></i>
    </div>

我们将得到下面的屏幕截图中的结果。

create trending section

在这里,我们已经有了趋势部分和一个搜索栏。现在,我们要在其中添加趋势主题部分。

为此,我们需要定义一个数组来保存趋势主题的数据,如下面的代码片段所示。

trending: [
        {top: 'techies all around', title: 'Tech', bottom: 'The technology'},
        {top: 'Apps', title: 'Flutter', bottom: '100K Tweets'},
        {top: 'Animals', title: 'Shark larger than Great white', bottom: '115k tweets'},
        {top: 'The techies nation', title: '2m servers', bottom: '30k tweets'},
      ],

现在,我们将循环浏览trending 数组,并使用下面的代码片段来显示潮流话题的UI模板。

<input class="pl-12 rounded-full w-full p-2 bg-lighter text-sm mb-4" placeholder="Search Twitter" />
      <i class="fas fa-search absolute left-0 top-0 mt-5 ml-12 text-sm text-light"></i>
      <div class="w-full rounded-lg bg-lightest">
        <div class="flex items-center justify-between p-3">
          <p class="text-lg font-bold">Trends for You</p>
          <i class="fas fa-cog text-lg text-blue"></i>
        </div>
        <button v-for="(trend,index) in trending" :key="index" class="w-full flex justify-between hover:bg-lighter p-3 border-t border-lighter">
          <div>
            <p class="text-xs text-left leading-tight text-dark"> {{ trend.top}} </p>
            <p class="font-semibold text-sm text-left leading-tight"> {{ trend.title}} </p>
            <p class="text-left text-sm leading-tight text-dark"> {{ trend.bottom}} </p>
          </div>
          <i class="fas fa-angle-down text-lg text-dark"></i>
        </button>
        <button class="p-3 w-full hover:bg-lighter text-left text-blue border-t border-lighter">
          Show More
        </button>
      </div>

我们将得到如下截图所示的趋势主题部分。

trending topics section

现在,就在热门话题部分的下面,我们将添加 "关注 "部分。关注部分将显示用户应该关注的用户账户。

首先,我们需要定义一个数组来保存用户账户的数据,包括图片、名字和用户名,如下面的代码片段所示。

follow: [
        {src: 'https://randomuser.me/api/portraits/men/79.jpg', name: 'Kriss Kovan', handle: '@kriss'},
        {src: 'https://randomuser.me/api/portraits/men/70.jpg', name: 'Danny D', handle: '@theD'},
        {src: 'https://randomuser.me/api/portraits/men/27.jpg', name: 'Hubert Aly', handle: '@alyway'}
      ],

现在,为了添加 "关注 "部分的用户界面,我们需要使用下面代码片段中的代码,就在趋势主题的下面div

<div class="w-full rounded-lg bg-lightest my-4">
  <div class=" p-3">
    <p class="text-lg font-bold">Who to Follow</p>
  </div>
  <button v-for="(user,index) in follow" :key="index" class="w-full flex hover:bg-lighter p-3 border-t border-lighter">
    <img :src="`${ user.src }`" class="w-12 h-12 rounded-full border border-lighter" />
    <div class="hidden lg:block ml-4">
      <p class="text-sm font-bold leading-tight"> {{ user.name }} </p>
      <p class="text-sm leading-tight"> {{ user.handle }} </p>
    </div>
    <button class="ml-auto text-sm text-blue py-1 px-4 rounded-full border-2 border-blue">
      Follow
    </button>
  </button>
  <button class="p-3 w-full hover:bg-lighter text-left text-blue border-t border-lighter">
    Show More
  </button>
</div>

我们将得到如下截图所示的结果。

follow section

创建中间的推特部分

现在,我们要创建推特部分,这是用户界面的中间部分。这个部分将包含一个标题,一个用于输入推文的推文输入部分,以及输入部分下面的推文显示部分。

为此,我们将从标题部分开始。标题部分将包含一个标题和一个图标。

这方面的代码在下面的代码片断中提供。

<!-- Tweet Section -->
    <div class="w-full md:w-1/2 h-full overflow-y-scroll">
      <div class="px-5 py-3 border-b border-lighter flex items-center justify-between">
        <h1 class="text-xl font-bold">Home</h1>
        <i class="far fa-star text-xl text-blue"></i>
      </div>
    </div>

我们将得到标题部分,如下面的代码片断所示。

middle tweet section

接下来,是Tweet输入部分。鸣叫输入部分将包含一个写鸣叫的文本编辑器和一个将鸣叫添加到鸣叫列表中的按钮。

我们需要定义一些变量,这些变量将保存推文列表以及当前推文的文本。

tweetList: [
        {text: 'Why am I a nerd!'}
      ],
tweet: {text: ''}

接下来,我们需要实现一个函数,一旦点击推文按钮,就将当前的推文添加到推文列表中。该函数的整体实现在下面的代码片段中提供。

methods: {
    addTweet () {
      let temp = {
        text: this.tweet.text
      };
      this.tweetList.push(temp)
	this.tweet = {
        text : ""
      }

    }
  }

现在,我们需要通过使用下面的代码片断,在标题部分下面添加推文输入部分的用户界面。

<div class="px-5 py-3 border-b-8 border-lighter flex">
  <div class="flex-none">
    <img src="https://randomuser.me/api/portraits/men/11.jpg" class="flex-none w-12 h-12 rounded-full border border-lighter"/>
  </div>
  <form v-on:submit.prevent = "addTweet" class="w-full px-4 relative">
    <textarea v-model="tweet.text" placeholder="What's up?" class="mt-3 pb-3 w-full focus:outline-none"/>
    <div class="flex items-center">
      <i class="text-lg text-blue mr-4 far fa-image"></i>
      <i class="text-lg text-blue mr-4 fas fa-film"></i>
      <i class="text-lg text-blue mr-4 far fa-chart-bar"></i>
      <i class="text-lg text-blue mr-4 far fa-smile"></i>
    </div>
    <button type="submit" class="h-10 px-4 text-white font-semibold bg-blue hover:bg-darkblue focus:outline-none rounded-full absolute bottom-0 right-0">
      Tweet
    </button>
  </form>
</div>

这里,我们使用了form 标签,并在form 标签的submit 事件中调用我们的addTweet 函数。buttontype 提交,这意味着按下按钮将触发提交事件,反过来调用addTweet 函数。

我们可以看到Tweet输入部分,如下面的屏幕截图所示。

tweet input section

现在,我们需要在Tweet输入部分下面显示Tweet列表。为此,我们需要使用以下代码片断的代码。

<div class="flex flex-col-reverse">
  <div v-for="(tweet, index) in tweetList" :key="index" class="w-full p-4 border-b hover:bg-lighter flex">
    <div class="flex-none mr-4">
      <img src="https://randomuser.me/api/portraits/men/11.jpg" class="h-12 w-12 rounded-full flex-none"/>
    </div>
    <div class="w-full">
      <div class="flex items-center w-full">
        <p class="font-semibold"> Kriss Kawa </p>
        <p class="text-sm text-dark ml-2"> @kriss </p>
        <p class="text-sm text-dark ml-2"> 2 sec </p>
        <i class="fas fa-angle-down text-dark ml-auto"></i>
      </div>
      <p class="py-2">
        {{ tweet.text }}
      </p>
      <div class="flex items-center justify-between w-full">
        <div class="flex items-center text-sm text-dark">
          <i class="far fa-comment mr-3"></i>
          <p> 1 </p>
        </div>
        <div class="flex items-center text-sm text-dark">
          <i class="fas fa-retweet mr-3"></i>
          <p> 0 </p>
        </div>
        <div class="flex items-center text-sm text-dark">
          <i class="fas fa-heart mr-3"></i>
          <p> 2 </p>
        </div>
        <div class="flex items-center text-sm text-dark">
          <i class="fas fa-share-square mr-3"></i>
        </div>
      </div>
    </div>
  </div>
</div>

现在,我们可以将我们的推文添加到推文列表中,如下面的演示所示。

show tweet list

现在,我们也要添加一些来自用户的模拟推文。为此,我们需要定义一个数组变量,以保存有关用户图像、姓名、用户名、推文、时间、喜欢和评论的信息,如下面的代码片段所示。

following: [
        {src: 'https://randomuser.me/api/portraits/women/52.jpg', name: 'Giza Lamo', handle: '@giza', time: '1.2 hr', tweet: 'The very essence of TailWindCSS??', comments: '500', retweets: '250', like: '52,003'},
        {src: 'https://randomuser.me/api/portraits/women/62.jpg', name: 'Doug mama', handle: '@mama', time: '25 min', tweet: 'Should I use Flutter now?', comments: '1000', retweets: '500', like: '70,003'},
        {src: 'https://randomuser.me/api/portraits/men/63.jpg', name: 'Ezy Pzy', handle: '@ezypzy', time: '2.7 hr', tweet: 'Get Ready for the tech revolution', comments: '10,000', retweets: '100,002', like: '200,003'},
      ],

现在,我们只需要循环浏览这个数组,以显示这些推文。为此,我们可以使用以下代码片断的代码。

<div v-for="(follow,index) in following" :key="index" class="w-full p-4 border-b hover:bg-lighter flex">
  <div class="flex-none mr-4">
    <img :src="`${follow.src}`" class="h-12 w-12 rounded-full flex-none"/>
  </div>
  <div class="w-full">
    <div class="flex items-center w-full">
      <p class="font-semibold"> {{ follow.name }} </p>
      <p class="text-sm text-dark ml-2"> {{ follow.handle }} </p>
      <p class="text-sm text-dark ml-2"> {{ follow.time }} </p>
      <i class="fas fa-angle-down text-dark ml-auto"></i>
    </div>
    <p class="py-2">
      {{ follow.tweet }}
    </p>
    <div class="flex items-center justify-between w-full">
      <div class="flex items-center text-sm text-dark">
        <i class="far fa-comment mr-3"></i>
        <p> {{ follow.comments }} </p>
      </div>
      <div class="flex items-center text-sm text-dark">
        <i class="fas fa-retweet mr-3"></i>
        <p> {{ follow.retweets }} </p>
      </div>
      <div class="flex items-center text-sm text-dark">
        <i class="fas fa-heart mr-3"></i>
        <p> {{ follow.like }} </p>
      </div>
      <div class="flex items-center text-sm text-dark">
        <i class="fas fa-share-square mr-3"></i>
      </div>
    </div>
  </div>
</div>

因此,我们将得到如下代码片断所示的结果。

complete twitter clone with vue and tailwind

最后,我们已经成功地使用Vue版本3和Tailwind CSS实现了Twitter主页的用户界面克隆。

总结

本教程的主要目的是展示Tailwind CSS在Vue生态系统中的集成和使用,并在此过程中创建Twitter主页的UI克隆。尾风CSS很容易配置,只需要几个配置文件和导入。使用这些Tailwind CSS类,就像普通的CSS类一样简单易行。

这使得用户界面的开发变得更加简单和容易。布局设计以及其他风格的实现都非常棒。我们可以从Twitter主页的最终结果中看到,Tailwind CSS如何使设计实现变得更容易。在Tailwind CSS中,类的属性与普通CSS相似,可以根据需要进行定制。

主要的优点是,Tailwind CSS不象其他CSS框架那样强加样式实现,如Bootstrap。Bulma等。