Vue修改主题的方法

实现思路

(1)通过判定 icon 图标去实现黑白的判断
1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- 这是vue的伪代码 -->
<!-- 这是其他组件 -->
<template>
<div id="header">
<i :class="icon"></i>
</div>
</template>
<style lang="less" scoped>
#app {
/* 后续整体颜色都可以通过var(--themeColor)去实现 */
--themeColor: white;
}
</style>
阅读更多...

Vue的指令

分类

  • 内容渲染指令
  • 属性绑定指令
  • 事件绑定指令
  • 双向绑定指令
  • 条件渲染指令
  • 列表渲染指令

内容渲染指令

插值表达式:将需要的值插入进去就可以了,不会覆盖标签内的其余内容

1
<div id="app">用户名是:{{ username }}</div>
1
2
3
4
5
6
const vm = new Vue({
el:'#app',
data:{
username:'zhangsan'
}
})

v-text 可以把值插入到标签里,但是会覆盖标签内的其余内容

1
<div v-text="app">用户名是:{{ username }}</div>
1
2
3
4
5
6
const vm = new Vue({
el:'#app',
data:{
username:'zhangsan'
}
})

v-html 适用于渲染html的元素

1
<div id="app" v-html="info"></div>
1
2
3
4
5
6
const vm = new Vue({
el:'#app',
data:{
info:'<h4 style="color:red;font-weight:blod">我是zhangsan</h4>'
}
})

属性绑定指令

v-bind 可以简写为’:’

1
2
3
4
5
<div id="app">
<input type="text" :placeholder="tips">
<hr>
<div>{{ tips }}</div>
</div>
1
2
3
4
5
6
const vm = new Vue({
el:"#app",
data:{
tips:'我是张三'
}
})

事件绑定指令

v-on 可以简写为@

1
2
3
4
5
6
<div id="app">
<p>count的值是:{{ count }}</p>
<!-- add或者sub后面加上小括号就可以传值 -->
<button @click="add">+1</button>
<button @click="sub">-1<button>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const vm = new Vue({
el:"#app",
data:{
count:0
},
// 定义事件处理函数
methods:{
add(){
this.count +=1
},
sub(){
this.count -=1
}
}
})

双向绑定指令

v-model 只能和input,textarea,select一起使用

1
2
3
4
<div id="app">
<p>用户名是:{{ username }}</p>
<input type="text" v-model="username">
</div>
1
2
3
4
5
6
const vm = new Vue({
el:"#app",
data:{
username:'zhangsan'
}
})

条件渲染指令

v-if 如果不符合条件,会把该标签删除,之后符合条件就会复原.
v-show 如果不符合条件,会把标签的display改为none,否则就为block.控制display

1
2
3
4
5
6
7
8
9
10
<div id="app">
<!-- v-if是直接删除元素来隐藏元素 -->
<p v-if="flag">这是被v-if控制的元素</p>
<!-- v-show是控制display来隐藏元素的 -->
<p v-show="flag">这是被v-show控制的元素</p>
<hr>
<div v-if="type==='A'">优秀</div>
<div v-else-if="type==='B'">良好</div>
<div v-else-if="type==='C'">一般</div>
</div>
1
2
3
4
5
6
7
const vm = new Vue({
el:'#app',
data:{
flag: true,
type: 'A'
}
})

列表渲染指令

v-for 官方规定:使用v-for都必须有一个:key的属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<div id="#app">
<table>
<thead>
<th>索引</th>
<th>ID</th>
<th>名字</th>
<thead>
<tbody>
<tr v-for="(item,index) in li" :key="item.id" :title="item.name">
<td>{{ index }}</td>
<td>{{ item.id }}</td>
<td>{{ item.name }}</td>
</tr>
</tbody>
</table>
</div>
1
2
3
4
5
6
7
8
9
10
11
const vm = new Vue({
el:"#app",
data:{
li:[
{id:1,name:'zs'},
{id:2,name:'ls'},
{id:3,name:'ww'}
]
}
})

关于上篇文章登录注册接口中bug修复

BUG描述

1
2
Cannot set headers after they are sent to the client
翻译过来就是:发送到客户端后无法设置标头

发送这个bug的原因

原因:在上个博客中app.js中的res.cc和router_handler的user.js中的regUser模块的判定用户名是否被占用中的res.cc发生冲突,因为在执行完判定后,它自动去执行了加入数据库那堆代码中的res.cc(err),相当于执行了两次.客户端发送一次请求,服务器给出了两次反映

