Ant Design Mobile of React开发移动应用:健身追踪-灵析社区

JOHO

前言

最近,我感觉移动应用在我国现在的社会还是很火,可以用方兴未艾来形容。从近期软件开发公司和国内的国际大公司职位招聘岗位需求来看,供不应求。高薪、岗位多。移动应用应用商店的app每年都能增加几万个。可见,移动应用开发现在还是很热门,炙手可热。
另外,我感觉国产的一些移动应用开发UI框架也表现出色,趋于成熟。比如,React类UI框架Ant Design Mobile of React、Taro Ul for React。Vue类UI框架Ant Design Mobile Vue、VantUI、MintUI等移动UI框架。于是,近期我也对国产移动应用开发UI框架来了兴趣。抽空关注相关技术博文,尝试着搞一些移动应用小项目开发。把实验日记和心得写成博文发布,希望可以和朋友们分享,可以和朋友们在评论区交流。我的CSDN账号就是我的会客厅,以代码会友,以编程博文会友,不亦乐乎?

一、项目目标

使用Ant Design Mobile of React和本地存储LocalStorage来实现健身追踪应用:开发一个健身追踪应用,允许用户记录每日的运动和健身活动,并提供统计数据,折线图显示统计结果,有备份数据和恢复数据功能。

二、创建项目和配置

要使用Ant Design Mobile of React和本地存储来实现健身追踪应用,你需要进行以下的项目配置:

  1. 创建React项目:首先,确保你已经安装了Node.js和npm。然后在命令行中运行以下命令来创建一个新的React项目:
npx create-react-app fitness-tracker

这将创建一个名为"fitness-tracker"的新目录,并在其中初始化一个新的React项目。

2.  安装Ant Design Mobile of React:进入项目目录,运行以下命令来安装Ant Design Mobile of React:

cd fitness-tracker
npm install antd-mobile --save

这将安装Ant Design Mobile of React及其相关依赖到你的项目中。

3.  配置Ant Design Mobile of React:在你的项目根目录中创建一个名为craco.config.js的文件,并添加以下内容:

const CracoAntDesignMobilePlugin = require('craco-antd-mobile');

module.exports = {
  plugins: [
    {
      plugin: CracoAntDesignMobilePlugin,
      options: {
        customizeThemeLessPath: path.join(
          __dirname,
          'src/styles/antd-custom.less'
        ),
      },
    },
  ],
};

这将配置Craco插件以支持Ant Design Mobile的自定义主题。

4.  创建页面和组件:在你的项目中创建所需的页面和组件,以实现健身追踪应用的功能。

5.  使用本地存储:你可以使用浏览器的本地存储(如LocalStorage)来存储用户的运动和健身活动数据。在适当的时机(如用户提交表单或进行数据更新)将数据存储到本地存储中,并在应用启动时从本地存储中恢复数据。

6.  统计数据和折线图:使用合适的图表库(如Chart.js)来展示统计数据并生成折线图。根据用户的运动和健身活动数据,计算统计结果,并将其传递给图表组件进行展示。

7.   备份数据和恢复数据功能:为用户提供备份数据和恢复数据的功能,允许他们将数据导出到文件或从文件中导入数据。你可以使用浏览器的文件操作API(如File API)来实现这些功能。

以上是使用Ant Design Mobile of React和本地存储来实现健身追踪应用的项目配置步骤。根据你的具体需求和技术选型,可能还需要进行其他配置和开发工作。

三、创建页面和组件实现健身追踪功能

