# multilingual_shop
**Repository Path**: iiiboy/multilingual_shop
## Basic Information
- **Project Name**: multilingual_shop
- **Description**: 多语言电商平台前端部分,使用react+react-bootstrap进行设计开发,使用axios进行数据请求,使用redux,redux-saga进行公共数据管理,react-router进行路由管理.
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2020-09-10
- **Last Updated**: 2021-03-30
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 多语言电商项目(毕业设计)react实现
## 1. 使用到的技术栈
react,node,koa
## 2. 创建项目,搭建环境
1. 使用`npx create-react-app project`创建react项目
2. 使用react-bootstrap作为ui框架,并且在上下载bootstrap主题,然后使用`yarn add react-bootstrap`安装依赖
3. 因为react项目默认为sass,但是我更习惯用less,所以需要配置less环境:`yarn add less less-loader react-app-rewired customize-cra -D`
安装对应依赖,然后再src目录下创建config-overrides.js进行配置,注意:
如果配置完成还是报错,可能是less-loader版本出现问题,可以删除当前版本的less-loader,然后`yarn add less-loader@5.0.0 -D`
4. 因为react-i18next使用比较复杂,没有相应中文文档,而且教程较少
下面换到react-intl-universal这个库由阿里开发,主要参考
```jsx
import React, { Component } from 'react'
import Routes from './routes/Routes'
// ! 这里将intl的初始化放到App组件里面来进行 经过实测这样还是会遇到intl.get()为空的情况
import intl from 'react-intl-universal'
import resource from './locales/resource'
import './plugins/font-awesome'
import './plugins/axios'
// 可以借助intl.determineLocale获取当前浏览器的语言环境设置初始化的语言环境
// 这个函数会返回字符串 就是当前获取到的环境
const lng = intl.determineLocale({
// 但是这里建议不要使用localStorage来更改当前页面语言环境
// 因为当你修改localStorage的lang字段之后没有刷新页面 是不会更改语言的 所以使用 url 或者cookie
// localStorageLocaleKey:'lang', // 这个用于从localStorage中确定语言环境,寻找 lang 这个键名
// *注意 当这里声明了但是匹配不上时 会默认为当前浏览器的语言环境 也就是 navigator.language
urlLocaleKey: 'lang',
localStorageLocaleKey: 'lang',
fallbackLocale: 'zh-CN' // 当所有的匹配不上时就使用这个备用的
})
class App extends Component {
// 这里很重要 在没有constructor时 将state写在最前面就相当于 在constructor里面写state
// isDone用于判断intl是否初始化完成
state = { isDone: false }
componentDidMount () {
// 组件挂载完成后进行初始化intl
this.loadLocales()
}
// 这里是intl用于初始化的函数
loadLocales = () => {
intl.init({
currentLocale: lng,
fallbackLocale: 'zh_CN',
locales: resource
}).then(() => {
// 这里时初始化完成后触发
this.setState({ isDone: true })
})
}
render () {
return (
// !第一次挂载时 因为isDone为false 所以并没有挂载渲染Routes 当初始化完成时才进行渲染
// !这样其实很重要,保证了一下所有的组件所处的环境都是intl渲染完成后的 不然的话 会遇到 intl.get()获取到空的情况
// !!!经过实测 这样还是会遇到intl.get()为空的情况 目前没有好的方法
// !只能在componentDidMount()进行定义 或者在 render() 中进行定义
// !好像还有一种方法 但是对于我目前的情况 不是很适用 https://blog.csdn.net/chenqk_123/article/details/102858073
this.state.isDone &&
)
}
}
export default App
```
## 3. 需要先移除之前的库 然后进行配置
## 4. 在项目中使用font-awesome
参考这个网址:
官方文档:
1.
使用 `yarn add @fortawesome/fontawesome-svg-core @fortawesome/free-solid-svg-icons @fortawesome/react-fontawesome @fortawesome/free-brands-svg-icons @fortawesome/free-regular-svg-icons`
安装这么多依赖
2. 这样进行使用
```jsx
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faQuestionCircle } from '@fortawesome/free-regular-svg-icons';
```
3. 像上面那样每个组件太麻烦了 我们可以将一些使用比较多的icon注册到全局
3.1 src下创建plugins文件夹
3.2 在plugins文件夹下创建font-awesome.js文件,并且进行配置
```js
import { library } from '@fortawesome/fontawesome-svg-core'
import { fab } from '@fortawesome/free-brands-svg-icons'
import { faCheckSquare, faCoffee } from '@fortawesome/free-solid-svg-icons'
// 这个library 就相当于是全局 add就是添加到全局
// 接下来我们就可以之直接 这样使用 注意使用这种方式要去掉'fa'
library.add(fab, faCheckSquare, faCoffee)
```
3.3 在app.js下进行导入 `import './plugins/font-awesome'`
## 5. react-bootstrap进行表单验证
1. react-bootstrap 可以使用constraint validation API 进行表单验证 这个api相当于是H5的新特性,可以直接通过html5,js进行一些 简单的表单验证
参考网址:
参考网址:
主要的验证规则:
1.1 pattern 正则匹配 1.2 min 最小值 1.3 max 最大值 1.4 required 是否必需 1.5 step 暂时没有看懂 后面可以理解一下 1.6 maxlength最大长度 1.7
minlength最小长度
```jsx
// 因为是原生的api所以可以直接使用 具体的可以看react-bootstrap官网
import React from 'react'
class Example extends React.Component {
constructor (props) {
super(props)
this.state = {}
}
onSubmit = (event) => {
const form = event.currentTarget
if (form.checkValidity() === false) {
event.preventDefault()
}
this.setState({}, () => {
console.log(this.state)
})
}
render () {
return (
)
}
}
```
2. 如果使用validation API无法满足需求的话 还可以使用react-formal,formik配合yup进行验证,react-bootstrap中有formik进行验证
```jsx
// 注意引入formik的方式
import { Formik } from 'formik'
// 引入yup的方式
import * as yup from 'yup'
import React, { Component } from 'react'
const schema = yup.object().shape({
email: yup.string().required('请输入邮箱!'),
password: yup.string().required('请输入密码!')
})
class Login extends Component {
render () {
return (
<>
{/*
* 注意这里的使用方法 Formik 组件只是 formik依赖的一个组件 还有其他的可以去官方文档看
* Formik 有很多属性可以看源码
*/}
{
({
handleSubmit, handleChange, handleBlur,
// 这里就相当于是上面Formik的initialValues
values,
// 默认的字段信息 用于做提示
touched,
// 是否全部通过验证
isValid,
// 没有通过验证
errors
}) => {
return (
{errors.email}
{errors.password}
{touched.password}
)
}
}
>
)
}
}
```
## 6. 创建store存储用户信息
1. 获取用户信息的话需要进行网络请求,这里使用的是axios进行网络请求的,在plugins/axios.js对axios进行了一些默认的配置,
然后又在services里对get,post,put,delete请求方法进行了封装,就可以直接引入services/http.js里的方法进行网络请求了, 而且后面还可以在http.js文件中进行集中的错误处理
2. 网络请求这方面完成后,还需要创建store用于存储用户信息 其他的没什么好说的,主要是redux处理异步的情况,我选择使用redux-saga 看之前的笔记就在lesson_05_saga redux-saga
官方网址:
3. 使用saga的步骤 同时还有启动redux-devtools
```js
import { createStore, combineReducers, applyMiddleware } from 'redux'
// 这个用于启动redux-devtools 便于浏览器redux工具的配合
// 参考网址 https://www.npmjs.com/package/redux-devtools-extension
import { composeWithDevTools } from 'redux-devtools-extension'
// 1. 导入创建saga中间件的函数
import createSagaMiddleware from 'redux-saga'
// 2. 导入对应的generator函数
import { userSaga } from '../sagas/userSaga'
import { user } from './reducers/user'
// 注意使用saga的步骤
// 3. 创建saga中间件
const sagaMiddleware = createSagaMiddleware()
const store = createStore(
combineReducers({
user
}),
// 4. 使用saga中间件 注意redux-devtools同时还需要监听中间件 所以这里使用这个函数包裹中间件
composeWithDevTools(applyMiddleware(sagaMiddleware))
)
// 5. 使用generator函数
sagaMiddleware.run(userSaga)
export default store
```
4. 开始正确使用redux-saga 4.1 saga是用于处理redux的,所以需要先创建store,reducer,actions等一系列操作,创建完成后,在页面中使用connect连接组件,注入dispatch 4.2
在页面中就可以使用dispatch来触发saga 下面是saga的基础写法
```js
import {
takeEvery,// 用于监听
call,// 用于异步请求
put,// 相当于原生dispatch用于分发
select// 用于获取当前state
} from 'redux-saga/effects'
import { LOGIN_USER, UPDATE_USER } from '../constants/user'
// 注意这里的loginUser是这样的 export const loginUser = () => httpGet({ url: '/user/current' }) 所以下面call时不用传入参数
import { loginUser } from '../actions/userActions'
// 创建并导出generator函数
export function * userSaga () {
console.log('redux-saga创建成功')
// !注意这里哦 !!! 这里监听的type 前往不要与分发的type一样 如果一样了 就会一直dispatch 然后一直监听触发
// !陷入死循环
yield takeEvery(LOGIN_USER, function * (...aru) {
// 这里的loginUser这个函数不用传入参数 如果需要传参的话 就直接在后面添加参数就是了 与改变this指向的call一样的传参方式
const [res] = yield call(loginUser)
if (res) {
// !这里分发的type 前往不要和分发的type一样
yield put({ type: UPDATE_USER, payload: res.data.data })
}
// * 注意 这里的返回值好像是下一个yield的参数, 但是这里使用的是一个函数 应该不一样
return '登陆成功'
})
}
```
# 7. 使用redux-persist让redux持久化
redux-persist的npm网址:
这个网上一找一大推的教程
## 8. 去掉input为number时的上下箭头
```css
input[type=number] {
-moz-appearance: textfield;
}
input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
```
## 9. react ref的所有注册方式
## 10. react遍历生成ref