项目实战【vue,react,微信小程序】(1705E)
目录
一、git
1、git简介
2、github简介
3、在github上创建项目
4、克隆代码
5、提交代码
6、git工作区
7、分支
8、对比分支
9、生成ssh key
10、安装git
11、安装小乌龟
12、忽略提交.gitignore
13、git配置用户名和邮箱
14、git免密
参考链接
二、MySql
1、安装mysql
2、安装Navicat
3、破解Navicat
4、Navicat连接mysql报错的解决办法
5、使mysql允许外部连接访问
6、Navicat建立MySql连接
7、sql语句简介
8、nodejs封装sql查询
9、不使用vue.config.js,单独使用node
10、封装api接口
11、axios拦截器
12、redis
13、jwt-simple
14、uuid
15、node操纵mysql数据库进行增删查改以及登录退出
三、vue
1、周考一
四、react
1、hook入门
五、微信小程序
1、书城
github源码
一、git
1、git简介
Git 是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。
Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。
Git 与常用的版本控制工具 CVS, Subversion 等不同,它采用了分布式版本库的方式,不必服务器端软件支持。
2、github简介
章鱼猫:GitHub的吉祥物(Octocat)
GitHub是一个面向开源及私有软件项目的托管平台,因为只支持git 作为唯一的版本库格式进行托管,故名GitHub。
2018年6月4日,微软宣布,通过75亿美元的股票交易收购代码托管平台GitHub。
3、在github上创建项目
4、克隆代码
git clone git@github.com:baweireact/m-app-test.git
5、提交代码
添加要上传的文件:
git add README.md
提交到本地:
git commit -m "first commit"
提交到远程:
git push origin master
git add readme.txtgit add readme.txt ant.txt
git add *.html
git add all
git add .
git add *
git log
git status
git add . 会把本地所有untrack的文件都加入暂存区,并且会根据.gitignore做过滤,但是git add * 会忽略.gitignore把任何文件都加入
6、git工作区
使用 git add 命令将想要快照的内容写入缓存区, 而执行 git commit 将缓存区内容添加到本地仓库中。
7、分支
::切换到develop分支git checkout beta
git pull origin beta
::把develop分支的代码合并到beta上
git merge develop
git status
::push到远程beta
git push origin beta
::切换到develop分支
git checkout develop
echo. & pause
新建分支:
git branch feature_x
将分支提交到远程:
git push origin feature_x
切换分支:
git checkout master
查看有所有分支:
git branch -a
查看本地分支:
git branch
创建新分支并立即切换到该分支下:
git checkout -b feature_login
在github上查看有哪些分支:
删除本地分支:
git branch -d feature_x
删除远程分支:
git push origin -d feature_x
合并分支,合并后再提交到远程仓库(先切换到master分支,然后合并feature_login分支到master分支,然后再把合并后的代码提交到远程仓库):
git merge feature_logingit push origin master
查看历史记录(按Q键退出历史记录):
git log
查看简洁历史记录:
git log --oneline
反顺序的历史记录:
git log --reverse
8、对比分支
git diff master feature_login
9、生成ssh key
git clone 时,可以所用不同的协议,包括 ssh, git, https 等,其中最常用的是 ssh,因为速度较快,还可以配置公钥免输入密码
ssh-keygen -t rsa -C "1183391880@qq.com"
生成的key的位置:
github添加key:
点击setting:
新建ssh key :
把生成的key粘贴到github上:
确保启用 SSH 代理:
$ eval "$(ssh-agent -s)"
为 SSH key 启用 SSH 代理:
$ ssh-add ~/.ssh/id_rsa
10、安装git
11、安装小乌龟
配置ssh:
12、忽略提交.gitignore
在使用Git的过程中,我们喜欢有的文件比如日志,临时文件,编译的中间文件等不要提交到代码仓库,这时就要设置相应的忽略规则,来忽略这些文件的提交。
/mtk 过滤整个文件夹
*.zip 过滤所有.zip文件
参考链接:
https://www.jianshu.com/p/74bd0ceb6182
13、git配置用户名和邮箱
全局配置用户名:
git config --global user.name "xutongbao"
全局配置邮箱:
git config --global user.email "1183391880@qq.com"
14、git免密
ssh配置失败的同学,可以用https协议下载代码,而且也可以配置免密!
用git时,每次都需要输入密码会比较麻烦。
可以进行设置,这样在输入过一次密码之后,以后就不需要每次都输入密码了。
打开终端输入 :
touch ~/.git-credentials
再输入:
git config --global credential.helper store
参考链接
git使用简易指南:
https://www.bootcss.com/p/git-guide/
加入到暂存区参考链接:
http://www.softwhy.com/article-8489-1.html
设置ssh key出问题的可以参考下面的链接:
https://blog.csdn.net/felicity294250051/article/details/53606158
https://blog.csdn.net/goawaycow1/article/details/78069487
二、MySql
1、安装mysql
2、安装Navicat
3、破解Navicat
4、Navicat连接mysql报错的解决办法
第一句:修改加密规则
第二句:更新用户密码
第三句:刷新权限
alter user 'root'@'localhost' identified by 'root' password expire never;alter user 'root'@'localhost' identified with mysql_native_password by 'root';
flush privileges;
参考链接:
https://www.jianshu.com/p/c8eb6d2471f8
5、使mysql允许外部连接访问
update user set host='%' where user='root';flush privileges;
6、Navicat建立MySql连接
7、sql语句简介
通过sql语句实现增删查改:
-- 建表create table user (
id varchar(100) primary key,
username varchar(100),
password varchar(100)
);
-- 增
insert into user values ('001', 'admin', '123456');
insert into user values ('002', 'xu', '123456');
insert into user values ('003', 'xutongbao', '123456');
-- 删
delete from user;
delete from user where id = '003';
-- 查
select * from user;
select username from user;
select * from user where id = '002';
-- 模糊搜索
select * from user where username like '%n%';
-- 降序
select * from user order by username desc;
-- 升序
select * from user order by username asc;
-- 分页
select * from user order by username asc limit 1,2;
-- 数量
select count(*) from user;
-- 改
update user set password = '123';
update user set password = '1234' where id = '001';
8、nodejs封装sql查询
mysqlQuery.js:
const mysql = require('mysql')let connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'root',
database: 'demo'
})
connection.connect((error) => {
if (error) {
console.log('失败')
} else {
console.log('成功')
}
})
//使用回调函数返回查询结果
const query = (sql, callback) => {
connection.query(sql, (error, results) => {
if (error) {
throw error
} else {
callback && callback(results)
}
})
}
//使用promise封装sql查询
const queryPromise = (sql) => {
return new Promise((resolve, reject) => {
connection.query(sql, (error, results) => {
if (error) {
reject(error)
} else {
resolve(results)
}
})
})
}
module.exports = {
query,
queryPromise
}
vue.config.js:
const { query, queryPromise } = require('./mysqlQuery')module.exports = {
devServer: {
open: true,
before(app) {
app.get('/api/get_user_query', async (req, res) => {
query(`select * from user`, (results) => {
res.send({
code: 200,
data: results,
message: '用户列表'
})
})
})
app.get('/api/get_user', async (req, res) => {
let results = await queryPromise(`select * from user`)
res.send({
code: 200,
data: results,
message: '用户列表'
})
})
}
}
}
9、不使用vue.config.js,单独使用node
主要是为了可以使用nodemon,后端代码改变时不需要重启
const express = require('express')const cors = require('cors')
const { queryPromise } = require('./mysqlQuery')
const app = express()
app.use(cors())
app.get('/api/get_user', async (req, res) => {
let users = await queryPromise('select * from user')
res.send({
code: 200,
data: users,
message: '用户列表'
})
})
app.listen(3000, () => {
console.log('3000端口')
})
参考链接:
跨域:
http://www.expressjs.com.cn/en/resources/middleware/cors.html
express:
http://www.expressjs.com.cn/starter/hello-world.html
nodemon:
https://www.npmjs.com/package/nodemon
10、封装api接口
index.js:
import axios from 'axios'import url from './url'
axios.defaults.baseURL = 'http://localhost:3000'
const common = async (config) => {
const response = await axios(config)
return response
}
export default {
getUser: () => common({ url: url.getUser })
}
url.js:
export default { getUser: '/api/get_user'
}
11、axios拦截器
前端请求前添加token,请求后判断状态码:
import axios from 'axios'import url from './url'
axios.defaults.baseURL = 'http://localhost:3000'
axios.interceptors.request.use((config) => {
config.headers.token = '666'
return config
})
axios.interceptors.response.use((res) => {
if (res.data.code === 200) {
return res
} else if (res.data.code === 400) {
alert(res.data.message)
return res
} else if (res.data.code === 403) {
window.location.href = '/login'
}
})
const common = async (config) => {
const response = await axios(config)
return response
}
export default {
getUser: () => common({ url: url.getUser })
}
后端接收token:
const express = require('express')const cors = require('cors')
const { queryPromise } = require('./mysqlQuery')
const app = express()
app.use(cors())
app.get('/api/get_user', async (req, res) => {
let token = req.headers.token
console.log(token)
let users = await queryPromise('select * from user')
res.send({
code: 400,
data: users,
message: '用户列表'
})
})
app.listen(3000, () => {
console.log('3000端口')
})
参考链接:
http://www.axios-js.com/docs/#Interceptors
12、redis
用于保存token
安装:
启动:
在控制台使用:
//启动redis-server.exe redis.windows.conf
//访问
redis-cli.exe -h 127.0.0.1 -p 6379
//设置值
set a 1
//获取值
get a
//删除key
del a
//设置一个值20秒后删除
set a 1 EX 20
参考链接:
https://www.npmjs.com/package/redis
13、jwt-simple
用于生成token
参考链接:
https://www.npmjs.com/package/jwt-simple
14、uuid
用于生成用户id
参考链接:
https://www.npmjs.com/package/uuid
15、node操纵mysql数据库进行增删查改以及登录退出
app.js:
const express = require('express')const cors = require('cors')
const redis = require('redis')
const bodyParser = require('body-parser')
const jwt = require('jwt-simple')
const uuidv1 = require('uuid/v1')
const { queryPromise } = require('./mysqlQuery')
const app = express()
//跨域
app.use(cors())
app.use(bodyParser.json())
var secret = 'xxx';
//如果没有启动redis,会报错,启动redis方法,在cd到redis的安装目录,执行redis-server.exe redis.windows.conf
const client = redis.createClient()
client.on('error', (err) => {
console.log('redis错误:' + err)
})
//检查token是否存在,并更新token过期时间
const checkToken = async (token) => {
let result = await new Promise((resolve) => {
client.get(token, function (err, res) {
return resolve(res);
});
});
console.log(result)
if (result) {
client.set(token, token , 'EX', 600)
return true
} else {
return false
}
}
//增
app.post('/api/add_user', async (req, res) => {
let token = req.headers.token
let { username, password } = req.body
let isLogin = await checkToken(token)
if (isLogin) {
let users = await queryPromise(`select * from user where username = '${username}'`)
console.log(users)
if (users.length > 0) {
res.send({
code: 400,
data: {
username
},
message: '用户名已存在'
})
} else {
let id = uuidv1()
let user = await queryPromise(`insert into user values('${id}', '${username}', '${password}')`)
if (user) {
res.send({
code: 200,
data: user,
message: '添加成功'
})
}
}
} else {
res.send({
code: 403,
message: '登录过期'
})
}
})
//删
app.post('/api/delete_user', async (req, res) => {
let token = req.headers.token
let { ids } = req.body
let isLogin = await checkToken(token)
if (isLogin) {
let idString = ''
for (let i = 0; i < ids.length; i++) {
if (i === ids.length - 1) {
idString += ` id = '${ids[i]}' `
} else {
idString += ` id = '${ids[i]}' or `
}
}
let result = await queryPromise(`delete from user where ${idString}`)
res.send({
code: 200,
data: result,
message: '删除成功'
})
} else {
res.send({
code: 403,
message: '登录过期'
})
}
})
//查
app.get('/api/get_user', async (req, res) => {
let token = req.headers.token
let isLogin = await checkToken(token)
if (isLogin) {
let users = await queryPromise('select * from user')
res.send({
code: 200,
data: users,
message: '用户列表'
})
} else {
res.send({
code: 403,
message: '登录过期'
})
}
})
//改
app.post('/api/update_user', async (req, res) => {
let token = req.headers.token
let { id, username, password } = req.body
let isLogin = await checkToken(token)
if (isLogin) {
let result = await queryPromise(`update user set username = '${username}', password = '${password}' where id = '${id}' `)
res.send({
code: 200,
data: result,
message: '更新成功'
})
} else {
res.send({
code: 403,
message: '登录过期'
})
}
})
//登录
app.post('/api/login', async (req, res) => {
let { username, password } = req.body
let users = await queryPromise('select * from user')
let user = users.find(item => item.username === username && item.password === password)
if (user) {
let token = jwt.encode(user.id, secret)
client.set(token, token , 'EX', 600) //60秒后验证码过期知道
res.send({
code: 200,
data: {
username,
token
},
message: '登录成功'
})
} else {
res.send({
code: 400,
message: '登录失败'
})
}
})
//退出
app.post('/api/login_out', (req, res) => {
let token = req.headers.token
client.del(token)
res.send({
code: 200,
message: '退出'
})
})
app.listen(3000, () => {
console.log('3000端口')
})
mysqlQuery.js:
const mysql = require('mysql')let connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'root',
database: 'demo'
})
connection.connect((error) => {
if (error) {
console.log('失败')
} else {
console.log('成功')
}
})
//使用回调函数返回查询结果
const query = (sql, callback) => {
connection.query(sql, (error, results) => {
if (error) {
throw error
} else {
callback && callback(results)
}
})
}
//使用promise封装sql查询
const queryPromise = (sql) => {
return new Promise((resolve, reject) => {
connection.query(sql, (error, results) => {
if (error) {
reject(error)
} else {
resolve(results)
}
})
})
}
module.exports = {
query,
queryPromise
}
三、vue
1、周考一
四、react
1、hook入门
React的组件化给前端开发带来了前所未有的体验,我们可以像玩乐高玩具一样将组件堆积拼接起来,组成完整的UI界面,在加快开发速度的同时又提高了代码的可维护性。
Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。
hook = 钩子
参考链接:
https://cloud.tencent.com/developer/article/1468196
https://react.docschina.org/docs/hooks-intro.html
useState、useEffect:
import React, { useState, useEffect } from 'react'const App = () => {
const [ count, setCount ] = useState(0)
const [ obj, setObj ] = useState({
name: 'xu',
job: 'web'
})
//初始化state可以使用函数
const [ name, setName ] = useState(() => {
return 'xu'
})
//每次更新完都会执行
useEffect(() => {
console.log(count)
return () => {
console.log('执行当前effect之前对上一个effect进行清除!' + count)
}
})
//只执行一次
useEffect(() => {
console.log('只执行一次!')
}, [])
useEffect(() => {
console.log('count更新时执行' + count)
}, ['count'])
return (
<div>
{ count }
<div>
<button onClick={() => { setCount(count - 1) }}>减</button>
<button onClick={() => { setCount(count + 1) }}>加</button>
<button onClick={() => { setCount(prevCount => {
return prevCount + 1
}) }}>加</button>
<button onClick={() => setCount(0)}>重置</button>
</div>
{ obj.name }, { obj.job }
<div>
<button onClick={() => setObj({ name: '徐' })}>改名(删除了job字段)</button>
<button onClick={() => setObj( prevObj => {
return {...prevObj, name: '星河'}
})}>改名(不会删除job字段)</button>
</div>
<div>
{name}
</div>
</div>
)
}
export default App
useReducer:
import React, { useReducer } from 'react'const initalState = { count: 0 }
const reducer = (state, action) => {
switch (action.type) {
case 'increment':
return { count: state.count + 1 }
case 'decrement':
return { count: state.count - 1 }
default:
return state
}
}
const App = () => {
const [state, dispatch] = useReducer(reducer, initalState)
return (
<div>
{state.count}
<div>
<button onClick={() => { dispatch({ type: 'decrement' }) }}>减</button>
<button onClick={() => { dispatch({ type: 'increment' }) }}>加</button>
</div>
</div>
)
}
export default App
使用函数初始化state:
import React, { useReducer } from 'react'const initalState = { count: 0 }
const init = (a) => {
return {count: a.count + 1}
}
const reducer = (state, action) => {
switch (action.type) {
case 'increment':
return { count: state.count + 1 }
case 'decrement':
return { count: state.count - 1 }
default:
return state
}
}
const App = () => {
const [state, dispatch] = useReducer(reducer, initalState, init)
return (
<div>
{state.count}
<div>
<button onClick={() => { dispatch({ type: 'decrement' }) }}>减</button>
<button onClick={() => { dispatch({ type: 'increment' }) }}>加</button>
</div>
</div>
)
}
export default App
useRef,输入框获取焦点:
import React, { useRef, useEffect } from 'react'const App = () => {
const inputEl = useRef(null)
const handleFocus = () => {
inputEl.current.focus()
}
useEffect(() => {
inputEl.current.focus()
}, [])
return (
<div>
<input ref={inputEl}></input>
<div>
<button onClick={handleFocus}>获取焦点</button>
</div>
</div>
)
}
export default App
自定义hook,获取上一轮的state:
import React, { useState, useRef, useEffect } from 'react'//自定义hook,获取上一轮的state
const usePrevious = (value) => {
const ref = useRef()
useEffect(() => {
ref.current = value
})
return ref.current
}
const App = () => {
const [ count, setCount ] = useState(0)
const prevCount = usePrevious(count)
return (
<div>
{count}, {prevCount}
<div>
<button onClick={() => setCount(count + 1)}>加</button>
</div>
</div>
)
}
export default App
获取数据:
function SearchResults() { const [data, setData] = useState({ hits: [] });
const [query, setQuery] = useState('react');
useEffect(() => {
let ignore = false;
async function fetchData() {
const result = await axios('https://hn.algolia.com/api/v1/search?query=' + query);
if (!ignore) setData(result.data);
}
fetchData();
return () => { ignore = true; }
}, [query]);
return (
<>
<input value={query} onChange={e => setQuery(e.target.value)} />
<ul>
{data.hits.map(item => (
<li key={item.objectID}>
<a href={item.url}>{item.title}</a>
</li>
))}
</ul>
</>
);
}
2、路由懒加载,代码分割
参考链接:
https://zh-hans.reactjs.org/docs/react-api.html#reactsuspense
https://blog.csdn.net/xutongbao/article/details/84822315
import React, { Component, Suspense, lazy } from 'react'import { Switch, Route, NavLink, Redirect } from 'react-router-dom'
// import Home from './Home'
// import MyBook from './MyBook'
import Detail from './Detail'
import Loading from '../components/Loading'
const MyBook = lazy(() => import('./MyBook'))
const Home = lazy(() => import('./Home'))
class Index extends Component {
render() {
return (
<div>
<div>
<NavLink to="/index/home" className="m-nav-item">首页</NavLink>
<NavLink to="/index/my_book" className="m-nav-item">书架</NavLink>
</div>
<Suspense fallback={<Loading></Loading>}>
<Switch>
<Route exact path="/index/home" component={Home}></Route>
<Route path="/index/my_book" render={() => {
if (localStorage.getItem('username')) {
return <MyBook></MyBook>
} else {
return <Redirect to="/login"></Redirect>
}
}}></Route>
<Route path="/index/home/detail/:id" component={Detail}></Route>
</Switch>
</Suspense>
</div>
)
}
}
export default Index
3、图片懒加载
装包:
yarn add react-lazy-load
<LazyLoad height={300} onContentVisible={() => console.log(item.title)}> <img src={item.avatar} ></img>
</LazyLoad>
参考链接:
https://www.npmjs.com/package/react-lazy-load
五、微信小程序
1、购物车
2、入门
申请账号:
https://mp.weixin.qq.com/wxopen/waregister?action=step1
安装开发者工具:
登录账号:
https://mp.weixin.qq.com/
3、轮播图
参考链接:https://www.cnblogs.com/zjjDaily/p/8041734.html
<swiper indicator-dots="{{true}}"
autoplay="{{true}}"
interval="{{1000}}"
style="height:{{height}}px">
<swiper-item wx:for="{{banner}}" wx:key="{{index}}">
<image src="{{item}}" mode="widthFix" class="m-item-img" bindload="handleImageLoad"></image>
</swiper-item>
</swiper>
4、tabbar
"tabBar": { "list": [{
"text": "首页",
"selectedIconPath": "./static/index-active.png",
"iconPath": "./static/index.png",
"pagePath": "pages/home/index"
}, {
"text": "书架",
"selectedIconPath": "./static/cart-active.png",
"iconPath": "./static/cart.png",
"pagePath": "pages/mybook/mybook"
}]
}
5、不支持状态管理
https://developers.weixin.qq.com/community/develop/doc/d4b0566fcd760a529181f2d4b009341c?_at=1558693595388
六、node
1.koa,egg
$ npm i egg-init -g$ egg-init egg-example --type=simple
$ cd egg-example
$ npm i
egg官网:https://eggjs.org/zh-cn/intro/quickstart.html
github源码
https://github.com/baweireact/m-app-1705E
以上是 项目实战【vue,react,微信小程序】(1705E) 的全部内容, 来源链接: utcz.com/z/376114.html