(一)要创建页面和组件来实现健身追踪功能,你可以按照以下步骤进行

  1. 创建页面组件:在你的项目中创建所需的页面组件,如登录页、主页、运动记录页等。可以使用React的函数组件或类组件来定义这些页面。
  2. 创建导航组件:如果需要多个页面之间的导航,你可以创建一个导航组件,用于在不同页面之间进行切换。你可以使用React Router库来管理路由。
  3. 创建表单组件:为了让用户记录每日的运动和健身活动,你可以创建一个表单组件,包含输入框、选择器、提交按钮等。用户可以在表单中填写相关信息,并通过提交按钮将数据保存到本地存储或发送到后端服务器。
  4. 创建统计组件:为了展示统计数据和生成折线图,你可以创建一个统计组件。该组件可以接收用户的运动和健身活动数据,并根据数据计算统计结果。你可以使用图表库(如Chart.js)来绘制折线图,并将统计结果以图表的形式展示给用户。
  5. 创建备份和恢复组件:为了实现备份数据和恢复数据的功能,你可以创建相应的组件。备份组件可以将用户的数据导出到文件,而恢复组件可以从文件中导入数据并恢复到应用中。
  6. 使用本地存储:在适当的时机,你可以使用浏览器的本地存储(如LocalStorage)来保存用户的运动和健身活动数据。你可以在表单提交时将数据存储到本地存储中,并在应用启动时从本地存储中读取数据并显示在界面上。

以上是创建页面和组件来实现健身追踪功能的基本步骤。你可以根据具体需求和设计进行相应的调整和扩展。记得在开发过程中遵循React的组件化和单向数据流原则,保持代码的可维护性和可扩展性。

(二)分别示例关键功能实现

1.以下是一个简单的示例代码,演示如何创建一个健身追踪应用的登录页面和主页组件

// LoginPage.js

import React, { useState } from 'react';

const LoginPage = ({ onLogin }) => {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');

  const handleLogin = () => {
    // 在这里可以进行登录验证,如发送请求到后端进行验证

    // 假设验证成功
    onLogin(username);
  };

  return (
    <div>
      <h1>登录</h1>
      <input
        type="text"
        placeholder="用户名"
        value={username}
        onChange={(e) => setUsername(e.target.value)}
      />
      <input
        type="password"
        placeholder="密码"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
      />
      <button onClick={handleLogin}>登录</button>
    </div>
  );
};

export default LoginPage;
// HomePage.js

import React from 'react';

const HomePage = ({ username }) => {
  return (
    <div>
      <h1>欢迎, {username}!</h1>
      <p>这是健身追踪应用的主页。</p>
      {/* 在这里添加其他页面内容和功能 */}
    </div>
  );
};

export default HomePage;
// App.js

import React, { useState } from 'react';
import LoginPage from './LoginPage';
import HomePage from './HomePage';

const App = () => {
  const [isLoggedIn, setIsLoggedIn] = useState(false);
  const [username, setUsername] = useState('');

  const handleLogin = (username) => {
    setIsLoggedIn(true);
    setUsername(username);
  };

  const handleLogout = () => {
    setIsLoggedIn(false);
    setUsername('');
  };

  return (
    <div>
      {isLoggedIn ? (
        <HomePage username={username} onLogout={handleLogout} />
      ) : (
        <LoginPage onLogin={handleLogin} />
      )}
    </div>
  );
};

export default App;

以上代码示例中,LoginPage 组件用于登录页面,HomePage 组件用于主页。App 组件是根组件,根据用户是否登录来显示不同的页面。App 组件中通过状态管理用户登录状态和用户名,并通过回调函数来更新状态。当用户成功登录时,会将登录状态设置为 true,并将用户名传递给 HomePage 组件展示欢迎信息。当用户点击登出按钮时,会将登录状态设置为 false,并清空用户名。

请注意,以上代码仅为示例,实际开发中可能需要结合其他功能和业务需求进行相应的调整和扩展。

2.接下来我将为你提供一个示例代码,演示如何创建一个运动记录页面和统计组件

// ExerciseRecordPage.js

import React, { useState } from 'react';

const ExerciseRecordPage = () => {
  const [exercise, setExercise] = useState('');
  const [duration, setDuration] = useState('');

  const handleRecord = () => {
    // 在这里可以将运动记录保存到本地存储或发送到后端服务器

    // 清空表单数据
    setExercise('');
    setDuration('');
  };

  return (
    <div>
      <h1>运动记录</h1>
      <input
        type="text"
        placeholder="运动名称"
        value={exercise}
        onChange={(e) => setExercise(e.target.value)}
      />
      <input
        type="text"
        placeholder="持续时间(分钟)"
        value={duration}
        onChange={(e) => setDuration(e.target.value)}
      />
      <button onClick={handleRecord}>记录</button>
    </div>
  );
};