解决

思路:给判定用户名中再添加一个if语句来判定,如果没被占用就执行insert操作,如果被占用,就直接返回错误信息

  • 原代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    exports.regUser = (req,res)=>{
    const userinfo = req.body

    const sql = 'select * from ev_users where username=?'
    db.query(sql,userinfo.username,(err,results)=>{
    if(err) return res.cc(err)
    if(results.length>0) return res.cc('用户名已经被占用')
    // console.log(results.length),如果为1,说明已经有该用户,如果为0,说明没有该用户,可以用于注册
    })
    // 加密密码
    userinfo.password = bcyptjs.hashSync(userinfo.password,10)
    // 执行sql
    const sqlStr = 'insert into ev_users set ?'
    db.query(sqlStr,{username:userinfo.username,password:userinfo.password},(err,results)=>{
    if(err) return res.cc(err)
    if(results.affectedRows !== 1) return res.cc('注册用户失败',1)
    res.cc('注册成功',0)
    })
    }
  • 修改后的代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    exports.regUser = (req,res)=>{
    const userinfo = req.body

    const sql = 'select * from ev_users where username=?'
    db.query(sql,userinfo.username,(err,results)=>{
    if(err) return res.cc(err)
    if(results.length>0) return res.cc('用户名已经被占用')
    if(results.length != 1){
    // 加密密码
    userinfo.password = bcyptjs.hashSync(userinfo.password,10)
    // 执行sql
    const sqlStr = 'insert into ev_users set ?'
    db.query(sqlStr,{username:userinfo.username,password:userinfo.password},(err,results)=>{
    if(err) return res.cc(err)
    if(results.affectedRows !== 1) return res.cc('注册用户失败',1)
    res.send({
    status:0,
    msg:'注册成功',
    })
    })
    }
    // console.log(results.length),如果为1,说明已经有该用户,如果为0,说明没有该用户,可以用于注册
    })
    }

关于node.js书写登录注册接口

准备

包准备

  • @escook/express-joi(使用验证规则)
  • joi(验证规则)
  • bcryptjs(密码加密和解密)
  • cors(解决跨域问题)
  • express(配置本地服务器)
  • mysql(导入数据库)

文件夹准备

  • db(装mysql的配置文件)
  • router(路由转接)
  • app.js(总端)
  • router_hanler(路由转接后进行函数处理)
  • schema(进行规则验证)

代码

db

  • index.js
    1
    2
    3
    4
    5
    6
    7
    8
    9
    const mysql = require('mysql')
    const db = mysql.createPool({
    host:'127.0.0.1',
    user:'root',
    password:'123456',
    database:'my_db_01',
    })
    // 向外共享
    module.exports = db

router

  • user.js
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    const express= require('express')

    const router = express.Router()
    // 导入规则验证的中间件
    const expressJoi = require('@escook/express-joi')


    const userHandler = require('../router_handler/user')
    // 导入规则验证文件
    const {reg_login_schema} = require('../schema/user')

    router.post('/login',expressJoi(reg_login_schema),userHandler.loginUser)

    router.post('/reg',expressJoi(reg_login_schema),userHandler.regUser)

    module.exports = router

router_handler

  • user.js
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    const db = require('../db/index')
    const bcyptjs = require('bcryptjs')
    exports.loginUser = (req,res)=>{
    const userinfo = req.body
    const sql = 'select * from ev_users where username=?'
    db.query(sql,userinfo.username,(err,results)=>{
    if(err) return res.cc(err)
    if(results.length !== 1) return res.cc('登录失败',1)
    const compareResult = bcyptjs.compareSync(userinfo.password,results[0].password)
    if(!compareResult) return res.cc('登录失败:密码不正确',0)
    res.send({
    status:0,
    msg:'登录成功'
    })
    })
    }
    exports.regUser = (req,res)=>{
    const userinfo = req.body

    const sql = 'select * from ev_users where username=?'
    db.query(sql,userinfo.username,(err,results)=>{
    if(err) return res.cc(err)
    if(results.length>0) return res.cc('用户名已经被占用')
    // console.log(results.length),如果为1,说明已经有该用户,如果为0,说明没有该用户,可以用于注册
    })
    // 加密密码
    userinfo.password = bcyptjs.hashSync(userinfo.password,10)
    // 执行sql
    const sqlStr = 'insert into ev_users set ?'
    db.query(sqlStr,{username:userinfo.username,password:userinfo.password},(err,results)=>{
    if(err) return res.cc(err)
    if(results.affectedRows !== 1) return res.cc('注册用户失败',1)
    res.cc('注册成功',0)
    })
    }

