1.基于rem单位的屏幕等比例缩放
const html = document.querySelector('html')
// 1. 我们定义 标准屏幕宽为 600px 标准字体大小为 20px;
// 2. 计算新的屏幕尺寸下的新的字体大小
let newFontSize = window.innerWidth / (600 / 20)
// 重新计算字体大小
function resize() {
let newFontSize = window.innerWidth / (600 / 20)
console.log(newFontSize);
// 设置html根节点的字体大小
html.style.fontSize = `${newFontSize}px`;
}
// 3. 绑定窗口尺寸变化事件和页面加载事件
window.addEventListener('resize', resize)
window.addEventListener('load', resize)
2.元素固定的宽高比等比例缩放
如何按比例设置元素的宽高
原理是:
一个父元素中的第一个子元素,其padding-top的百分比大小是参考的父元素的宽度
例如: padding-top: 25%,则子元素上侧内边距就是父元素宽度的25%
如此以来只要不设置父元素高度,则父元素的高度就是第一个子元素的高度,从而让父元素宽高成比例
具体操作步骤如下:
1. 创建一个等比例的比例盒,作为要填充元素的父元素使用
2. 创建不同比例尺的维元素例如: .box_3x4::before 并在其中使用 padding-top 来达成固定高宽比
3. 给所有 box 的子元素添加定位和宽高
4. 给 box 填入需要固定宽高比的子元素
<div class="box-container">
<div class="box box_3x4">
<img src="./img/big-img.png">
</div>
</div>
<script>
const html = document.querySelector('html')
function resize() {
let newFontSize = innerWidth / (600 / 16)
html.style.fontSize = `${newFontSize}px`
}
window.addEventListener('resize', resize)
window.addEventListener('load', resize)
</script>
3.预编译工具
预编译就是在编译环节发生之前,提前进行一次编译。其目的通常是将一个浏览器无法识别的语法提前编译成浏览器能够识别的语法。例如: css预编译 将 sass 转换为 css,js预编译 将 ts 转换成 js 等
文档:https://sass-lang.com/guide
[语法](#语法)
- [Variables 变量](#variables-变量)
- [Nesting 嵌套](#nesting-嵌套)
- [使用use引入其他的sass文件](#使用use引入其他的sass文件)
4.bootstrap
1.container布局
使用bootstrap的容器进行响应式布局的话,需要在head标签加上meta
<meta name="viewport" content="width=device-width, initial-scale=1.0">
运用类名来进行改变
class='container-sm' md lg xl xxl fluid
2.display显示方式
<!-- 当屏幕宽度小于 sm 时显示 -->
<div class="container d-block d-sm-none">小于 sm</div>
<!-- 当屏幕宽度为 md 时 显示 -->
<div class="container d-none d-sm-block d-md-none">md</div>
<!-- 当屏幕宽度大于 lg 时 显示 -->
<div class="container d-none d-md-block">大于 lg</div>
3.float \position\flex
float-start左浮 float-end右浮 clearfix 清除浮动
4.grid网格
利用行及列进行布局
row行
col 语法: col-{breakpoints}-{value}
例如: col-sm-3 col-lg-12
value: 范围在 1~12
bootstrap 中 一行 row 被等分为 12 分 那么col的value值代表的是占多少份
例如: col-3 此单元格占 12分之3份
<!-- 在 row 上可以使用flex 的 align-items 来进行竖直方向的排列 -->
class="row border border-3 align-items-center"
<!-- 在 row 上可以使用 flex 的 justify-content 来进行水平方向的排列 -->
class="row border border-3 justify-content-between"
<!-- offset 设置单元格左侧的偏移量 数字代表的含义和 col 相同 -->
class="col-3 offset-3"
<!-- 添加单元格间距使用 gutter 首字母为 g
可以使用 g-{value} 或 gx-{value} gy-{value}
g-{value} 水平和竖直间距
gx-{value} 水平间距
gy-{value} 竖直间距
-->
<!-- row-cols-{breakpoints}-{value} 让一行显示多少列 -->
class='row-cols-1'
5.color
背景色bg-value
文本色bg-value
文本+背景text-bg-value
value值{primary蓝色 secondary灰色 danger红色 warning黄色 info蓝色 light白色 dark黑色}
10.size /space/stack
元素大小=>w-25 50 75 100 auto
<div class="text-bg-primary w-25">25%</div>
内边距外边距
内边距使用p开头
外边距使用m开头
t b s e 分别代表上下左右
例如pt-2 ms-1
元素间的间距
vstack 竖直方向产生间距
hstack水平方向产生间距 hstack gap-1
6.text
对齐方式
text-end
换行及溢出
text-nowrap overflow-scroll
字体大小
fs-1
粗细及斜体
fw-bolder fst-italic
行高
1h-
文本装饰线
text-decoration-underline
text-decoration-line-through
7.form-contorl
label=>class='form-label'
input=>class='form-control'
设置大小 form-control-sm form-contorl-lg
禁用 直接添加disabeld
只读 直接添加readonly
朴素输入框
form-control-plaintext
想让label及表单元素左右排列可以使用网格的行及列进行布局
<div class="card p-3" style="width: 500px">
<div class="row">
<label class="col-3 col-form-label">姓名</label>
<div class="col">
<input class="form-control" type="text">
</div>
</div>
</div>
8.checksAndRadios
单选按钮
<div class="form-check">
<input class="form-check-input" id="male" type="radio" name="sex" value="male">
<label class="form-check-label" for="male">男</label>
</div>
<!-- form-check-inline 让选项排列在一行之中 -->
不确定的checkbox需要给输入框添加indeterminate属性,但是该属性只能用js添加
<input indeterminate id="indeterminate" class="form-check-input" type="checkbox">
<script>
let inp = document.querySelector('#indeterminate')
// indeterminate 属性是一个 bool 值
inp.indeterminate = true
</script>
类似按钮的多选或单选按钮
<!-- input 中添加 btn-check -->
<input id="a" class="btn-check" type="radio" value="a" name="btn">
<!-- label 中添加 btn btn-outline-{color} -->
<!-- 注意: 为了能够勾选成功 必须给label添加for 给 input 添加id -->
<label for="a" class="btn btn-outline-warning">a</label>
<!-- form-switch 是开关 只要给普通的 checkbox 添加该类名即可 -->
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox">
<label class="form-check-label">某某协议</label>
</div>
910.select
<select class="form-select">
<option value="" disabled selected>请选择</option>
<option value="1">一班</option>
<option value="2">二班</option>
<option value="3">三班</option>
</select>
写法二
<label class="form-label">班级</label>
<!-- 输入框用 list 属性关联 datalist -->
<input list="clazz" type="text" class="form-control">
<!-- 通过datalist 给输入框添加待选项 -->
<datalist id="clazz">
<option value="1">一班</option>
<option value="2">二班</option>
<option value="3">三班</option>
</datalist>
10.原生表单验证
1. 给表单添加 novalidate 屏蔽自动验证报告
2. 对每个元素的 validity 属性进行验证
3. 根据每个元素的验证结果设置自定义异常 setCustomValidity
4. 提交验证报告
5. 根据验证结果执行后续网络操作
<!-- novalidate 屏蔽默认的表单提交时的验证报告
屏蔽掉自动的验证报告的目的 是为了我们自己好去控制验证报告
-->
<!-- required 必填 -->
<!-- <input name="name" required type="text" class="form-control"> -->
<!-- pattern 正则表达式 -->
<!-- <input name="name" pattern="[\s\S]*张三[\s\S]*" type="text" class="form-control"> -->
<!-- minlength 最小长度 maxlength 最大长度 -->
<!-- <input name="name" minlength="2" maxlength="10" type="text" class="form-control"> -->
<!-- min 最小值 max 最大值 -->
<input name="name" min="0" max="200" type="number" class="form-control">
<!-- type 类型验证 -->
<!-- <input type="email" class="form-control"> -->
// 可以通过输入框的 validity 属性 来判断用户是否输入正确
// validity.valueMissing -> required 用户没填数据时为 true
// validity.patternMismatch -> pattern 用户输入不满足正则 true
// validity.rangeOverflow -> max 用户输入超过最大值 true
// validity.rangeUnderflow -> min 用户输入小于最小值 true
// validity.tooLong -> maxlength 用户输入超出长度 不会触发 true
// validity.tooShort -> minlength 用户输入小于了指定长度 true
// validity.valid -> 输入没有问题 验证通过 true
// 总结表单验证
btn2.addEventListener('click', () => {
// 2. 验证所有表单项
if (nameInp2.validity.valueMissing) {
// 3. 设置错误信息
nameInp2.setCustomValidity('请输入姓名')
} else if (nameInp2.validity.tooShort) {
nameInp2.setCustomValidity('请输入至少2个字的姓名')
} else {
nameInp2.setCustomValidity('')
}
if (ageInp.validity.valueMissing) {
ageInp.setCustomValidity('请输入年龄')
} else if (ageInp.validity.rangeOverflow) {
ageInp.setCustomValidity('请输入不超过150的年龄')
} else if (ageInp.validity.rangeUnderflow) {
ageInp.setCustomValidity('请输入不低于0的年龄')
} else {
ageInp.setCustomValidity('')
}
if (!form2.checkValidity()) {
// 4. 发起验证报告
form2.reportValidity()
} else {
// 5. 验证通过 执行后续逻辑
console.log('验证通过');
}
})
11.bootstrap自动验证
<!-- 给form添加类名 was-validated 就可以开启验证效果 -->
<input required type="text" class="form-control">
<!-- 验证的提示需要写在被验证的输入框下面 -->
<!-- valid-feedback 验证通过的提示文本 -->
<div class="valid-feedback"> ok </div>
btn.addEventListener('click', () => {
form.classList.add('was-validated')
})
12.bootstrap手动验证
在自行验证后 可以通过添加 is-valid is-invalid 手动指定输入框的验证结果
<div class="row">
<label class="col-3 col-form-label">年龄</label>
<div class="col">
<input name="age" type="number" class="form-control">
<div class="valid-feedback">ok</div>
<div class="invalid-feedback">error</div>
</div>
</div>
let nameInp = document.querySelector('input[name=name]')
let ageInp = document.querySelector('input[name=age]')
// 查询错误提示的元素
let nameErrTip = document.querySelector('input[name=name]~.invalid-feedback')
let ageErrTip = document.querySelector('input[name=age]~.invalid-feedback')
let btn = document.querySelector('button')
btn.addEventListener('click', () => {
// 手动通过代码进行验证
// 清空所有的 is-valid 和 is-invalid
nameInp.classList.remove('is-valid', 'is-invalid')
ageInp.classList.remove('is-valid', 'is-invalid')
// 定义一个代表验证通过的变量
let nameValid = true
if (nameInp.value.trim() === '') {
nameErrTip.textContent = '请输入姓名'
nameValid = false
} else if (nameInp.value.trim().length < 2 || nameInp.value.trim().length > 10) {
nameErrTip.textContent = '请输入2~10个字的姓名'
nameValid = false
}
let ageValid = true
if (Number(ageInp.value) < 0 || Number(ageInp.value) > 150) {
ageErrTip.textContent = '请输入0~150之间的年龄'
ageValid = false
}
nameInp.classList.add(nameValid ? 'is-valid' : 'is-invalid')
ageInp.classList.add(ageValid ? 'is-valid' : 'is-invalid')
if (nameValid && ageValid) {
// 整个表单输入正确的情况
// 可以执行后续的网络请求
console.log('验证通过');
}
})
5.react
条件渲染
在render内进行
使用&&进行短路运算前一个表达式为true时 就显示后面的内容
{sex === 'male' && <div style={{color: '#00f'}}>男</div>}
使用三元运算符 按不同条件显示不同的内容
{sex === 'male' ? <div style={{color: '#00f'}}>男</div> :
sex === 'female' ? <div style={{color: 'pink'}}>女</div> :
<div style={{color: '#ff0'}}>其他</div>
}
循环渲染
循环渲染,使用一个数组的map函数,返回一个由 react-dom 充当成员形成的一个新数组
{/* 循环渲染,使用一个数组的map函数 返回一个由 react-dom 充当成员形成的一个新数组 */}
{students.map(item => <li>姓名: {item.name}; 性别: {item.sex === 'male' ? '男' :
item.sex === 'female' ? '女' : '不详'
}; 年龄: {item.age}</li>)}
受控组件
什么是受控组件?
// 被 react 的 state 控制显示和输入的表单元素称为受控组件
// 受控组件的数据来自 state 而不是表单元素自身
// react 中 所有的事件都不能通过 return false 来屏蔽默认事件
// 声明 input[type=text] 、select 和 textarea 的受控组件
// 声明 input[type=radio] input[type=checkbox] 的受控组件
状态提升
function Child(props) {
const [count, setCount] = React.useState(0);
function increase() {
setCount(_c => _c + 1)
}
// 监视 count 的变化
React.useEffect(() => {
// count 发生变化
// 通知父组件
// 将状态值作为参数传入
props.countChange(count)
}, [count])
return (
<div>
<div>count: {count}</div>
<div>
<button onClick={increase}>+</button>
</div>
</div>
)
}
function App() {
// 此函数的参数用于接收子组件状态
function onCountChange(args) {
console.log(args)
}
return (
<div>
{/* 给子组件分配一个函数 用于接收组件状态 */}
<Child countChange={onCountChange}></Child>
</div>
)
}
ReactDOM.createRoot(document.querySelector('#root')).render(<App/>)
组件通信
通信方法:
// 1. 父组件将自身 state 作为参数传入子组件 props
// 2. 子组件依赖 props 显示内容
// 3. 子组件内希望修改 props 中的值,则发出一个事件
// 4. 父组件绑定子组件发出的事件并接收参数
// 5. 父组件接收事件后更新自身 state,此时 react 会自动更新子组件 props
创建组件
函数组件及类组件
// 函数组件必须返回一个react-dom对象
// 可以在组件内声明其他函数和变量
状态
// 声明状态
// 组件的状态更新 this.setState 的使用
// 1. 不要直接修改 state 要通过 setState 修改
// 2. setState 的参数不要直接依赖 this.state 或 this.props;应使用 this.setState((state, props)=>{return {}}) 代替
// 3. setState 方法是异步的 可以通过 setState 的第二个回调函数 来执行赋值成功后的代码
// 4. setState 最终会修改 this.state
class组件的状态
// 在构造函数中使用 this.state 来声明状态
this.state = {
count: 0
}
函数组件状态
// 0 号成员是 状态的 getter 用来读取状态
// 1 号成员是 状态的 setter 用来赋值状态
const [obj, setObj] = React.useState({name: '张三'})
事件处理
{/* 使用箭头函数在调用事件处理程序的时候传递参数 */}
{/* react 无法直接通过 return false 屏蔽默认事件 */}
class组件绑定事件
// 类组件中事件处理程序如何赋值this关键字
// 1. constructor 中使用 bind
// 2. 在绑定事件插值时使用箭头函数
// 3. 在绑定事件插值时使用bind
{/*<button onClick={this.clickHandler}>点击</button>*/}
{/* 2. 在绑定事件插值时使用箭头函数 */}
{/*<button onClick={ev => {
this.clickHandler(ev)
}}>点击</button>*/}
{/* 3. 在绑定事件插值时使用bind */}