export default ExerciseRecordPage;
// StatisticsComponent.js

import React, { useState } from 'react';
import { Line } from 'react-chartjs-2';

const StatisticsComponent = ({ exerciseData }) => {
  const [chartData, setChartData] = useState({
    labels: [], // 运动日期
    datasets: [
      {
        label: '运动时长',
        data: [], // 运动时长数据
        backgroundColor: 'rgba(75,192,192,0.4)',
        borderColor: 'rgba(75,192,192,1)',
        borderWidth: 2,
      },
    ],
  });

  // 更新图表数据
  const updateChartData = () => {
    const labels = exerciseData.map((record) => record.date);
    const durations = exerciseData.map((record) => record.duration);

    setChartData((prevState) => ({
      ...prevState,
      labels,
      datasets: [
        {
          ...prevState.datasets[0],
          data: durations,
        },
      ],
    }));
  };

  return (
    <div>
      <h1>统计数据</h1>
      <button onClick={updateChartData}>更新图表</button>
      <Line data={chartData} />
    </div>
  );
};

export default StatisticsComponent;

在上面的示例代码中,ExerciseRecordPage 组件用于记录运动信息,包含输入框和记录按钮。当用户点击记录按钮时,可以将运动名称和持续时间保存到本地存储或发送到后端服务器,并清空表单数据。

StatisticsComponent 组件用于展示统计数据,并生成折线图。它接收一个 exerciseData 属性,表示用户的运动记录数据。在组件内部,使用 react-chartjs-2 库来绘制折线图。通过将运动记录数据转换为图表所需的格式,更新图表数据并展示给用户。

请注意,以上代码仅为示例,实际开发中可能需要根据具体需求进行相应的调整和扩展。例如,可以添加更多的运动记录字段,实现数据的持久化存储和恢复,以及其他统计功能。

3.接下来我将为你提供一个示例代码,演示如何创建备份和恢复数据的组件

// BackupComponent.js

import React from 'react';

const BackupComponent = ({ exerciseData }) => {
  const handleBackup = () => {
    const dataToBackup = JSON.stringify(exerciseData);

    // 在这里可以将数据导出到文件,例如使用 File API 或者调用后端接口
    console.log('备份数据:', dataToBackup);
  };

  const handleRestore = (e) => {
    const file = e.target.files[0];
    const reader = new FileReader();

    reader.onload = (event) => {
      const dataToRestore = event.target.result;

      // 在这里可以从文件中导入数据并恢复到应用中
      console.log('恢复数据:', dataToRestore);
    };

    reader.readAsText(file);
  };

  return (
    <div>
      <h1>备份和恢复数据</h1>
      <button onClick={handleBackup}>备份数据</button>
      <input type="file" accept=".json" onChange={handleRestore} />
    </div>
  );
};

export default BackupComponent;

在上面的示例代码中,BackupComponent 组件用于实现备份和恢复数据的功能。它接收一个 exerciseData 属性,表示用户的运动记录数据。

handleBackup 函数中,将运动记录数据转换为 JSON 字符串,并可以将其导出到文件,例如使用浏览器的 File API 或者调用后端接口来保存文件。

handleRestore 函数中,通过文件选择器选择一个 JSON 文件,然后使用 FileReader 对象读取文件内容。读取到的数据可以进行解析和处理,例如将数据恢复到应用中。

请注意,以上代码仅为示例,实际开发中可能需要根据具体需求和技术选型进行相应的调整和扩展。例如,可以添加文件导出的格式选项,增加数据导入的验证逻辑等。

四、完整的项目示例代码

下面是一个完整的示例代码,演示如何使用Ant Design Mobile of React和本地存储localStorage来实现健身追踪应用:

// App.js