app.js

  • app.js
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    const express = require('express')

    const app = express()

    const cors = require('cors')
    app.use(express.urlencoded({extended:false}))
    // 简化res.send({})的操作
    app.use((req,res,next)=>{
    res.cc = function(err,status=1){
    res.send({
    status,
    msg:err instanceof Error ? err.msg : err
    })
    }
    next()
    })
    app.use(cors())
    // 导入登录和登录的模块
    const userRouter = require('./router/user')
    app.use('/api',userRouter)
    app.listen(80,()=>{
    console.log('server running at http://127.0.0.1')
    })

schema

  • user.js
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    const joi = require('joi')

    const username = joi.string().alphanum().min(6).max(10).required()

    const password = joi.string().pattern(/^[\S]{6,12}$/).required()

    exports.reg_login_schema = {
    body:{
    username,
    password
    }
    }

Node.js的大事件项目(后续补坑)

记录

<!>大事件项目属于是Vue教程里的,所以选完Vue再回来继续补Node.js
<!>CSS和BOM的移动端操作还没有学,后续补坑

Node.js中大事件项目的补坑(更新事件:2022/7/29 16:35)

文件类别分为:router;rouer_handler;db;Schema;app.js

文件分类的解释

Node中运用Mysql语句进行增改删查

导入Mysql模块

首先安装mysql模块

1
$ npm i mysql

然后导入mysql模块

1
2
3
4
5
6
7
8
9
10
11
12
13
// 导入mysql模块
const mysql = require('mysql')
// 建立与mysql数据库的连接
const db = mysql.createPool({
// 数据库的IP地址
host:'127.0.0.1',
// 登录数据库的账号
user:'root',
// 登录数据库的密码
password:'123456',
// 指定要操作哪一个数据库
database:'my_db_01',
})

对数据进行四大项操作

1.查询数据

1
2
3
4
5
6
7
const sql = 'select * from users'
db.query(sql,(err,results)=>{
// err
if(err){return console.log('出现问题--->'+err.message)}
// 成功
console.log("------查询成功------\n"+results+"\n-------查询结束------")
})

2.插入数据

1
2
3
4
5
6
7
8
9
const user = {username:'Spider-man',password:'123456'}
// 如果数据过多 sqlStr = 'insert into users (username,password) set ?'
const sqlStr = 'insert into users (username,password) values(?,?)'
// db.query(sqlStr,user,(err,results)
db.query(sqlStr,[user.username,user.password],(err,results)=>{
if(err){return console.log('出现问题--->'+err.message)}
// 利用affectedRows来判断是否插入数据成功
if(results.affectedRows === 1){return console.log('------插入成功------\n'+results+'\n-------插入结束-------')}
})

3.更新数据

1
2
3
4
5
6
7
8
9
10
11
12
// 更新数据
const user = {id:1,username:'aaa',password:'000'}
// 简便方式:
// const sqlStr = 'update users set ? where id=?'
const sqlStr = 'update users set username=?,password=? where id=?'
// db.query(sqlStr,user,(err,results)=>{})
db.query(sqlStr,[user.username,user.password,user.id],(err,results)=>{
if(err){return console.log('出现问题--->\n'+err.message)}
if(results.affectedRows === 1){
console.log('更新成功')
}
})

4.删除数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 删除数据
const sqlStrOne = 'delete from users where id=?'
db.query(sqlStrOne,1,(err,results)=>{
if(err){return console.log('出现问题--->\n'+err.message)}
if(results.affectedRows === 1){
console.log('删除成功')
}
})
// 标记删除
const sqlStrTwo = 'update users set status=1 where id=?'
db.query(sqlStrTwo,3,(err,results)=>{
if(err){return console.log('出现问题--->\n'+err.message)}
if(results.affectedRows === 1){
console.log('标记删除成功')
}
})

SQL语句使用

SQL的Select语句

<!>大小写不敏感

1
2
3
4
5
# 从from指定的[表中],查询出所有数据, * 表示所有列
SELECT * FROM 表名称

# 从from指定的[表中],查询出指定的 列名称 的数据
SELECT 列名称 FROM 表名称

SQL的INSERT INTO 语句

<!>向数据表中插入新的数据行

