前言
最近看见大家都在卷react源码,突然就心慌了。但是自己的操作水平还有待提高,现在看源码也需要循序渐进的,打算还是从写代码慢慢理解功能再去看源码。所以就尝试使用vite这个构建工具进行尝试构建一个react项目。因为是第一次使用,也是看着文档来操作的。下面展示一下效果。
效果
录屏软件生成gif的找到一个只能一次免费后面收费的,效果有点模糊。mac电脑,如果有比较好的,各位大佬推荐一下哈!!!
放个截图
实现步骤
一,项目搭建
- 1,按照vite文档进行操作。
- 目前require在vite项目中不能使用,导入用import
- 兼容性注意:Vite 需要 Node.js 版本 >= 14.18.0。然而,有些模板需要依赖更高的 Node 版本才能正常运行,当你的包管理器发出警告时,请注意升级你的 Node 版本。
yarn create vite #yarn安装
npm create vite@latest # npm安装
-
2,按照上面步骤之后,我选择了npm安装,选择react搭建
- 如图所示:
- 其中vanilla js可以翻译为原生js,vite搭建vanilla运行地址。
- preact是React 的轻量级替代方案,体积仅有 3kB,并且拥有与 React 相同的 API。vite搭建preact运行地址。
- 在svelte中,应用程序由一个或多个 组件(components) 构成。组件是一个可重用的、自包含的代码块,它将 HTML、CSS 和 JavaScript 代码封装在一起并写入
.svelte
后缀名的文件中,vite搭建svelte运行地址。 - Lit 是一个简单的框架,用于构建快速、轻量级的 Web 组件。它提供反应状态、作用域样式和一个小巧、快速且富有表现力的声明性模板系统,vite搭建lit运行地址
- 如图所示:
-
3,运行。cd到对应目录,然后查看package.json脚本显示dev
yarn dev # yarn安装 npm run dev # npm安装
-
4,适配移动端
- 安装插件
yarn add postcss-pxtorem -D # yarn安装 npm install postcss-pxtorem -D # npm安装
- 在vite.config.js中进行配置,将+ 后面的添加到相应的位置
import { defineConfig } from 'vite' // defineConfig对vite进行配置 import react from '@vitejs/plugin-react' + import postcss from 'postcss-pxtorem' //注意,这里和之前的不一样,将defineConfig({})中对像按照配置dev环境一样改成了箭头函数 export default defineConfig((command, mode) => { return { plugins: [ react(), ], // css模块适配移动端 + css: { postcss: { plugins: [ postcss({ // 把px单位换算成rem单位 rootValue: 16, // 换算基数,默认100,这样的话把根标签的字体规定为1rem //为50px,这样就可以从设计稿上量出多少个px直接在代码中写多上px了。 propList: ['*'], //属性的选择器,*表示通用 unitPrecision: 5, // 允许REM单位增长到的十进制数字,小数点后保留的位数。 exclude: /(node_module)/, // 默认false,可以(reg)利用正则表达 //式 排除某些文件夹的方法 }) ] } } } })
-
5,antd-mobile按需引入
- 安装antd-mobile
yarn add antd-mobile # yarn安装 npm install yarn add antd-mobile # npm安装
- 插件配置
import { defineConfig } from 'vite' // defineConfig对vite进行配置 import react from '@vitejs/plugin-react' + import postcss from 'postcss-pxtorem' + import vitePluginImp from 'vite-plugin-imp' export default defineConfig((command, mode) => { return { plugins: [ react(), // antd按需引入样式 + vitePluginImp({ libList: [ { libName: 'antd-mobile', libDirectory: 'es/components', style(name) { return `antd-mobile/es/components/${name}/${name}.css` }, }, ] }) ], })
-
6, 配置别名
import { defineConfig } from 'vite' // defineConfig对vite进行配置
import react from '@vitejs/plugin-react'
import postcss from 'postcss-pxtorem'
import vitePluginImp from 'vite-plugin-imp' //vitePluginImp 是将 antd-mobile 进行按需加载
export default defineConfig((command, mode) => {
return {
plugins: [
react(),
// antd按需引入样式
vitePluginImp({
libList: [
{
libName: 'antd-mobile',
libDirectory: 'es/components',
style(name) {
return `antd-mobile/es/components/${name}/${name}.css`
},
},
]
})
],
// 配置别名
+ resolve: {
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json'],
alias: {
'@': '/src'
}
},
css: {
postcss: {
plugins: [
postcss({ // 把px单位换算成rem单位
rootValue: 16, // 换算基数,默认100,这样的话把根标签的字体规定为1rem
//为50px,这样就可以从设计稿上量出多少个px直接在代码中写多上px了。
propList: ['*'], //属性的选择器,*表示通用
unitPrecision: 5, // 允许REM单位增长到的十进制数字,小数点后保留的位数。
exclude: /(node_module)/, // 默认false,可以(reg)利用正则表达
//式 排除某些文件夹的方法
})
]
}
}
}
})
canvas碰撞效果
- 1,初始化
import React, { useEffect } from 'react'
export default function
(props) {
// 全局变量
let canvas
// 将通过面相对象的小球push进去,后面调用才知道是哪一个小球在运动
let ballArr = []
// 定时器名字
let timerC
// 小球左边的文字
let fireWords = '你的眼睛|像星星|一样美丽|无论冬夏|晴雨山川|一样灿烂|我的眼睛|因为|有你|所以更美'
// 对文字做切割
let textArr = fireWords.split('|')
useEffect(() => {
// 获取canvas标签
canvas = document.getElementById('tutorial');
// 生成canvas上下文,创建都用上这个
let ctx = canvas.getContext('2d');
// 调用函数绘画
draw(ctx)
// 切换页面取消定时器
return () => { clearInterval(timerC) }
}, [])
return (
<canvas id="tutorial" width="375" height="750">
你的浏览器不支持canvas,请升级你的浏览器
</canvas>
)
}
- 2,绘画draw()函数实现
const draw = (ctx) => {
// 创建10小球,小球个数可以更多
for (let index = 0; index < 10; index++) {
// 构造10个随机的小球参数对象
var ball = new Ball()
// 将每个对象push进去
ballArr.push(ball)
}
// 通过定时器移动小球x,y坐标,实现小球的移动
timerC = setInterval(() => {
// 每次进行定时移动的时候,清除画布,不然图像会连在一块
ctx.clearRect(0, 0, 375, 750)
// 遍历ballArr,将所有参数取出来,通过show()创建小球
for (let index = 0; index < ballArr.length; index++) {
var ball = ballArr[index]
// 创建小球
show(ctx, ball, textArr[index])
//二次循环,确定直线的位置
for (let j = 0; j < index; j++) {
const preBall = ballArr[j]
// 画连接的直线
drawLine(ctx, preBall.x, preBall.y, ball.x, ball.y, ball.color)
}
}
}, 20)
}
- 3,面相对象写法。创建不同小球的参数
// 设置一个随机数
const randMod = (number) => {
return parseInt(Math.random() * number)
}
function Ball() {
// 的this指向new Ball()这个对象
this.w = 375 //画布的宽
this.h = 750 //画布的宽
this.x = randMod(5) + 60 //小球的x坐标
this.y = randMod(5) + 60 //小球的y坐标
this.r = randMod(50) + 10 //[10,60] //小球的半径
// this.color = '#' + parseInt(Math.random() * 0xffffff).toString(16)
//随机颜色
this.color = "rgb(" + Math.floor(Math.random() * 256) + ',' + Math.floor(Math.random() * 256) + ',' + Math.floor(Math.random() * 256) + ")"
this.xSpeed = randMod(2) + 3// [3,5] // 每个小球的速度,按x轴移动
this.ySpeed = randMod(3) + 1// [1,4] // 每个小球的速度,按y轴移动
}
- 4,画直线
const drawLine = (ctx, x1, y1, x2, y2, color) => {
ctx.beginPath()
ctx.moveTo(x1, y1)
ctx.lineTo(x2, y2)
ctx.closePath()
ctx.stroke();
ctx.strokeStyle = color
}
- 5,小球展示
const show = function (ctx, ball, text) {
// 每次展示的时候先运行一下
run(ball)
// 每次开始show被调用时,都要重新绘制路径,不然小球会连在一块儿
ctx.beginPath()
// 画小球
ctx.arc(ball.x, ball.y, ball.r, 0, 2 * Math.PI, false)
// 设置颜色
ctx.fillStyle = ball.color
ctx.fill()
//描述文字
text && drawText(ctx, text, ball.x, ball.y, ball.r, ball.color)
}
- 6,小球运行
const run = function (ball) {
if (ball.x - ball.r < 0 || ball.x + ball.r > ball.w) {
ball.xSpeed = -ball.xSpeed
}
if (ball.y - ball.r < 0 || ball.y + ball.r > ball.h) {
ball.ySpeed = -ball.ySpeed
}
ball.x = ball.x + ball.xSpeed
ball.y = ball.y + ball.ySpeed
}
- 7,画文字
const drawText = (ctx, text, x, y, r, color) => {
//文字要显示在小球右边,所以用小球的水平位置坐标,加上小球半径,可以作为文字的初始坐标
ctx.fillText(text, x + r, y)
ctx.fillStyle = color
ctx.textAlign = 'left'
}
思考
这个例子的小球碰撞,有一些不完美,上面的炫酷文字是另一个页面的,切换过来没有消失。正在学习canvas,所以一起加油。学习后持续输出才能为自己赋能!!!
番外
我正在参加「创意开发 投稿大赛」详情请看:掘金创意开发大赛来了!