import React, { useState, useEffect } from 'react';
import { as Router, Switch, Route, Link } from 'react-router-dom';
import { Button, WingBlank, WhiteSpace } from 'antd-mobile';
import ExerciseRecordPage from './ExerciseRecordPage';
import StatisticsComponent from './StatisticsComponent';
import BackupComponent from './BackupComponent';

const App = () => {
  const [exerciseData, setExerciseData] = useState([]);

  // 从本地存储中获取数据
  useEffect(() => {
    const dataFromLocalStorage = localStorage.getItem('exerciseData');
    if (dataFromLocalStorage) {
      setExerciseData(JSON.parse(dataFromLocalStorage));
    }
  }, []);

  // 更新本地存储中的数据
  useEffect(() => {
    localStorage.setItem('exerciseData', JSON.stringify(exerciseData));
  }, [exerciseData]);

  const handleRecord = (exerciseRecord) => {
    setExerciseData((prevData) => [...prevData, exerciseRecord]);
  };

  return (
    <Router>
      <div>
        <nav>
          <WingBlank>
            <WhiteSpace />
            <Link to="/">
              <Button type="primary" size="small">
                首页
              </Button>
            </Link>
            <Link to="/record">
              <Button type="primary" size="small">
                运动记录
              </Button>
            </Link>
            <Link to="/statistics">
              <Button type="primary" size="small">
                统计数据
              </Button>
            </Link>
            <Link to="/backup">
              <Button type="primary" size="small">
                备份和恢复数据
              </Button>
            </Link>
            <WhiteSpace />
          </WingBlank>
        </nav>

        <Switch>
          <Route path="/record">
            <ExerciseRecordPage onRecord={handleRecord} />
          </Route>
          <Route path="/statistics">
            <StatisticsComponent exerciseData={exerciseData} />
          </Route>
          <Route path="/backup">
            <BackupComponent exerciseData={exerciseData} />
          </Route>
          <Route path="/">
            <h1>欢迎使用健身追踪应用!</h1>
          </Route>
        </Switch>
      </div>
    </Router>
  );
};

export default App;
// ExerciseRecordPage.js

import React, { useState } from 'react';
import { WingBlank, WhiteSpace, InputItem, Button } from 'antd-mobile';

const ExerciseRecordPage = ({ onRecord }) => {
  const [exercise, setExercise] = useState('');
  const [duration, setDuration] = useState('');

  const handleRecord = () => {
    const exerciseRecord = {
      exercise,
      duration: parseInt(duration),
      date: new Date().toLocaleDateString(),
    };

    onRecord(exerciseRecord);

    setExercise('');
    setDuration('');
  };

  return (
    <div>
      <WingBlank>
        <WhiteSpace />
        <h1>运动记录</h1>
        <InputItem
          placeholder="运动名称"
          value={exercise}
          onChange={(value) => setExercise(value)}
        >
          运动名称
        </InputItem>
        <InputItem
          placeholder="持续时间(分钟)"
          value={duration}
          onChange={(value) => setDuration(value)}
        >
          持续时间(分钟)
        </InputItem>
        <WhiteSpace />
        <Button type="primary" onClick={handleRecord}>
          记录
        </Button>
        <WhiteSpace />
      </WingBlank>
    </div>
  );
};

export default ExerciseRecordPage;
// StatisticsComponent.js

import React, { useState } from 'react';
import { WingBlank, WhiteSpace, Button, Toast, List } from 'antd-mobile';
import { Line } from 'react-chartjs-2';

const StatisticsComponent = ({ exerciseData }) => {
  const [chartData, setChartData] = useState({
    labels: [],
    datasets: [
      {
        label: '运动时长',
        data: [],
        backgroundColor: 'rgba(75,192,192,0.4)',
        borderColor: 'rgba(75,192,192,1)',
        borderWidth: 2,
      },
    ],
  });

  const updateChartData = () => {
    const labels = exerciseData.map((record) => record.date);
    const durations = exerciseData.map((record) => record.duration);

    setChartData((prevState) => ({
      ...prevState,
      labels,
      datasets: [
        {
          ...prevState.datasets[0],
          data: durations,
        },
      ],
    }));
  };

  return (
    <div>
      <WingBlank>
        <WhiteSpace />
        <h1>统计数据</h1>
        <Button type="primary" onClick={updateChartData}>
          更新图表
        </Button>
        <WhiteSpace />
        <Line data={chartData} />
        <WhiteSpace />
        <h2>运动记录</h2>
        <List>
          {exerciseData.map((record, index) => (
            <List.Item key={index}>
              运动:{record.exercise},时长:{record.duration}分钟
            </List.Item>
          ))}
        </List>
      </WingBlank>
    </div>
  );
};

