哈喽哈喽,这里是小菜不拖延博主,本篇文章主要是记录博主的一些开发过程当中,经常用到的技能,但是博主又老是忘记,所以记录下来方便下一次直接使用,希望能帮助到你
一.通用
WangEditor
上传:
HTMLEncode(html) {
var temp = document.createElement("div");
(temp.textContent != null) ? (temp.textContent = html) : (temp.innerText = html);
var output = temp.innerHTML;
temp = null;
return output;
},
回显:解码
escape2Html(str) {
var arrEntities={'lt':'<','gt':'>','nbsp':' ','amp':'&','quot':'"'};
return str.replace(
/&(lt|gt|nbsp|amp|quot);/ig,
function(all,t) {
return arrEntities[t];
}
);
},
利用此解码的返回数据格式
1滚动属性
ScrollHeight
表示元素内容的总高度,包括在不可见区域内的部分
ScrollTop
是一个可读写属性,表示元素垂直方向上已经滚动的像素数。具体来说,对于一个具有垂直滚动条的元素,比如设置了 overflow-y: scroll; 的元素,scrollTop 属性将返回滚动条相对于顶部的偏移量.所以,注意含义,是一个可以滚动的盒子,滚动的偏移量,而不是自己的偏移量
2. 背景图位置设置
2.1保持宽高比占满盒子
.box {
position: relative; /* 确保盒子以其自身为参考点 */
width: 100%; /* 设置盒子的宽度 */
height: 0; /* 设置盒子的高度为0,之后会通过 padding 来撑开 */
padding-top: 75%; /* 设置一个 padding 值来撑开盒子的高度,比如这里的值是可根据需要调整的,表示宽高比为 4:3 */
background-image: url('your-image-url'); /* 设置背景图的路径 */
background-position: center center; /* 将背景图位置设置为盒子的中心 */
background-repeat: no-repeat; /* 禁止背景图重复显示 */
background-size: cover; /* 缩放背景图以填充整个盒子 会自动调整背景图片的大小,以确保背景图片完全覆盖容器*/
//background-size: auto 100%;以高度为主占满盒子
//background-size: contain;/*让图片缩放占满盒子以确保整个背景图片都能完整显示在容器内,不会被裁剪。*/
}
2. Vue
3.React
react启动
npm i -g create-react-app
create-react-app 项目名
npm/yarn start
监听键盘事件
onKeyUp
代表键盘事件完成后触发
event.keyCode---代表键盘每个键的标识,可以用这个判断回车提交
字符串处理
trim-去除空白字符
trim()是一个字符串方法,用于去除字符串两端的空白字符(包括空格、制表符、换行符等)并返回新的字符串。这个方法不会改变原始字符串本身,而是返回一个修剪后的版本。
例如:
let str = " Hello, World! ";
console.log(str.trim());
// 输出: "Hello, World!"
这个方法广泛利用于输入框判断是否为空
数组处理
map
可用于遍历数组
const {todos}=this.state
// 遍历找到制定项
const newTodos=todos.map((todoObj)=>{
if(todoObj.id ===id) return {...todoObj,done}
else{
return todoObj
}
})
reduce
它用于对数组进行迭代和累积操作。它接受一个回调函数作为参数,并且可以选择接受一个初始值。
array.reduce(callback[, initialValue]);
callback:回调函数,它接受四个参数:accumulator(累加器):累积器累计回调的返回值。它在每次执行回调时更新。currentValue(当前值):数组中当前正在处理的元素。currentIndex(当前索引):数组中当前正在处理的元素的索引。array(源数组):调用reduce()方法的数组。
initialValue(初始值,可选):作为第一次调用回调函数时的第一个参数的值。如果没有提供初始值,则使用数组的第一个元素作为初始值,并从第二个元素开始迭代。
const donecount=todos.reduce((pre,todo)=>{
return pre+(todo.done?1:0)
},0)
filter
可用于过滤数组,比如我想删除某个元素
todos.filter((todoObj)=>{
return todoObj.id!==id
})
window操作
window.confirm--弹窗确定取消
if(window.confirm('确定删除吗')){
this.props.deleteTodo(id);
}
input
当属性为checkbox时
+ defaultChecked:只能触发一次,也就是最开始页面加载的时候
+ checked:使用checked会写死他的值,让他不能改变,所以我们必须添加onchange事件
node请求
const express = require('express')
const app = express()
app.use((request,response,next)=>{
console.log('有人请求服务器1了');
console.log('请求来自于',request.get('Host'));
console.log('请求的地址',request.url);
next()
})
app.get('/students',(request,response)=>{
const students = [
{id:'001',name:'tom',age:18},
{id:'002',name:'jerry',age:19},
{id:'003',name:'tony',age:120},
]
response.send(students)
})
app.listen(5000,(err)=>{
if(!err) console.log('服务器1启动成功了,请求学生信息地址为:http://localhost:5000/students');
})
react配置代理
大概的逻辑是,配置了之后,他现在3000的public找,找不到再去配置的端口找
若配置一个代理,在package.json中,更改配置之后,重启运行
"proxy":"http://localhost:5000()"
//我站在3000给5000发,会跨域,所以我配置一下,让我请求发3000能到5000,所以这里请求需要改成程序运行的地址,由于我们配置了proxy,所以会转发到5000,从而解决跨域
若配置多个代理,需要在src目录下创建setupProxy.js文件
它实际上不是给前端代码执行,他是找到这个文件,加到webpack里面,而webpack里面是node里面的语法,所以我们这个文件写的是commonjs的语法
const {createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function (app) {
app.use(
createProxyMiddleware ('/api1', {
target: 'http://localhost:5000',//转发地址
changeOrigin: true,//控制服务器收到的请求头中host字段的值,true的时候请求时服务器打印是前端请求的地址,false的时候就是请求的服务器地址,加不加没什么太大影响,但是最好还是加上
pathRewrite: {'^/api1': ''}
}),
createProxyMiddleware ('/api2', {
target: 'http://localhost:5001',
changeOrigin: true,
pathRewrite: {'^/api2': ''}
})
)
};
React点击按钮但是获取输入框的内容
import React, { Component } from 'react'
export default class Search extends Component {
search=()=>{
const {value}=this.keyWord
console.log('value',value);
}
render() {
return (
<div>
<section className="jumbotron">
<h3 className="jumbotron-heading">Search Github Users</h3>
<div>
//重点在这里
//这里的含义是将该节点放在this的某个属性上(这个属性是自己取的)
<input ref={c =>this.keyWord=c} type="text" placeholder="enter the name you search"/>
<button onClick={this.search}>Search</button>
</div>
</section>
</div>
)
}
}
解构赋值
简单来说就是省略掉一直......,更快编码
-
若只有一层解构
const {}=xxx -
若不止一层,以下形式可以实现连续解构,注意!!!!这样就拿不到aaa,只能拿到最里面的数据了
const {aaa:{xxx}}=xxx -
赋值重命名,以下是将b改成data
const {a:{b:data}}=this
React订阅与发布
库:pubsub-js
PubSub.publish('atguigu',{name:'tom',age:11})
this.xxx=PubSub.subscribe('atguigu',(_,data)=>{
console.log('listdata',data);
})
//取消订阅
PubSub.unsubscribe(this.xxx)
fetch
axios与jquery都属于xmlHttpReaquest,而fetch与xhr一样都可以发送网络请求
// 发送GET请求
fetch('https://api.example.com/data')
.then(response => {
// 检查响应状态码
if (response.ok) {
// 读取响应数据
return response.json();
} else {
throw new Error('请求失败');
}
})
.then(data => {
// 处理响应数据
console.log(data);
})
.catch(error => {
// 处理错误
console.error(error);
});
React 路由
history
//跳转路由
history.push()
//替换当前屏幕为指定屏幕
//可避免用户通过返回按钮返回到登录屏幕
history.replace()
//回到上一页面
history.goback()
路由切换组件
路由组件一般放在pages,普通组件放在components
<Home/> //普通组件
<Route path="/home" componennts={Home}/> //路由组件
注意版本问题,@5版本上写法:
安装控制版本:yarn add react-router-dom@5
使用,最外层需要包裹BrowserRouter/HashRouter,所以我们直接在app最外层包裹(index.jx文件)
router是路由器,route是路由
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
);
import React, { Component } from 'react';
import {Link,Route} from 'react-router-dom'
import Home from "./componennts/home/home"
import About from "./componennts/about/about"
class App extends Component {
render() {
return (
<div>
<div className="row">
<div className="col-xs-offset-2 col-xs-8">
<div className="page-header"><h2>React Router Demo</h2></div>
</div>
</div>
<div className="row">
<div className="col-xs-2 col-xs-offset-2">
<div className="list-group">
//需要包裹BrowserRouter
<Link className='list-group-item' to='/about'>About</Link>
<Link className='list-group-item' to='/home'>Home</Link>
</div>
</div>
<div className="col-xs-6">
<div className="panel">
<div className="panel-body">
{/* <Home/>
<About/> */}
//需要包裹BrowserRouter
<Route path='/about' component={About} />
<Route path='/home' component={Home} />
</div>
</div>
</div>
</div>
</div>
);
}
}
export default App;
BrowserRouter与HashRouter
#号后面部分认为是前台资源是不会带给服务器的
- URL格式: BrowserRouter使用HTML5的history API来管理URL,它使用真实的URL路径,不带有哈希符号(#)。而HashRouter则使用URL的哈希部分(#)来管理路由,将路由信息保存在URL的哈希中。
- BrowserRouter示例URL:
https://example.com/about - HashRouter示例URL:
https://example.com/#/about
- BrowserRouter示例URL:
- 服务器配置: 当使用BrowserRouter时,需要服务器端的配置支持,以便正确处理在应用程序中定义的URL路径。服务器需要返回应用程序的主页,然后由React Router接管并处理路由。而HashRouter不需要特殊的服务器配置,因为所有路由信息都包含在URL的哈希部分中,服务器只需返回一个主页即可。
- 兼容性: 由于HashRouter使用的是URL的哈希部分,所以对于不支持HTML5 history API的旧版本浏览器,HashRouter是一个较好的选择。而BrowserRouter对于大多数现代浏览器来说是更自然的选择,并且可以使用更简洁的URL
NavLink
就是点谁给谁追加一个active类,所以他会高亮啥的
activeClassName='xxx'
//这样就规定了active的时候的样式名,通过这个样式名字就可以改变active时候的样式
路由匹配
路由匹配都是从最开始注册到最后进行匹配,意思就是,我在某个组件里面写了路由,那么他会从最开的是app里面的路由进行匹配,路由匹配是有顺序的
比如我在/home下想跳转/news,那我的意思就是/home/news的形式,但是我如果我写成:
<Link to '/news' ``````>这样,他会直接那这/news这个去匹配所有的路由,如果我们app里面写的是/home,就导致无法匹配,直接到了redirect里面的路由位置,所以必须带上前面的路径
react路由匹配,他匹配path成功之后,还会继续往下匹配直到最后,所以我们需要引入switch(但是感觉好像么啥用,反正我们写都是一个路径)
<Switch>
<Route />
</Switch>
路由模糊匹配
//路由链接写多了,可以匹配下面的route
<Link to='/home/a/b'>Home</Link>
<Route path='/home' component={Home} />
//但是路由链接写少了不行
<Link to='/home'>Home</Link>
<Route path='/home/a/b' component={Home} />
//开启严格匹配
**exact**
<Route exact={true} path='/home/a/b' component={Home} />
//注意不要滥用严格匹配,最开始不要写,就只有页面混乱,都往一个地方跳了,我们再写该属性,否则会引发严重的问题
Redirect
//若路由跟谁都匹配不上那就去redirect的组件地址
<Redirect to='/about'>
Redux
安装:npm i redux
//拿到store的值
store.getState()
//调用通知redux
store.dispatch({type:'',data:})
//监听状态
store.subscribe(()=>{
//执行操作
this.setState({})
})
使用
-
src下建立:
-redux
-store.js
// 该文件专门用于暴露一个store对象 import {createStore} from "redux" import countReducer from "./count_reducer" const store =createStore(countReducer) export default store -xxx-reducer.js
//该文件是用于创建一个为count组件服务的reducer,本质是一个函数 // 有两个参数,之前状态prestate,动作对象action //reducer第一次被调用,store.js是自动触发的,传递的preState是undefined const initState=0 // 给一个初始化值,pre为undefined的话,那么就会等于initState export default function countReducer(preState=initState,action){ const {type,data}=action switch(type){ case 'increment': return preState+data case 'decrement': return preState-data; default: return preState; } }
-xxx_action.js
```react
// 该文件专门为count组件生成action对象
// function createIncrementAction(data){
// return {type:'increment',data}
// }
// function createDncrementAction(data){
// return {type:'decrement',data}
// }
import { INCREMENT,DECREMENT } from "./constant"
export const createIncrementAction = data=>({type:INCREMENT,data})
export const createDecrementAction = data=>({type:DECREMENT,data})
```
--constant.js
// 该模块是用于Dion工艺action对象中type类型的常量值
// 这样写的好处是变量写错会直接报错,就不用自己慢慢找了
export const INCREMENT ='increment'
export const DECREMENT ='decrement'
redux只负责管理状态,至于驱动页面改变,需要自己写
//这只是一个例子,我们也可以一劳永逸,直接放到index.js里面
componentDidMount(){
//检测redux中的状态变化,只要有变化就调用render,进行及时的页面更新
store.subscribe(()=>{
this.setState({})//什么也没改帮我调render
})
}
(index.js)
import store from "./redux/store"
const root = ReactDOM.createRoot(document.getElementById('root'));
store.subscribe(()=>{
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
})
constant.js
// 该模块是用于Dion工艺action对象中type类型的常量值
// 这样写的好处是变量写错会直接报错,就不用自己慢慢找了
export const INCREMENT ='increment'
export const DECREMENT ='decrement'
redux-devtools-extension使用
安装之后,在总的store当中进行配置
汇总所有的store
//引入createStore,专门用于创建store对象
import {createStore,applyMiddleware,combineReducers} from 'redux'
//引入为count组件复位的reducer
import countReducer from "./reducers/count"
//引入reduce-thunk,用于支持异步action
import thunk from 'reduc-thunk'
//汇总所有的reducer比那为一个总的reducer
const allReducer=combineReducers({
//自己命名的he,rens
he:countReducer,
rens:personReducer
})
export default createStore(allReducer,composeWithDevTools(applyMiddleware(thunk)))
React -setState
注意setState是异步的
对象式
对象式是函数式的语法糖
import React, { Component } from 'react';
class Demo extends Component {
state={count:0}
add =() =>{
const {count}=this.state
this.setState({count:count+1})
//这里打印出来不是最新值
console.log('count',count);
}
render() {
return (
<div>
<h1>当前和{this.state.count}</h1>
<button onClick={this.add}>add1</button>
</div>
);
}
}
export default Demo;
所以如果我们想获取最新的值,我们需要回调函数
this.setState({count:count+1},()=>{
//相关操作
})
函数式
好处是能直接收到state和props,就不用自己还要const获取
//函数式
this.setState((state,props)=>{
console.log(state,props);
return {count:state.count+1}
})
react-layLoad
用的时候再加载组件
//引入suspense是为了解决,点击组件加载等很久出现白屏体验不好的问题
import {lazy,Suspense} from "react"
const Home =lazy(()=>{import('./home')})
//在注册路由的位置将其包裹起来
<Suspense fallback={<h1>loading</h1>}>//这样正在加载就可以显示加载中
<Route path='/about' component={About}/>
</Suspense>
react-hooks
useState
import React, { Component } from 'react'
export default function Demo(){
//这一行代码react做了处理,所以使得我们用了就可以更新状态了
const [count,setCount]=React.useState(0)
function add(){
//第一种写法
setCount(count+1)
//第二
setCount(count=>count+1)
}
return(
<div>
<h1>count:{count}</h1>
<button onClick={add}>addd</button>
</div>
)
}
useEffect
React.useEffect(()=>{
},参数)
//参数不写,就默认全部检测,当状态改变的时候,就会调用,当传入一个空数组([])就表示谁都不监测,[count]就是监测count
//页面加载完成会触发一次,有点像componenntDidMount
React-Ref
import React, { Component } from 'react'
export default function Demo(){
//用法
const myRef=React.useRef()
function show(){
alert(myRef.current.value)
}
return(
<div>
<input type='text' ref={myRef}></input>
<button onClick={show}>show</button>
</div>
)
}
React-Fragment
Fragment 是一种特殊的组件,用于包裹多个子元素而不需要创建额外的 DOM 节点。
import React, { Component,Fragment } from 'react';
class Demo extends Component {
render() {
return (
//只能接受一个参数为key
<Fragment ket={1}>
<input type="text" />
<input type="text" />
</Fragment>
//空标签和fragment作用一样,但是不能接受任何一个参数
<>
</>
);
}
}
export default Demo;
react-context
适用于祖组件与后代之间的通信
1) 创建Context容器对象:
const XxxContext = React.createContext()
2) 渲染子组时,外面包裹xxxContext.Provider, 通过value属性给后代组件传递数据:
<xxxContext.Provider value={数据}>
子组件
</xxxContext.Provider>
3) 后代组件读取数据:
//第一种方式:仅适用于类组件
static contextType = xxxContext // 声明接收context
this.context // 读取context中的value数据
//第二种方式: 函数组件与类组件都可以
<xxxContext.Consumer>
{
value => ( // value就是context中的value数据
要显示的内容
)
}
</xxxContext.Consumer>
第一种
import React, { Component } from 'react';
import "./index.css"
// 创建context对象
const MyContext=React.createContext()
const {Provider}=MyContext
class A extends Component {
state={name:'tom'}
render() {
const {name}=this.state
return (
<div className='parent'>
<h1>a</h1>
<h3>我的name:{this.state.name}</h3>
{/* <B username={this.state.name}/> */}
//包裹
<Provider value={name}>
<B/>
</Provider>
</div>
);
}
}
export default A;
class B extends Component{
render(){
return(
<div className='child'>
<h1>bbbbb</h1>
<h3>name:{this.props.username}</h3>
<C/>
</div>
)
}
}
class C extends Component{
//这里要声明
static contextType=MyContext
render(){
return(
<div className='grand'>
<h1>ccccc</h1>
//这里才能接受
<h3>name:{this.context}</h3>
</div>
)
}
}
第二种
import React, { Component } from 'react';
import "./index.css"
// 创建context对象
const MyContext=React.createContext()
const {Provider,Consumer}=MyContext
class A extends Component {
state={name:'tom'}
render() {
const {name}=this.state
return (
<div className='parent'>
<h1>a</h1>
<h3>我的name:{this.state.name}</h3>
{/* <B username={this.state.name}/> */}
<Provider value={name}>
<B/>
</Provider>
</div>
);
}
export default A
class B extends Component{
render(){
return(
<div className='child'>
<h1>bbbbb</h1>
<h3>name:{this.props.username}</h3>
<C/>
</div>
)
}
}
function C(){
return(
<div className='grand'>
<h1>ccccc</h1>
<h3>name:
<Consumer>
{
value=>{
return `${value}`
}
}
</Consumer>
</h3>
</div>
)
}
react-PureComponent
控制阀门,就不用我们写控制逻辑,这个是一个优化的东西,避免没有更新也要调render
import React, { Component,PureComponent } from 'react';
class Parent extends PureComponent {
react-renderprops
<A>hello/</A>
在a当中,this.props.children拿到
<A><B></B></A>
这样ab也能形成父子,但是要展示b的话,a当中需要通过 {this.props.children}才会展示出来
this.props.render()
利用这个就可以预留一个位置放置任意组件,插槽相当于
export default class Demo extends Component {
render() {
return (
<div className='parent'>
<h3>parent</h3>
<A render={(name)=><B name={name}/>}/>//render的返回值是b,通过这样的方式进行父子组件传值
</div>
)
}
}
class A extends Component{
state ={name:'111'}
render(){
return(
<div className='child'>
<h1>aaaaa</h1>
<h3>name</h3>
{this.props.render(this.state.name)}//在这里调用了render,其实render这里的名字是自己取得,上下保持一致就行
</div>
)
}
}
class B extends Component{
render(){
return(
<div className='child'>
<h1>bbbbb</h1>
<h3>name:{this.props.name}</h3>
</div>
)
}
}
react-错误边界
把错误限制在这个组件,不影响外部组件得渲染
//当parent的子组件出现报错的时候,会触发
static getDeriveStateFromError(error){
return {hasError:error}
}
//调用,比如可以这样利用,这样控制子组件出错不影响父组件了
{this.state.hasError? <h1>错误处理</h1>:<Child/>}
componentDidCatch(){
//子组件渲染出现问题就会调用这个生命周期次数,可以用来统计错误次数
}
Vue 组件传值
父组件对子组件
传值
调用函数
子组件对父组件
子组件无法直接改变父组件的值,因为vue是单向数据流
//父组件当中
<child-component :message="message" @update-message="updateMessage" />
//子组件当中
//这个可以传值
props: ['message'],
//这样是调用方法
updateParentMessage() {
this.$emit('update-message', this.inputValue);
}