大前端开发

从零开始:打造创业公司官网——(二)前端实现篇

2020-02-10  本文已影响0人  思考蛙

本文使用「署名 4.0 国际 (CC BY 4.0)」许可协议,欢迎转载、或重新修改使用,但需要注明来源。 署名 4.0 国际 (CC BY 4.0)

此系列共分以下几篇

零、项目规划
一、UI 设计
二、前端实现篇 本篇
三、项目运维

在规划篇和设计篇中已经确定我们的需求,前端的技术实现层面我们选中了 nuxtjs 这个实现 vuejs ssr 的框架,目的是为之后的扩展打下一个好的基础,比如增加资讯页面、作品详情页面、Blog等。

结合设计稿,我们本来计划是用一些第三方的UI框架或者是直接写一套样式进来,但是考虑这套设计稿中的色彩、元素和预留的一些组件扩展,比如Button、Text、Card等这些组件在以后的业务中也会经常用到,虽然有很多前端框架实现的很好,但是并不是我们自己创作的UI/UX,最终无法形成很好的品牌效应。

最终考虑还是决定自行实现,恰好刚完成的一个大数据展示的业务中用到 tailwindCss 这个框架,这个是工具优先的 css 框架,灵活性非常高,内部很好的实现了CSS中常用的工具,比如网格、网站自适应工具等,只需要按我们的设计进行定制规划就可以满足我们的需求,并且 nuxtjs 也实现了 tailwind 的插件。那么我就开始前端实现的旅程吧:

项目搭建

$ yarn create nuxt-app caixie-website-nuxtjs