export default StatisticsComponent;
// BackupComponent.js

import React from 'react';
import { WingBlank, WhiteSpace, Button } from 'antd-mobile';

const BackupComponent = ({ exerciseData }) => {
  const handleBackup = () => {
    const dataToBackup = JSON.stringify(exerciseData);
    console.log('备份数据:', dataToBackup);
    // 在这里可以将数据导出到文件,例如使用 File API 或者调用后端接口
    Toast.success('数据已备份', 1);
  };

  const handleRestore = (e) => {
    const file = e.target.files[0];
    const reader = new FileReader();

    reader.onload = (event) => {
      const dataToRestore = event.target.result;
      console.log('恢复数据:', dataToRestore);
      // 在这里可以从文件中导入数据并恢复到应用中
      Toast.success('数据已恢复', 1);
    };

    reader.readAsText(file);
  };

  return (
    <div>
      <WingBlank>
        <WhiteSpace />
        <h1>备份和恢复数据</h1>
        <Button type="primary" onClick={handleBackup}>
          备份数据
        </Button>
        <WhiteSpace />
        <input type="file" accept=".json" onChange={handleRestore} />
        <WhiteSpace />
      </WingBlank>
    </div>
  );
};

export default BackupComponent;

以上代码是一个完整的健身追踪应用示例,包含了登录页面、主页、运动记录页面、统计组件、备份和恢复数据组件等功能。通过使用Ant Design Mobile of React和本地存储,实现了记录每日运动和健身活动、展示统计数据、备份和恢复数据等功能。

请注意,以上代码仅为示例,实际开发中可能需要根据具体需求和设计进行相应的调整和扩展。另外,还需要注意数据的验证、错误处理、样式美化等方面的工作。

五、知识点归纳总结和分别示例代码

(一)在创建健身追踪应用的过程中,涉及到了以下知识点:

  1. React组件:使用React框架来构建应用的界面和功能,通过创建函数组件或类组件来定义页面和组件。
  2. 状态管理:使用React的useState钩子来管理组件的状态,例如记录用户输入的数据、保存运动记录等。
  3. 路由管理:使用React Router库来管理应用的路由,实现不同页面之间的切换和导航。
  4. Ant Design Mobile of React:使用Ant Design Mobile of React组件库来快速构建移动端界面,包括按钮、输入框、列表等。
  5. 本地存储:使用浏览器的本地存储(如LocalStorage)来保存应用的数据,实现数据的持久化存储和恢复。
  6. 图表绘制:使用React Chart.js库来绘制折线图,展示统计数据。
  7. 文件操作:使用File API和FileReader对象来实现文件的导出和导入,实现数据的备份和恢复。
  8. 数据处理和传递:对用户输入的数据进行处理、验证和转换,将数据传递给其他组件进行展示或进行其他操作。

以上是创建健身追踪应用所涉及的主要知识点。通过理解和掌握这些知识点,可以开发出功能完善、用户友好的健身追踪应用。当然,在实际开发中还需要考虑其他方面的细节,如错误处理、用户体验优化等。

(二)下面我将为你提供每个知识点的示例代码

  1. React组件示例代码:
import React from 'react';

const MyComponent = () => {
  return <h1>Hello, World!</h1>;
};

export default MyComponent;

2.  状态管理示例代码:

import React, { useState } from 'react';

const Counter = () => {
  const [count, setCount] = useState(0);

  const increment = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
};

export default Counter;

3.  路由管理示例代码:

