目录
一、bootstrap是什么?
bootstrap是一个基于HTML、CSS和Javascript语言编写的框架,具有简单、灵活的特性,拥有样式库、组件和插件,bootstrap常用来开发响应式布局和移动设备优先的Web项目,能够帮助开发者快速搭建前端页面。
1.下载安装
在官网下载对应的dist的安装包,在html中引用 bootstrap.css 和bootstrap.min.css。
2.bootstrap使用
2.1 原生表单验证
validity 每个表单元素(input select)的验证状态的对象
validity.valid 只有当表单元素通过校验,valid = true 否则为false
validity.patternMismatch 表单中正则表达式pattern不匹配 返回true
validity.rangeOverflow 表单中要求数值超出max不匹配 返回true
validity.rangeUnderflow 表单中要求数值低于min不匹配 返回true
validity.tooLong 表单中输入的内容超出了maxlength,返回为true
validity.tooShort 表单中输入的内容低于minlength,返回为true
validity.typeMismatch 与表单中输入要求type 不匹配,返回为true(type="email" 输入电话)
validity.valueMissing 如果表单中有required限制,但步步输入 返回为true
<form style="width: 300px;" onsubmit="return false">
<div class="mb-3">
<label class="form-label" for="stuName">学生姓名</label>
<input type="text" id="stuName" class="form-control" required minlength="2" maxlength="3" />
<label class="form-label" for="stuAge">学生年龄</label>
<input min="16" max="30" type="number" id="stuAge" class="form-control"/>
<label class="form-label" for="stuID">学生编号</label>
<input pattern="stu[0-9]{5}" type="text" id="stuID" class="form-control"/>
<input type="checkbox" id="accept" class="form-check-input" required/>
<label class="form-check-label" for="accept">同意用户协议和说明</label>
</div>
<div>
<button class="btn btn-primary w-100" type="submit">提交</button>
</div>
</form>
<script>
let form = document.querySelector('form')
let btn = document.querySelector('button')
let stuName = document.querySelector('#stuName')
let stuAge = document.querySelector('#stuAge')
let stuID = document.querySelector('#stuID')
let accept = document.querySelector('accept')
btn.addEventListener('click',()=>{
// 如果不输入必要内容
if(stuName.validity.valueMissing){
//setCustomValidity(string) 设置自定义的提示内容
stuName.setCustomValidity("请输入正确的姓名")
}else if(stuName.validity.tooShort){
stuName.setCustomValidity("姓名太短")
}else if(stuName.validity.tooLong){
stuName.setCustomValidity("姓名太长")
}
if(stuAge.validity.rangeOverflow){
stuAge.setCustomValidity("年龄太大")
}else if(stuAge.validity.rangeUnderflow){
stuAge.setCustomValidity("年龄太小")
}
// 验证通过的条件 针对元素的校验成功或者失败
// if(stuName.validity.valid
// && stuAge.validity.valid
// && stuID.validity.valid
// && accept.validity.valid){
// console.log('验证通过')
// }
//form.checkValidity() 整个表单校验通过就返回true 否则为false
if(!form.checkValidity()){
form.reportValidity()
}else{
console.log('验证通过')
}
})
// form.addEventListener('submit',()=>{
// })
</script>
2.2 bootstrap表单手动验证
form.addEventListener('submit',(ev)=>{
// 取消form的默认事件
ev.preventDefault()
// 取消from的submit事件的冒泡\捕获
ev.stopPropagation()
//表明这个表单校验过
//XXX-feedback
form.classList.add('was-validated')
})
<body>
<div class="container-fluid">
<form onsubmit="return false" style="width: 300px;" novalidate>
<div class="mb-3">
<label class="form-label" for="stuName">学生姓名</label>
<input type="text" id="stuName" class="form-control" required/>
<div class="invalid-feedback">
学生姓名为空
</div>
</div>
<div class="mb-3">
<button type="submit" class="btn btn-primary w-100">提交</button>
</div>
</form>
</div>
</body>
<script>
let form = document.querySelector('form')
let stuName = document.querySelector('#stuName')
form.addEventListener('submit',(ev)=>{
// 取消form的默认事件
ev.preventDefault()
// 取消from的submit事件的冒泡\捕获
ev.stopPropagation()
let stuNameVal = stuName.value
// 为空
if(stuNameVal === ''){
// 校验正确 is-valid valid-feedback
// 校验失败 is-invalid invalid-feedback
stuName.classList.remove('is-invalid','is-valid')
// is-invalid 直接显示后面的 invalid-feedback 中的内容
stuName.classList.add('is-invalid')
}
//表明这个表单校验过
//XXX-feedback
//防止重复添加
// if(!form.classList.contains('was-validated')){
form.classList.add('was-validated')
// }
})
</script>
二、react
1.react 概述
1.1 react定义
react是一个用于构建用户界面的JavaScript库。
1.2 特点
声明式:只需要描述UI(HTML)是什么样,React负责渲染UI,并在数据变化时更新UI
基于组件:组件时React`最重要`的内容、组件表示页面中的部分内容、组合、复用多个组件,可以实现完成的页面功能
2.react安装和使用
2.1安装
安装命令:npm i react react-dom
react 包是核心,提供创建元素、组件等功能
react-dom 包提供DOM相关功能等
2.2 使用
2.2.1引用
引入react和react-dom 两个js文件
<script src="./node_modules/react/umd/react.development.js"></script>
<script src="./node_modules/react-dom/umd/react-dom.development.js"></script>
2.2.2 创建和渲染react元素
方法说明:
React.createElement
参数1:元素名称
参数2:元素属性
参数3...:元素的子节点(文本、标记...)
ReactDOM.render
参数1:要渲染的React元素
参数2:DOM,渲染的挂载位置
<script>
const title = React.createElement('h1',null,'Hello React')
</script>
ReactDOM.render(title,document.getElementById('root'))
2.JSX
2.1 jsx概述
JSX是JavaScript XML的简写,表示在JavaScript代码中写XML ( HTML )格式的代码。
优势:声明式语法更加直观、与HTML 结构相同,降低了学习成本、提升开发效率
2.2jsx的使用
1、使用JSX语法创建react元素
const title = <h1>Hello JSX</h1>
2、使用ReactDOM.render() 方法渲染react元素到页面
ReactDOM.render(title,root)
为什么脚手架中可以使用JSX语法
-
JSX不是标准的ECMAScript语法,它是
ECMAScript的语法扩展
。 -
需要使用
babel
编译处理后,才能在浏览器环境中使用。 -
create-react-app脚手架中已经默认有该配置,无需手动配置。
-
编译JSX语法的包为: @babel/preset-react。
1、JSX中的元素的属性需要用驼峰法命名
2、class在JSX中为className for为htmlFor
3、没有子节点的React元素可以用`/>` 结束
4、推荐:使用`小括号包裹JSX`,从而避免JS中的自动插入分号陷阱
5、所有React组件名称均用驼峰法命名
代码如下(示例):
<script type="text/babel">
const InnerBox = (<div className="a"
style={{background:'red',fontSize:'30px'}}>
<h1>Hello World</h1>
</div>)
// InnerBox实际是一个jsx的对象(object)
console.log(InnerBox)
let root = document.querySelector('#root')
// ReactDOM.createRoot 创建出React页面根节点
// render 根节点渲染React对象
//JSX 是JS的预编译语言,需要通过babel处理成JavaScript
ReactDOM.createRoot(root).render(InnerBox)
</script>
2.3 JSX的条件渲染
条件渲染根据条件渲染特定的JSX结构、可以使用if/else
或三元运算符
或逻辑与运算符
来实现
2.4JSX的列表渲染
如果要渲染一组数据,应该使用数组的
map()
方法注意:渲染列表时应该添加key属性,
key属性的值要保证唯一
原则:
map()
遍历谁,就给谁添加key属性注意:
尽量避免使用索引号作为key
const students = [
{id:1,name:'张三'},
{id:2,name:'李四'},
{id:3,name:'王五'},
]
const list = {
<ul>
{students.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
}
2.5JSX的样式处理
1、行内样式-style
<h1 style={{color:'red',backgroundColor:'blue'}}> JSX行内样式 </h1>
2、类名-className(推荐)
需要引入css
import './css/index/css'
3.6 学习案例
1.代码:
<script type="text/babel">
function News() {
return (
news.map((item, index) => (
<div className="content">
<div class="img">
<img className="img" src={item.img == '' ? './1.jpg' : item.img} alt="" />
<div className="num">{index + 1}</div>
</div>
<div className="words">
<div className="title">{item.title}</div>
<div className="word">{item.content == '' ? '' : item.content}
</div>
<a href={item.link} >查看更多></a>
</div>
</div >
))
)
}
let root = document.querySelector('#root')
ReactDOM.createRoot(root).render(<News />)
2.运行结果
3.react组件
组件是React的一等公民
,使用React就是在用组件、组件表示React实现的部分功能、组合多个组件实现完整的页面功能
特点:可复用、独立、可组合
3.1 创建方式:
1.函数组件
-
函数组件:使用JS的函数(或箭头函数)创建的组件
-
注意:函数名称必须以
大写字母开头
-
注意: 函数组件必须有
返回值
,表示该组件的结构 -
注意:返回值为null,就不显示任何内容
function Hello(){
return (
<div>函数组件</div>
)
}
-
渲染函数组件:用函数名作为组件标签名,组件标签可以是单标签,也可以是双标签
2.类组件
-
类组件:使用ES6的class创建的组件
-
注意:类名称必须以
大写字母开头
-
注意:类组件应该继承
React.Component
父类,从而可以使用父类中提供的方法或者属性 -
注意:类组件必须提供
render()
方法 -
注意:render() 方法必须用
return返回值
,表示该组件的结构
class Hello extends React.Component{
render(){
return <div>Hello Class Component!</div>
}
}
ReactDOM.render(<Hello />,root)
3.2 React事件处理
1、事件绑定
-
eact事件绑定语法与DOM事件语法很相似
-
语法:
on+事件名称 = {事件处理程序}
,比如:onClick = {()=>{}} -
注意:
React事件采用驼峰法命名
, 比如:onMouseEnter,onFocus -
如果在函数组件中绑定事件,则调用事件函数不加this
class App extends React.Component {
handleClick(){
console.log('被点击了')
}
render(){
return (
<button onClick={this.handleClick()}></button>
)
}
}
-
可以通过
事件处理程序参数
获取到事件对象 -
React中的事件对象叫做:
合成事件
(对象) -
合成事件:兼容所有浏览器,无需担心跨浏览器兼容性问题
function handleClick(e){
e.preventDefault()
console.log('事件对象',e)
}
<a onClick={handleClick}>点击跳转</a>
3.3 有状态组件和无状态组件
-
函数组件又叫做
无状态组件
,类组件又叫做有状态组件
-
状态(state)即
数据
-
函数组件没有自己的状态,只负责
数据展示
(静态) -
类组件有自己的状态,
负责更新UI
(动态)
3.4 state的基本使用
-
状态(state)即数据,是组件内部的私有数据,只能在组件内部使用
-
state的值是对象
,表示一个组件中可以有多个数据 -
通过this.state 来获取状态
1、组件中的state和setState()
class Hello extends React.Component {
state = {
count:0
}
render(){
return (
<div>计数器:{this.state.count}</div>
<button onClick={()={
this.setState({
count:this.state.count + 1
})
}}>+1</button>
)
}
}
const [count,setCount] = React.useState(0)
const [number,setNumber] = React.useState(1)
3.5 受控组件的表单处理
-
HTML中的表单元素是可输入的,也就是有自己的可变状态
-
而React中可变状态通常保存在state中,并且只能通过setState() 方法来修改
-
React将state与表单元素值value绑定到一起,
由state的值来控制表单元素的值
-
受控组件:其值受到React控制的表单元素
受控组件设置步骤:
1、在state中添加一个状态,作为表单元素的value值(控制表单元素值的来源)
2、给表单元素绑定change事件,将表单元素的值,设置为state的值(受控表单元素值的变化)
state = {txt:''}
<input type="text" value={this.state.txt} onchange={e =>
this.setState({txt : e.target.value})} />
多表单元素优化步骤
1、给表单元素添加name属性,名称与state相同
<input type="text" \
name="txt"
value={this.state.txt}
onChange={this.handleForm}/>
2、根据表单元素类型获取对应值
const value = target.type === 'checkbox' ? target.checked : target.value
this.setState({
[name]:value
})
3.6 非受控组件的表单处理
1、调用React.createRef() 方法创建一个ref对象
constructor(){
super()
this.txtRef = React.createRef()
}
2、将创建好的ref对象添加到文本框中
<input type="text" ref={this.txtRef} />
3、通过ref对象获取到文本框的值
console.log(this.txtRef.current.value)
3.7 表单案例
1、要求:使用 react 制作如图所示的表格、能够点击删除按钮,删除一行数据、能够在右侧表单点击添加按钮,添加数据
2、代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="js/babel.js"></script>
<script src="js/react.development.js"></script>
<script src="js/react-dom.development.js"></script>
<link rel="stylesheet" href="css/bootstrap.css">
</head>
<body>
<div id="app"></div>
</body>
<script type="text/babel">
class App extends React.Component {
state = {
students: [
{
name: '张三',
sex: 'male',
age: 17
},
{
name: '李四',
sex: 'female',
age: 24
},
{
name: '老王',
sex: 'other',
age: 30
},
],
formData: {
name: '',
sex: 'other',
age: 0
}
}
remove(index) {
const result = confirm('确定删除吗?')
if (result) {
console.log(index)
this.state.students.splice(index, 1)
this.setState((state, props) => ({students: state.students}))
}
}
onSexChange(ev) {
this.state.formData.sex = ev.target.value
this.setState(state => ({formData: state.formData}))
}
submit(ev) {
ev.preventDefault()
ev.stopPropagation()
console.log(this.state.formData)
this.state.students.unshift({...this.state.formData})
this.setState(state => ({students: state.students}))
}
render() {
return (
<div>
<table className="table">
<thead>
<tr>
<th>姓名</th>
<th>性别</th>
<th>年龄</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{
this.state.students.map((stu, i) => (
<tr key={i}>
<td>{stu.name}</td>
<td>{stu.sex === 'male' ? <b style={{color: 'blue'}}>男</b> :
stu.sex === 'female' ? <u style={{color: 'red'}}>女</u> :
<i style={{color: 'yellow'}}>其他</i>
}
</td>
<td>{stu.age}</td>
<td>
<button className="btn btn-danger" onClick={this.remove.bind(this, i)}>删除
</button>
</td>
</tr>
))
}
</tbody>
</table>
<div className="card p-3" style={{width: '400px'}}>
<form>
<div className="row mb-3">
<label className="col-3 form-label">姓名</label>
<div className="col">
<input value={this.state.formData.name} onInput={ev => {
this.state.formData.name = ev.target.value
this.setState(state => ({formData: state.formData}))
}} name="name" type="text" className="form-control"/>
</div>
</div>
<div className="row mb-3">
<label className="col-3 form-label">性别</label>
<div className="col">
<div className="form-check-inline">
<input checked={this.state.formData.sex === 'male'}
onChange={this.onSexChange.bind(this)} name="sex" type="radio"
value="male" className="form-check-input"/>
<label className="form-check-label">男</label>
</div>
<div className="form-check-inline">
<input checked={this.state.formData.sex === 'female'}
onChange={this.onSexChange.bind(this)} name="sex" type="radio"
value="female" className="form-check-input"/>
<label className="form-check-label">女</label>
</div>
<div className="form-check-inline">
<input checked={this.state.formData.sex === 'other'}
onChange={this.onSexChange.bind(this)} name="sex" type="radio"
value="other" className="form-check-input"/>
<label className="form-check-label">其他</label>
</div>
</div>
</div>
<div className="row mb-3">
<label className="col-3 form-label">年龄</label>
<div className="col">
<input value={this.state.formData.age} onChange={ev => {
this.state.formData.age = ev.target.value
this.setState(state => ({formData: state.formData}))
}} name="age" type="number" className="form-control"/>
</div>
</div>
<div className="row">
<div className="col-3">
</div>
<div className="col">
<button className="btn btn-primary" onClick={this.submit.bind(this)}>提交</button>
</div>
</div>
</form>
</div>
</div>
)
}
}
// 渲染函数
ReactDOM.render(
<App></App>,
document.querySelector('#app')
)
</script>
</html>
3、运行结果:
3.8 组件通信
组件通信是独立且封闭的单元,默认情况下,只能使用组件自己的数据。在组件化过程中,我们将个完整的功能拆分成多个组件,以更好的完成整个应用的功能。而在这个过程中,多个组件之间不可避免的要共享某些数据。为了实现这些功能,就需要打破组件的独立封闭性,让其与外界沟通。这个过程就是组件通信。
1、组件的props
组件是封闭的,要接收外部数据应该通过props来实现
props的作用:接收传递给组件的数据
传递数据:给组件标签添加属性
接收数据:函数组件通过参数props接收数据,类组件通过this.props接收数据
2、父组件向子组件传递信息
1、父组件提供要传递的state数据
2、给子组件标签添加属性,值为state中的数据
3、子组件中通过props接收父组件中传递的数据
代码:
class App extends React.Component{
//state在类组件调用 this.state
//props在类组件调用 this.props
state = {
content:'父组件的内容'
}
render(){
return (
<div className="parent">
<Child1 data={this.state.content} />
<Child2 data={this.state.content} />
</div>
)
}
}
//类组件
class Child1 extends React.Component{
render(){
return (
<div className="child1">
<h3>{this.props.data}</h3>
</div>)
}
}
//函数组件
function Child2(props){
return (
<div className="child2">
<h3>{props.data}</h3>
</div>)
}
let root = document.querySelector('#root')
ReactDOM.createRoot(root).render(<App />)
3、子组件向父组件发送信息
1、在父组件中设置一个触发事件函数(形参)
2、在子组件标记中自定义属性,并传入上述的函数名称
3、在子组件中设置props传递过来的函数
3.9 组件生命周期
组件从被创建到挂载到页面中运行,再到组件不用时卸载的过程
1、钩子函数
定义:生命周期的每个阶段总是伴随着一些方法调用,这些方法就是生命周期的钩子函数
2、React 生命周期的阶段以及对应的钩子函数的执行过程 和 触发条件:
1、创建 constructor -> render -> componentDidMount 运行React程序
2、更新 render -> componentDidUpdate setState 新的props forceUpdate
3、卸载 componentWillDestory 该React组件被隐藏或者清除
总结
以上就是对高级特效学习的基础知识总结,简单介绍了bootstrap,react的基本用法和一些简单的案例。