基于nodejs服务端web组件化开发(七、项目搭建)

64 阅读3分钟

七、项目搭建

本节将采用 express 搭建一个简单的门户网站基本结构,感受下服务端组件化的开发工具的使用方式

  1. 门户网站最终样式

web.png
2. 创建门户网站项目文件结构

web
├─ app.js             入口文件
├─ hcdr.config.js     全局配置
├─ index.tpl          全局模板
├─ package.json       项目配置文件
├─ controller
│     └─ index.js     控制器
├─ hcdr               组件化核心,这里已重新整理
│  ├─ index.js        主控文件
│  ├─ package.json    配置文件
│  ├─ README.md       说明文件
│  └─src
│      ├─ compile.js  编译相关
│      ├─ compose.js  合并相关
│      └─ template.js 默认模板
├─ public             公共目录
│  └─ css
│ 	  └─ reset.css    初始化样式
├─ router
│   └─ index.js       路由
└─ views              组件视图目录
    ├─ componets      通用组件
        └─ Content.js 内容
    ├─ About.js       关于
    ├─ Contact.js     联系
    ├─ Home.js        主页
    ├─ Layout         布局目录
    │    ├─ Footer.js 底部
    │    ├─ Header.js 头部
    │    ├─ index.js  布局
    │    └─ Navbar.js 导航
    └─ Product.js

没什么好讲的,直接上代码

组件

Header 组件

// views/Header.js
const { html, css, define } = require("hcdr")

const template = () => {
  return html`
    <div class="header">
      <h1>企业门户</h1>
    </div>
  `
}

const style = () => {
  return css`
    .header {
      background-color: #333;
      color: #fff;
      padding: 10px 30px;
      box-sizing: border-box;
    }
  `
}

module.exports = define("Header", { template, style })

Navbar 组件

// views/Layout/Navbar.js
const { html, css, define } = require("hcdr")

// 模拟项数据库请求得到异步数据

const navbarList = async () => [
  { url: "/", title: "主页" },
  { url: "/product", title: "产品" },
  { url: "/about", title: "关于" },
  { url: "/contact", title: "联系" }
]

const template = async () => {
  const data = await navbarList()
  return html`
    <ul class="navbar">
      ${data
        .map(function (item) {
          return html`
            <li>
              <a href="${item.url}">${item.title}</a>
            </li>
          `
        })
        .join("\n")}
    </ul>
  `
}

const style = () => {
  return css`
    .navbar {
      list-style-type: none;
      margin: 0;
      padding: 0;
      overflow: hidden;
      background-color: #ddd;
    }
    .navbar li {
      float: left;
    }
    .navbar li a {
      display: block;
      color: #000;
      text-align: center;
      padding: 14px 16px;
      text-decoration: none;
    }
    .navbar li a:hover {
      background-color: #ddd;
    }
    .navbar li a:hover {
      color: #409eff;
    }
  `
}

module.exports = define("Navbar", { template, style })

Footer 组件

// views/Layout/Footer.js
const { html, css, define } = require("hcdr")

const template = () => {
  return html`
    <div class="footer">
      <p>版权信息 &copy; 2024</p>
    </div>
  `
}

const style = () => {
  return css`
    .footer {
      color: #999;
      background-color: #333;
      padding: 10px;
      text-align: center;
    }
    .footer p {
      margin: 0;
    }
  `
}

module.exports = define("Footer", { template, style })

Layout 组件

// views/Layout/index.js
const { html, css, define } = require("hcdr")

const Header = require("./Header")
const Navbar = require("./Navbar")
const Footer = require("./Footer")

const template = async ({ main }) => {
  return html`
    <div class="app">
      <header>${Header()}</header>
      <nav>${await Navbar()}</nav>
      <main class="content">${main}</main>
      <footer>${Footer()}</footer>
    </div>
  `
}

const style = () => {
  return css`
    .app {
      width: 100vw;
      height: 100vh;
      display: flex;
      flex-direction: column;
    }
    .content {
      flex: 1;
      margin: 10px;
      padding: 20px;
    }
  `
}

module.exports = define("Layout", { template, style })

Content 组件

这里偷懒各页面内容就一种款式

// views/component/Content.js
const { html, css, define } = require("hcdr")