1
2
3
4
5
6
7
8
9
10
INSERT INTO table_name(列1,列2......) values (值1,值2......)

# 例子:

# 1.修改单个数据
INSERT INTO users (username,password) values ('Toy','246810')

# 2.修改多个数据
update users set password = '123456',status = '1' where username = 'ls'

SQL的UPDATE语句

<!>修改表中的数据

1
2
3
4
5
6
UPDATE 表名称 SET 列名称 = 新值 WHERE 列名称 = 某值

# 例子:

update users set password = '123456' where username = 'ls'

SQL的DELETE语句

<!>删除表中的数据

1
2
3
4
DELETE FROM 表名称 WHERE 列名称 = 

# 例子:
DELETE FROM users WHERE id = '4'

SQL的ORDERBY语句

<!>排序
DESC:降序排序
默认:升序排序(ASC)

1
2
3
4
5
6
7
8
9
1.单个排序
# 升序
Select * from users ORDER BY status

# 降序
Select * from users ORDER BY status DESC

2.多重排序
Select * from users ORDER BY status desc, username asc

SQL的COUNT(*)函数

<!>查询数量

1
2
3
4
select count(*) from users where status = '0'

AS:给列起别名
select count(*) AS total from users where status = '0'

web开发模式

服务器端渲染

概念:服务器发送给客户端的HTML页面,是在服务器通过字符串的拼接,动态生成的,所以不需要Ajax来进行额外请求

1

前后端分离的开发模式

概念:依赖于Ajax技术,后端负责提供API接口,前端使用Ajax调用接口的开发模式
优点:1.开发体验好,前端专注于UI,后端专注于API;
2.用户体验好;
3.减轻了服务器端的压力.
缺点:1.不利于SEO(搜索引擎优化).

如何选择何种开发模式

1.功能主要是展示,没有复杂的交互,并且需要良好的SEO,就用服务器端渲染

2.类似于后台管理项目,交互性比较强,不需要考虑SEO,就用前后端分离的开发模式

3.混合开发:首屏服务器端渲染(兼顾首屏的渲染速度),分页是前后端分离的开发模式

身份认证

对于服务器端渲染—–推荐使用!<Session认证机制>

对于前后端分离—–推荐使用!<JWT认证机制>

Seesion

1.HTTP协议的无状态性

指的是:客户端的每次HTTP请求都是独立的,连续多个请求之间没有直接的关系,服务器不会主动保留每次HTTP请求的状态

2.Cookie(键值对)

指的是:存储在用户浏览器中的一段不超过4KB的字符串

特性:1.自动发送;
    2.域名独立;
    3.过期时限;
    4.4KB限制;

<!>Cookie很容易被伪造,不具有安全性

3.Session认证机制

设计理念类似于:会员卡+刷卡认证

Express路由

概念

在Express中,路由指的是客户端的请求与服务器处理函数之间的映射关系.
Express的路由分为三个部分:请求的类型,请求的URL地址,处理函数
格式如下:

路由匹配的注意点

1.按照定义的先后顺序进行匹配
2.请求类型和请求的URL同时匹配成功,才会调用对应的处理函数

挂在路由的方式

1.直接挂在到app上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    const express = require('express')
const app = express()

// 挂载路由
app.get('/',(req,res)=>{
res.send('hello world')
})


app.post('/',(res,req)=>{
res.send('post Request.')
})


app.listen(80,()=>{
console.log('http://127.0.0.1')
})

2.将路由抽离为单独的模块进行挂载
2.1步骤:
(1).创建路由模块对应的js文件
(2).调用express.Router()函数创建路由对象
(3).向路由对象上挂载具体的路由
(4).使用module.exports向外共享路由对象
(5).向app.use()函数注册路由模块

路由模块化.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let express = require('express')
let app = express()

// 导入路由模块
let router = require('./router')


// 注册路由模块
// 作用:注册全局中间件
// 挂载前缀
app.use('/api',router)

app.listen(80,()=>{
console.log('http://127.0.0.1')
})

router.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 路由模块
let express = require('express')

let router = express.Router()

// 挂载路由

router.get('/user/list',(req,res)=>{
res.send('Get User List.')
})

router.post('/user/add',(req,res)=>{
res.send('Add new User')
})

// 向外导出路由对象

module.exports = router

中间件

概念:业务中,中间处理的环节
格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
let express = require('express')
let app = express()