# 执行选择结果如下
create-nuxt-app v2.14.0
✨  Generating Nuxt.js project in caixie-website-nuxtjs
? Project name caixie-website-nuxtjs
? Project description 北京采撷科技有限公司
? Author name baisheng
? Choose the package manager Yarn
? Choose UI framework Tailwind CSS
? Choose custom server framework None (Recommended)
? Choose Nuxt.js modules DotEnv
? Choose linting tools (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Choose test framework None
? Choose rendering mode Universal (SSR)
? Choose development tools (Press <space> to select, <a> to toggle all, <i> to invert selection)

🎉  Successfully created project caixie-website-nuxtjs

  To get started:

    cd caixie-website-nuxtjs
    yarn dev

  To build & start for production:

    cd caixie-website-nuxtjs
    yarn build
    yarn start

✨  Done in 68.03s.

接下来我们开始规划工程目录
工程目录如下

前端工程目录

components 目录是我们根据设计稿的规划,将整个页面进行组件化分形成的,方便后期调整各组件样式和结构。由于采用了 tailwind 去做样式,实现上就简单很多,拿 service 组件为例:
components/Service.vue

<template>
  <div id="service"
       class="container  bg-center bg-no-repeat bg-contain sm:pb-16 sm:mt-16 landing-changelog-bg text-center ">
    <span class="text-3xl font-black leading-tight text-indigo-100 sm:text-4xl">
      服务范围
    </span>
    <p class="mt-8 mb-12 font-light text-gray-700 sm:mt-4 sm:text-xl">
      <span class="block font-normal text-indigo-80"> 从概念到现实需要大量的时间和工作,你需要一个补充你技能的团队</span>
    </p>
    <div class="grid grid-cols-1 lg:grid-cols-3 sm:grid-cols-1">
      <div class="flex flex-col justify-center text-gray-700 text-center bg-white px-8 py-2 m-4 h-40 rounded shadow hover:shadow-large transition-shadow duration-700 ease-in-out " v-for="(item, key) in services" :key="key">
        <span class="font-bold text-indigo-100">{{item.title}}</span>
        <p class="font-normal text-indigo-60">{{item.desc}}</p>
      </div>
    </div>
  </div>
</template>
<script>
  export default {
    data() {
      return {
        services: [{
          title: '网站开发',
          desc: '响应式网站设计、H5、WebGL'
        }, {
          title: '移动端研发',
          desc: 'IOS & Android、小程序'
        }, {
          title: '后端服务',
          desc: '云服务、API 服务'
        }, {
          title: '运维服务',
          desc: '服务器维护、部署、故障处理'
        }, {
          title: '产品策划',
          desc: '需要分析、产品整理、原型设计'
        }, {
          title: '设计服务',
          desc: '标准设计、高水平设计'
        }]
      }
    }
  }
</script>

效果如下:

PC端
移动端
以上简单的10几行代码就可以很精准的实现出自适应效果。

tailwind.config.js包含的是全部的样式配置,包含配色、排版、字体、阴影等,配置文件内容如下:

const {COLORS}  = require('./colors')
// Depth level 1 (sitting on background)
const BOX_SHADOW_BORDER_LIGHTER = `0 0 0 1px rgba(${COLORS.indigoRgb}, .08)`;
const BOX_SHADOW_BORDER = `0 0 0 1px rgba(${COLORS.indigoRgb}, .08)`;
const BOX_SHADOW_BORDER_DARKER = `0 0 0 1px rgba(${COLORS.indigoRgb}, .16)`;
const BOX_SHADOW_SITTING = `0 4px 4px -4px rgba(${COLORS.indigoRgb}, .32)`;
// Depth level 2 (dropdowns, dialogs, draggables when lifted)
const BOX_SHADOW_LIFTED = `0 16px 24px -8px rgba(${COLORS.indigoRgb}, .32)`;
// Depth level 3 (huge shadows)
const BOX_SHADOW_LARGE = `0 16px 40px -4px rgba(${COLORS.indigoRgb}, .2)`;
// Focus style
const BOX_SHADOW_FOCUS = `0 0 0 3px ${COLORS.focus}`;
const BOX_SHADOW_BUTTON = `0 0 0 1px rgba(20, 11, 47, 0.12), 0 4px 4px -4px rgba(0, 0, 0, .32)`
const BOX_SHADOW_BUTTON_HOVER = `0 0 0 1px rgba(20, 11, 47, 0.32), 0 4px 4px -4px rgba(0, 0, 0, .32)`
module.exports = {
  prefix: '',
  important: false,
  separator: ':',
  theme: {
    screens: {
      sm: '640px',
      md: '768px',
      lg: '1024px',
      xl: '1280px',
    },
    colors: {
      transparent: 'transparent',

      black: '#000',
      white: '#fff',

      gray: {
        100: '#f7fafc',
        200: '#edf2f7',
        300: '#e2e8f0',
        400: '#cbd5e0',
        500: '#a0aec0',
        600: '#718096',
        700: '#4a5568',
        800: '#2d3748',
        900: '#1a202c',
      },
      red: {
        100: '#fff5f5',
        200: '#fed7d7',
        300: '#feb2b2',
        400: '#fc8181',
        500: '#f56565',
        600: '#e53e3e',
        700: '#c53030',
        800: '#9b2c2c',
        900: '#742a2a',
      },
      orange: {
        100: '#fffaf0',
        200: '#feebc8',
        300: '#fbd38d',
        400: '#f6ad55',
        500: '#ed8936',
        600: '#dd6b20',
        700: '#c05621',
        800: '#9c4221',
        900: '#7b341e',
      },
      // yellow: "#ffb300",
      // y80: "#ffc233",
      // y60: "#ffd166",
      // y40: "#ffe199",
      // y20: "#fff0cc",
      // y12: "#fff5e0",
      // y08: "#fff9eb",
      // y04: "#fffcf5",
      // y02: "#fffefa",
      yellow: {
        100: '#ffb300',
        80: '#ffc233',
        60: '#faf089',
        40: '#ffe199',
        20: '#fff0cc',
        12: '#fff5e0',
        8: '#fff9eb',
        4: '#fffcf5',
        2: '#fffefa',
      },
      green: {
        100: '#f0fff4',
        200: '#c6f6d5',
        300: '#9ae6b4',
        400: '#68d391',
        500: '#48bb78',
        600: '#38a169',
        700: '#2f855a',
        800: '#276749',
        900: '#22543d',
      },
      teal: {
        100: '#e6fffa',
        200: '#b2f5ea',
        300: '#81e6d9',
        400: '#4fd1c5',
        500: '#38b2ac',
        600: '#319795',
        700: '#2c7a7b',
        800: '#285e61',
        900: '#234e52',
      },
      blue: {
        100: '#ebf8ff',
        200: '#bee3f8',
        300: '#90cdf4',
        400: '#63b3ed',
        500: '#4299e1',
        600: '#3182ce',
        700: '#2b6cb0',
        800: '#2c5282',
        900: '#2a4365',
      },
      indigo: {
        100: "#24124d",
        80: "#4f4270",
        60: "#7b7194",
        40: "#a7a0b8",
        20: "#d3d0db",
        12: "#e4e2e9",
        8: "#eeecf1",
        4: "#f4f3f6",
        2: "#fbfafc",
      },
      purple: {
        100: "#512da8",
        80: "#7457b9",
        60: "#9781cb",
        40: "#b9abdc",
        20: "#dcd5ee",
        12: "#eae5f4",
        8: "#f1eff8",
        4: "#f8f7fc",
        2: "#fcfbfd",
        rgba: `rgba(${COLORS.purpleRgb}, 0.04)`,
        rgbaDark: `rgba(${COLORS.purpleRgb}, 0.08)`
      },
      pink: {
        100: '#fff5f7',
        200: '#fed7e2',
        300: '#fbb6ce',
        400: '#f687b3',
        500: '#ed64a6',
        600: '#d53f8c',
        700: '#b83280',
        800: '#97266d',
        900: '#702459',
      },
      magenta: {
        100: "#f84f77",
        80: "#f97292",
        60: "#fb95ad",
        40: "#fcb9c9",
        20: "#fedce4",
        12: "#fee9ee",
        8: "#fff1f5",
        4: "#fff8fa",
        2: "#fffcfc"
      },

    },
    spacing: {
      px: '1px',
      '0': '0',
      '1': '0.25rem',
      '2': '0.5rem',
      '3': '0.75rem',
      '4': '1rem',
      '5': '1.25rem',
      '6': '1.5rem',
      '8': '2rem',
      '10': '2.5rem',
      '12': '3rem',
      '16': '4rem',
      '20': '5rem',
      '24': '6rem',
      '32': '8rem',
      '40': '10rem',
      '48': '12rem',
      '56': '14rem',
      '64': '16rem',
    },
    backgroundColor: theme => theme('colors'),
    backgroundPosition: {
      bottom: 'bottom',
      center: 'center',
      left: 'left',
      'left-bottom': 'left bottom',
      'left-top': 'left top',
      right: 'right',
      'right-bottom': 'right bottom',
      'right-top': 'right top',
      top: 'top',
    },
    backgroundSize: {
      auto: 'auto',
      cover: 'cover',
      contain: 'contain',
    },
    borderColor: theme => ({
      ...theme('colors'),
      default: theme('colors.gray.300', 'currentColor'),
    }),
    borderRadius: {
      none: '0',
      sm: '0.125rem',
      default: '0.25rem',
      lg: '0.5rem',
      full: '9999px',
    },
    borderWidth: {
      default: '1px',
      '0': '0',
      '2': '2px',
      '4': '4px',
      '8': '8px',
    },
    boxShadow: {
      default: '0 0 0 1px rgba(20, 11, 47, 0.12), 0 4px 4px -4px rgba(0, 0, 0, .32)',
      md: BOX_SHADOW_BUTTON_HOVER,
      lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
      xl: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
      '2xl': '0 25px 50px -12px rgba(0, 0, 0, 0.25)',
      inner: 'inset 0 2px 4px 0 rgba(0, 0, 0, 0.06)',
      outline: '0 0 0 3px rgba(66, 153, 225, 0.5)',
      none: 'none',
      borderLighter: BOX_SHADOW_BORDER_LIGHTER,
      border: BOX_SHADOW_BORDER,
      borderDark: BOX_SHADOW_BORDER_DARKER,
      sitting: BOX_SHADOW_SITTING,
      lifted: BOX_SHADOW_LIFTED,
      large: BOX_SHADOW_LARGE,
      focus: BOX_SHADOW_FOCUS,
      buttonHover: BOX_SHADOW_BUTTON_HOVER
    },
    container: {},
    cursor: {
      auto: 'auto',
      default: 'default',
      pointer: 'pointer',
      wait: 'wait',
      text: 'text',
      move: 'move',
      'not-allowed': 'not-allowed',
    },
    fill: {
      current: 'currentColor',
    },
    flex: {
      '1': '1 1 0%',
      auto: '1 1 auto',
      initial: '0 1 auto',
      none: 'none',
    },
    flexGrow: {
      '0': '0',
      default: '1',
    },
    flexShrink: {
      '0': '0',
      default: '1',
    },
    fontFamily: {
      sans: [
        '-apple-system',
        'BlinkMacSystemFont',
        '"Segoe UI"',
        'Roboto',
        '"Helvetica Neue"',
        'Arial',
        '"Noto Sans"',
        'sans-serif',
        '"Apple Color Emoji"',
        '"Segoe UI Emoji"',
        '"Segoe UI Symbol"',
        '"Noto Color Emoji"',
      ],
      serif: [
        'Georgia',
        'Cambria',
        '"Times New Roman"',
        'Times',
        'serif',
      ],
      mono: [
        'Menlo',
        'Monaco',
        'Consolas',
        '"Liberation Mono"',
        '"Courier New"',
        'monospace',
      ],
    },
    fontSize: {
      xs: '0.75rem',
      sm: '0.875rem',
      base: '1rem',
      lg: '1.125rem',
      xl: '1.25rem',
      '2xl': '1.5rem',
      '3xl': '1.875rem',
      '4xl': '2.25rem',
      '5xl': '3rem',
      '6xl': '4rem',
    },
    fontWeight: {
      hairline: '100',
      thin: '200',
      light: '300',
      normal: '400',
      medium: '500',
      semibold: '600',
      bold: '700',
      extrabold: '800',
      black: '900',
    },
    height: theme => ({
      auto: 'auto',
      ...theme('spacing'),
      full: '100%',
      screen: '100vh',
    }),
    inset: {
      '0': '0',
      auto: 'auto',
    },
    letterSpacing: {
      tighter: '-0.05em',
      tight: '-0.025em',
      normal: '0',
      wide: '0.025em',
      wider: '0.05em',
      widest: '0.1em',
    },
    lineHeight: {
      none: '1',
      tight: '1.25',
      snug: '1.375',
      normal: '1.5',
      relaxed: '1.625',
      loose: '2',
    },
    listStyleType: {
      none: 'none',
      disc: 'disc',
      decimal: 'decimal',
    },
    margin: (theme, { negative }) => ({
      auto: 'auto',
      ...theme('spacing'),
      ...negative(theme('spacing')),
    }),
    maxHeight: {
      full: '100%',
      screen: '100vh',
    },
    maxWidth: {
      xs: '20rem',
      sm: '24rem',
      md: '28rem',
      lg: '32rem',
      xl: '36rem',
      '2xl': '42rem',
      '3xl': '48rem',
      '4xl': '56rem',
      '5xl': '64rem',
      '6xl': '72rem',
      full: '100%',
    },
    minHeight: {
      '0': '0',
      full: '100%',
      screen: '100vh',
    },
    minWidth: {
      '0': '0',
      full: '100%',
    },
    objectPosition: {
      bottom: 'bottom',
      center: 'center',
      left: 'left',
      'left-bottom': 'left bottom',
      'left-top': 'left top',
      right: 'right',
      'right-bottom': 'right bottom',
      'right-top': 'right top',
      top: 'top',
    },
    opacity: {
      '0': '0',
      '25': '0.25',
      '50': '0.5',
      '75': '0.75',
      '90': '.9',
      '100': '1',
    },
    order: {
      first: '-9999',
      last: '9999',
      none: '0',
      '1': '1',
      '2': '2',
      '3': '3',
      '4': '4',
      '5': '5',
      '6': '6',
      '7': '7',
      '8': '8',
      '9': '9',
      '10': '10',
      '11': '11',
      '12': '12',
    },
    padding: theme => theme('spacing'),
    stroke: {
      current: 'currentColor',
    },
    textColor: theme => theme('colors'),
    width: theme => ({
      auto: 'auto',
      ...theme('spacing'),
      '1/2': '50%',
      '1/3': '33.33333%',
      '2/3': '66.66667%',
      '1/4': '25%',
      '2/4': '50%',
      '3/4': '75%',
      '1/5': '20%',
      '2/5': '40%',
      '3/5': '60%',
      '4/5': '80%',
      '1/6': '16.66667%',
      '2/6': '33.33333%',
      '3/6': '50%',
      '4/6': '66.66667%',
      '5/6': '83.33333%',
      '1/12': '8.33333%',
      '2/12': '16.66667%',
      '3/12': '25%',
      '4/12': '33.33333%',
      '5/12': '41.66667%',
      '6/12': '50%',
      '7/12': '58.33333%',
      '8/12': '66.66667%',
      '9/12': '75%',
      '10/12': '83.33333%',
      '11/12': '91.66667%',
      full: '100%',
      screen: '100vw',
    }),
    zIndex: {
      auto: 'auto',
      '0': '0',
      '10': '10',
      '20': '20',
      '30': '30',
      '40': '40',
      '50': '50',
    },
    transitionProperty: {
      none: 'none',
      all: 'all',
      default: 'background-color, border-color, color, opacity, transform',
      colors: 'background-color, border-color, color',
      opacity: 'opacity',
      transform: 'transform',
      shadow: 'box-shadow',
    },
    transitionTimingFunction: {
      linear: 'linear',
      in: 'cubic-bezier(0.4, 0, 1, 1)',
      out: 'cubic-bezier(0, 0, 0.2, 1)',
      // 'in-out': 'cubic-bezier(0.4, 0, 0.2, 1)',
      'in-out': 'cubic-bezier(0.2, .6, .6, 1)',
    },
    // transition: box-shadow 150ms cubic-bezier(.2,.6,.6,1);
    transitionDuration: {
      '75': '75ms',
      '100': '100ms',
      '150': '150ms',
      '200': '200ms',
      '300': '300ms',
      '500': '500ms',
      '700': '700ms',
      '1000': '1000ms',
    },
  },
  variants: {
    transitionProperty: ['responsive', 'focus', 'hover'],
    transitionTimingFunction: ['responsive', 'focus', 'hover'],
    transitionDuration: ['responsive', 'focus', 'hover'],
    alignContent: ['responsive'],
    alignItems: ['responsive'],
    alignSelf: ['responsive'],
    appearance: ['responsive'],
    backgroundAttachment: ['responsive'],
    backgroundColor: ['responsive', 'hover', 'focus'],
    backgroundPosition: ['responsive'],
    backgroundRepeat: ['responsive'],
    backgroundSize: ['responsive'],
    borderCollapse: ['responsive'],
    borderColor: ['responsive', 'hover', 'focus'],
    borderRadius: ['responsive'],
    borderStyle: ['responsive'],
    borderWidth: ['responsive'],
    boxShadow: ['responsive', 'hover', 'focus'],
    cursor: ['responsive'],
    display: ['responsive'],
    fill: ['responsive'],
    flex: ['responsive'],
    flexDirection: ['responsive'],
    flexGrow: ['responsive'],
    flexShrink: ['responsive'],
    flexWrap: ['responsive'],
    float: ['responsive'],
    fontFamily: ['responsive'],
    fontSize: ['responsive'],
    fontSmoothing: ['responsive'],
    fontStyle: ['responsive'],
    fontWeight: ['responsive', 'hover', 'focus'],
    height: ['responsive'],
    inset: ['responsive'],
    justifyContent: ['responsive'],
    letterSpacing: ['responsive'],
    lineHeight: ['responsive'],
    listStylePosition: ['responsive'],
    listStyleType: ['responsive'],
    margin: ['responsive'],
    maxHeight: ['responsive'],
    maxWidth: ['responsive'],
    minHeight: ['responsive'],
    minWidth: ['responsive'],
    objectFit: ['responsive'],
    objectPosition: ['responsive'],
    opacity: ['responsive', 'hover', 'focus', 'active'],
    order: ['responsive'],
    outline: ['responsive', 'focus'],
    overflow: ['responsive'],
    padding: ['responsive'],
    pointerEvents: ['responsive'],
    position: ['responsive'],
    resize: ['responsive'],
    stroke: ['responsive'],
    tableLayout: ['responsive'],
    textAlign: ['responsive'],
    textColor: ['responsive', 'hover', 'focus'],
    textDecoration: ['responsive', 'hover', 'focus'],
    textTransform: ['responsive'],
    userSelect: ['responsive'],
    verticalAlign: ['responsive'],
    visibility: ['responsive'],
    whitespace: ['responsive'],
    width: ['responsive'],
    wordBreak: ['responsive'],
    zIndex: ['responsive'],
    transition: ['responsive', 'hover', 'focus'],
  },
  corePlugins: {
    // outline: false,
  },
  plugins: [
    function({ addBase, config }) {
      addBase({
        'a': {
          color: config('theme.colors.teal.500'),
        },
        'h1': {
          fontSize: config('theme.fontSize.2xl'),
          fontWeight: config('theme.fontWeight.bold')
        },
        'h2': {
          fontSize: config('theme.fontSize.xl'),
          fontWeight: config('theme.fontWeight.bold')
        },
        'h3': {
          fontSize: config('theme.fontSize.base'),
          fontWeight: config('theme.fontWeight.bold')
        },
        'p': { marginTop: '0.5em' },
      })
    },
  ]
}

nuxt.config.js中包含了 nuxt的基础配置,和 tailwind 模块配置,重点配置如下:

  /*
  ** Nuxt.js dev-modules
  */
  buildModules: [
    // Doc: https://github.com/nuxt-community/nuxt-tailwindcss
    '@nuxtjs/tailwindcss',
  ],
  tailwindcss: {
    configPath: '~/tailwind.config.js',
    cssPath: '~/assets/main.styl'
  },

其中 main.styl,包含了 tailwind 的 css 工具的引入,内容如下

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

这样基础配置和实现完成后,就可以打包发布,执行

yarn build

将项目打包


相关资源

上一篇 下一篇

猜你喜欢

热点阅读