@scqilin/phone-ui 手机外观组件库

@scqilin/phone-ui 手机外观组件库

写在最前面

最近开发一个移动端编辑器,我需要一个非常轻量的"手机壳"来把内容包起来用于预览与截图。于是做了 @scqilin/phone-ui:一个零依赖、用原生 TypeScript 写的手机外观渲染库,核心目标是简单、可复用、易适配。我的目标很明确:

  • 零依赖:能用在任何项目里,不管是 Vue、React 还是原生 JS。
  • 纯粹:只做"手机外观"这一件事,保持轻量。
  • 易用:API 简单,上手快。

✨ 特点

  • 🚀 零依赖,纯 TypeScript + 动态样式注入
  • 📱 内置 iPhone 16 全系列机型(16/Plus/Pro/Pro Max)
  • 🎨 支持完全自定义外观(尺寸、颜色、按钮等)
  • 💻 适用于任何前端项目
  • 🎯 在线演示 可直接体验

📦 安装

bash 复制代码
npm install @scqilin/phone-ui

🚀 快速开始

把下面这段代码扔进你的项目,就能看到效果。

HTML 结构:

html 复制代码
<div id="phone-demo" style="width: 500px; height: 900px;"></div>

JS 调用:

javascript 复制代码
import { createPhoneUI } from '@scqilin/phone-ui';

const container = document.getElementById('phone-demo');

// 方式一:使用预设机型
createPhoneUI({
  container,
  phoneType: 'iphone16pro'
});

// 方式二:完全自定义
createPhoneUI({
  container,
  width: 400,
  height: 800,
  frameColor: '#1a1a1a',
  screenColor: '#ffffff',
  showButtons: true
});

🤔 设计思路与权衡

1. 为什么是原生库,而不是 Vue/React 组件?

最开始我也想直接写个 Vue 组件,但很快发现,把核心做成原生库更灵活。

  • 框架无关:原生实现意味着最大程度的复用。
  • 关注点分离:核心库只管渲染,框架适配(如 Vue 组件)只管生命周期和数据流。这样结构更清晰,维护也更容易。

2. 样式隔离

为了避免污染宿主页面的样式,我没有让用户引入 CSS 文件,而是通过 JS 动态创建 <style> 标签 并注入到 head 中。所有样式都带上了 phone-ui- 前缀,并通过 CSS 变量暴露定制接口,比如 --phone-ui-frame-color

📖 API 文档

createPhoneUI(options)

参数 类型 必填 说明
container HTMLElement 渲染目标容器
phoneType string 机型名称,支持 'iphone16', 'iphone16plus', 'iphone16pro', 'iphone16promax'
width number 自定义宽度(phoneType 存在时无效)
height number 自定义高度(phoneType 存在时无效)
frameColor string 边框颜色,默认 '#1a1a1a'
screenColor string 屏幕颜色,默认 '#ffffff'
showButtons boolean 是否显示侧边按钮,默认 true
borderRadius number 圆角大小,默认 30

📱 支持的机型

机型 phoneType 尺寸 (宽×高)
iPhone 16 'iphone16' 402×874
iPhone 16 Plus 'iphone16plus' 440×950
iPhone 16 Pro 'iphone16pro' 402×874
iPhone 16 Pro Max 'iphone16promax' 440×950

💡 常见问题

  • 屏幕看不见/高度为0 :请确保传入的 container 元素有自己的尺寸(宽高)。
  • 样式被覆盖 :检查宿主页面是否有更高优先级的选择器。可以尝试通过 CSS 变量覆盖颜色,或用 !important
  • 按钮能点吗:不能,按钮仅为装饰。

📦 关于 Vue 的适配

我最初尝试在 Vue 项目里直接用这个原生库,但发现不太"顺手":

  1. 插槽不好用 :想用 Vue 的 <slot> 功能把内容放进"手机屏幕"里,操作起来很别扭。
  2. 生命周期问题 :必须在 onMounted 之后手动调用,在 onBeforeUnmount 手动销毁,很繁琐。

为了解决这个问题,我另外写了一个轻量的 Vue 3 适配包,它做的事情很简单:

  • 把原生库的 API 封装成一个真正的 Vue 组件。
  • onMountedonBeforeUnmount 管理生命周期。
  • 把组件的默认插槽内容正确地渲染到手机屏幕里。

现在,在 Vue 里可以这样用:

vue 复制代码
<template>
  <PhoneUi phoneType="iphone16pro">
    <!-- 这里的内容会自动放进手机屏幕 -->
    <h1>Hello, Vue!</h1>
  </PhoneUi>
</template>

<script setup>
// 假设你已经安装并配置了 vue 适配包
import PhoneUi from '@scqilin/phone-ui-vue'; 
</script>

这样就舒服多了。这个 Vue 适配包是独立的项目,你可以在这里找到它:

🎉 结语

如果你对这个小项目感兴趣,或者希望支持其他机型,欢迎在 GitHub 上提 Issue 或 PR!

相关推荐
前进的李工1 天前
LangChain使用之Model IO(提示词模版之ChatPromptTemplate)
java·前端·人工智能·python·langchain·大模型
Triv20251 天前
太阳能船远程信息处理:CAN数据记录 + Grafana仪表板实战案例
grafana·数据可视化·influxdb·嵌入式系统·can总线·数据采集与监控·智能船舶
漫随流水1 天前
旅游推荐系统(login.html)
前端·html·旅游
1024小神1 天前
记录xcode项目swiftui配置APP加载启动图
前端·ios·swiftui·swift
CHU7290351 天前
社区生鲜买菜小程序前端功能版块设计及玩法介绍
前端·小程序
尤山海1 天前
深度防御:内容类网站如何有效抵御 SQL 注入与脚本攻击(XSS)
前端·sql·安全·web安全·性能优化·状态模式·xss
前端小趴菜051 天前
Windi CSS
前端·css
榴莲omega1 天前
第7天:网络进阶——TCP/UDP、WebSocket、长连接
javascript·网络·tcp/ip·udp·八股
xuankuxiaoyao1 天前
VUE.JS 实践 第二章
前端·javascript·vue.js
毕设源码-赖学姐1 天前
【开题答辩全过程】以 基于Vue的电商管理平台为例,包含答辩的问题和答案
前端·javascript·vue.js