const template = ({ key, title = "", content = [] }) => {
  return html`
    <div class="${key}">
      <h2>${title}</h2>
      <ol>
        ${content
          .map(function (item) {
            return html`<li>${item}</li>`
          })
          .join(",")}
      </ol>
    </div>
  `
}

const style = ({ key }) => {
  return css`
    .${key} ol li {
      font-size: 16px;
      color: #333;
      line-height: 1.5em;
    }
  `
}

module.exports = define("Content", { template, style })

Home 组件

// views/Home/index.js
const { define } = require("hcdr")

const Content = require("./componets/Content")

const data = {
  title: "主要内容",
  content: [
    "‌‌轮播图‌:展示公司最新动态、产品图片或重要活动。",
    "‌服务介绍‌:简要介绍公司的主营业务和服务范围。",
    "成功案例‌:展示公司成功案例或客户评价。"
  ]
}

module.exports = define("Home", {
  template: () => {
    const key = "home"
    return Content({ key, ...data }, { key })
  }
})

Product 组件

// views/Product.js
const { define } = require("hcdr")

const Content = require("./componets/Content")

const data = {
  title: "产品页面",
  content: [
    "‌产品分类‌:根据产品类型进行分类展示,如“电子产品”、“机械设备”等。",
    "‌产品详情‌:点击产品分类后,展示具体产品的详细信息,包括产品图片、价格、功能介绍等。",
    "‌购买方式‌:提供在线购买链接或联系方式,方便客户咨询和购买。",
    "‌客户评价‌:展示客户对产品的评价和反馈。"
  ]
}

module.exports = define("Product", {
  template: () => {
    const key = "product"
    return Content({ key, ...data }, { key })
  }
})

About 组件

// views/About.js
const { define } = require("hcdr")

const Content = require("./componets/Content")

const data = {
  title: "关于我们",
  content: [
    "公司简介‌:介绍公司的历史、愿景、使命等基本信息。",
    "‌团队介绍‌:展示公司团队成员的简介和照片。",
    "‌公司文化‌:介绍公司的核心价值观、企业精神等。"
  ]
}

module.exports = define("About", {
  template: () => {
    const key = "about"
    return Content({ key, ...data }, { key })
  }
})

Contact 组件

const { define } = require("hcdr")

const Content = require("./componets/Content")

const data = {
  title: "联系我们",
  content: [
    "‌联系方式‌:提供公司的电话、邮箱、地址等联系方式。",
    "‌在线表单‌:提供在线联系表单,方便客户提交咨询或反馈。",
    "‌地图定位‌:嵌入百度地图或谷歌地图,方便客户找到公司位置。",
    "‌常见问题‌:列出客户常见问题及解答,减少重复咨询。"
  ]
}

module.exports = define("Contact", {
  template: () => {
    const key = "contact"
    return Content({ key, ...data }, { key })
  }
})

控制器

// controller/index.js
const { render } = require("hcdr")
const Home = require("../views/Home")
const About = require("../views/About")
const Layout = require("../views/Layout")
const Product = require("../views/Product")
const Contact = require("../views/Contact")

const homeView = async (req, res) => {
  const code = await render(Layout, { main: Home() }, null, {
    title: "主页-企业门户"
  })
  res.send(code)
}

const productView = async (req, res) => {
  const code = await render(Layout, { main: Product() }, null, {
    title: "产品-企业门户"
  })
  res.send(code)
}

const aboutView = async (req, res) => {
  const code = await render(Layout, { main: About() }, null, {
    title: "关于-企业门户"
  })
  res.send(code)
}
const contactView = async (req, res) => {
  const code = await render(Layout, { main: Contact() }, null, {
    title: "联系-企业门户"
  })
  res.send(code)
}

module.exports = { homeView, productView, aboutView, contactView }

路由

// router/index.js
const express = require("express")

const router = express.Router()

const {
  homeView,
  productView,
  aboutView,
  contactView
} = require("../controller")

router.get("/", homeView)
router.get("/product", productView)
router.get("/about", aboutView)
router.get("/contact", contactView)

module.exports = router

主控文件

// app.js
const express = require("express")
const app = express()

app.use(express.static("./public"))

const router = require("./router")
app.use(router)

app.listen(3000, () => {
  console.log("express server running at http://localhost:3000 .")
})

别忘了安装依赖npm i express 直接运行node app效果有了,体会了一把。

下节,把核心代码整理规范下