// 定义中间件函数
const mw = function(req,res,next){
console.log('这是一个简单的中间件函数')
// 把流转关系转交给下一个中间件或路由
next()
}

// 全局生效的中间件
app.use(mw)


app.get('/',(req,res)=>{
res.send('Home Page.')
})

app.get('/user',(req,res)=>{
res.send('User Page.')
})

app.listen(80,()=>{
console.log('http://127.0.0.1')
})

中间件函数的简化形式:

1
2
3
4
5
6
7
8
9
10
11
12
13
// // 定义中间件函数
// const mw = function(req,res,next){
// console.log('这是一个简单的中间件函数')
// // 把流转关系转交给下一个中间件或路由
// next()
// }

// // 全局生效的中间件
// app.use(mw)
app.use((res,req,next)=>{
console.log('这是简单的中间件函数')
next()
})

中间件的作用

1.多个中间件之间可以用共享同一份req,res:统一为req或res对象添加自定义的属性或方法
例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
let express = require('express')
let app = express()

app.use((res,req,next)=>{
// 获取请求到达服务器的时间
const time = Date.now()
// 为req挂载自定义属性,从而把time共享给后面的路由
req.startTime = time
next()
})

app.get('/',(req,res)=>{
res.send('Home Page.'+ req.startTime)
})

app.get('/user',(req,res)=>{
res.send('User Page.'+req.startTime)
})

app.listen(80,()=>{
console.log('http://127.0.0.1')
})

局部生效的中间件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const express = require('express')
const app = express()

// 定义中间件函数
const mw1 = (req,res,next)=>{
console.log('调用了局部生效的中间件')
next()
}

app.get('/',mw1,(req,res)=>{
res.send('Home page.')
})

app.get('/user',(req,res)=>{
res.send('User page.')
})

app.listen(80,()=>{
console.log('http://127.0.0.1')
})

同时使用多个局部中间件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const express = require('express')
const app = express()

// 定义中间件函数
const mw1 = (req,res,next)=>{
console.log('调用了第一个局部生效的中间件')
next()
}

const mw2 = (req,res,next)=>{
console.log('调用了第二个局部生效的中间件')
next()
}

app.get('/',mw1,mw2,(req,res)=>{
res.send('Home page.')
})

app.get('/user',[mw1,mw2],(req,res)=>{
res.send('User page.')
})

app.listen(80,()=>{
console.log('http://127.0.0.1')
})

中间件的分类

1.应用级别:绑定到app实例上的中间件
app.use();app.get()/app.post()

2.路由级别:绑定到Router上的中间
express.Router()

3.错误级别:必须注册在所有路由之后
处理函数 function(err,req,res,next){}

4.Express内置的中间件:
(1)express.static:快速托管静态资源
(2)express.json:解析json格式的请求体数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const express = require('express')
const app = express()

// 除了错误级别的中间件,其他中间件,必须在路由之前进行配置
app.use(express.json())

app.post('/user',(req,res)=>{
// 在服务器中,可以使用req.body可以收到客户端发来的请求体数据
console.log(req.body)
res.send('ok')
})

app.listen(80,()=>{
console.log('http://127.0.0.1')
})
(3)express.urlencoded:解析URL-encoded格式的请求体数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const express = require('express')
const app = express()

// 除了错误级别的中间件,其他中间件,必须在路由之前进行配置
// 解析表达那中url-encoded格式的数据
app.use(express.urlencoded())
// 在服务器中,可以使用req.body可以收到客户端发来的请求体数据

app.post('/book',(req,res)=>{
console.log(req.body)
res.send('ok')
})

app.listen(80,()=>{
console.log('http://127.0.0.1')
})

4.第三方中间件:
a.安装

1
npm install <body-parser>

b.使用require()导入中间件
1
const <body-parser> = require('<body-parser>')
c.调用app.use()注册并使用中间件
1
app.use(<body-parser>)

5.自定义中间件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 const express = require('express')
// 作用:解析请求体
const qs = require('querystring')
const app = express()

app.use((req,res,next)=>{
// 定义变量
let str = ''
// 监听req的data事件
req.on('data',(chunk)=>{
str += chunk
})
// 监听req的end事件
req.on('end',()=>{
// 在str中存放的是完整的请求体数据
const body = qs.parse(str)
console.log(body)
req.body = body
next()
})
})

app.post('/user',(req,res)=>{
res.send(req.body)
})

app.listen(80,()=>{
console.log('http://127.0.0.1')
})

  • Copyrights © 2022 BieGua
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信