import React from 'react';
import { BrowserRouter as Router, Switch, Route, Link } from 'react-router-dom';
import Home from './Home';
import About from './About';
import Contact from './Contact';

const App = () => {
  return (
    <Router>
      <div>
        <nav>
          <ul>
            <li>
              <Link to="/">Home</Link>
            </li>
            <li>
              <Link to="/about">About</Link>
            </li>
            <li>
              <Link to="/contact">Contact</Link>
            </li>
          </ul>
        </nav>

        <Switch>
          <Route path="/about">
            <About />
          </Route>
          <Route path="/contact">
            <Contact />
          </Route>
          <Route path="/">
            <Home />
          </Route>
        </Switch>
      </div>
    </Router>
  );
};

export default App;

4.  Ant Design Mobile of React示例代码:

import React from 'react';
import { Button } from 'antd-mobile';

const MyButton = () => {
  return <Button type="primary">Click me</Button>;
};

export default MyButton;

5.  本地存储示例代码:

import React, { useState, useEffect } from 'react';

const MyComponent = () => {
  const [data, setData] = useState('');

  useEffect(() => {
    const savedData = localStorage.getItem('myData');
    if (savedData) {
      setData(savedData);
    }
  }, []);

  const handleSave = () => {
    localStorage.setItem('myData', data);
  };

  return (
    <div>
      <input
        type="text"
        value={data}
        onChange={(e) => setData(e.target.value)}
      />
      <button onClick={handleSave}>Save</button>
    </div>
  );
};

export default MyComponent;

6.  图表绘制示例代码:

import React from 'react';
import { Line } from 'react-chartjs-2';

const MyChart = () => {
  const chartData = {
    labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
    datasets: [
      {
        label: 'Sales',
        data: [12, 19, 3, 5, 2, 3, 10],
        backgroundColor: 'rgba(75,192,192,0.4)',
        borderColor: 'rgba(75,192,192,1)',
        borderWidth: 2,
      },
    ],
  };

  return <Line data={chartData} />;
};

export default MyChart;

7.  文件操作示例代码:

import React from 'react';

const MyFileComponent = () => {
  const handleFileUpload = (event) => {
    const file = event.target.files[0];
    console.log('File uploaded:', file);
  };

  const handleFileDownload = () => {
    const data = 'Hello, World!';
    const blob = new Blob([data], { type: 'text/plain' });
    const url = URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.href = url;
    link.download = 'myFile.txt';
    link.click();
  };

  return (
    <div>
      <input type="file" onChange={handleFileUpload} />
      <button onClick={handleFileDownload}>Download</button>
    </div>
  );
};

export default MyFileComponent;

以上是每个知识点的简单示例代码,可以作为参考来理解和学习相关概念和用法。请注意,这些示例代码仅作为示例,实际应用中可能需要根据具体需求进行调整和扩展。

8.  数据处理和传递示例代码:

import React, { useState } from 'react';

const FormComponent = () => {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');

  const handleSubmit = (event) => {
    event.preventDefault();

    // 处理表单提交逻辑
    if (username === 'admin' && password === 'password') {
      alert('登录成功');
    } else {
      alert('用户名或密码错误');
    }

    // 清空表单数据
    setUsername('');
    setPassword('');
  };

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label>用户名:</label>
        <input
          type="text"
          value={username}
          onChange={(e) => setUsername(e.target.value)}
        />
      </div>
      <div>
        <label>密码:</label>
        <input
          type="password"
          value={password}
          onChange={(e) => setPassword(e.target.value)}
        />
      </div>
      <button type="submit">登录</button>
    </form>
  );
};

export default FormComponent;

以上示例代码展示了一个简单的登录表单组件。在表单提交时,通过判断输入的用户名和密码是否正确来进行相应的处理。如果登录成功,弹出登录成功的提示;如果用户名或密码错误,弹出错误提示。

在处理表单提交时,可以根据具体需求进行进一步的处理,例如调用后端接口进行验证、进行表单验证等。这个示例代码主要展示了如何处理表单数据以及进行简单的逻辑判断。


阅读量:512

点赞量:0

收藏量:0