2023年最全前端React18面试题考点

目录

目录

React18

特点

声明式编码

单向数据流 

组件化

虚拟DOM(Virtual Dom)(同Vue)

Diff算法(同Vue)

组件属性

props

state

refs

总结

受控组件和非受控组件

事件event

事件处理的几种方法

事件中this的处理

事件传参处理

鼠标事件 mouseenter与mouseover区别

跨组件通信

生命周期

状态提升

复用组件

Render Props模式

HOC高阶组件模式

Hooks

useState

useReducer

useEffect

useRef

倒计时(⭐手写)

useCallback和useMemo

自定义Hook

StrictMode严格模式

Router

路由模式(同Vue)

基础路由搭建

重定向路由

自定义全局守卫

动态路由

Redux状态管理库

应用

React脚手架

Angular,Vue,React对比

Angular

React和Vue

MVC、MVP、MVVM模式

MVC (Model View Controller)

MVP(Model View Presenter)

MVVM (Model View View Model)


React18

React是用来构造用户界面的JS库 

在React18中,需要使用两个文件来初始化框架:

  • react.development.js 或 react模块 -> 生成虚拟DOM

  • react-dom.development.js 或 react-dom/client模块 -> Diff算法 + 处理真实DOM

下面就是初始化React程序的代码。




  
  
  
  Document
    
  
  


  
 

特点

虚拟DOM,组件化设计模式,声明式代码,单向数据流,使用jsx描述信息

声明式编码

  • 命令式编程:流程(每一步指令怎么去做)
  • 声明式编码:目标,而非流程

因没有指令的概念,所以条件渲染和列表渲染都要通过命令式编程来实现(即JS本身的能力)

map()方法
let app = document.querySelector('#app');
let root = ReactDOM.createRoot(app); 
let data = [
    { id: 1, text: 'aaa' },
    { id: 2, text: 'bbb' },
    { id: 3, text: 'ccc' }
];
let element = (
    
    { data.map(v=>
  • {v.text}
  • ) }
); root.render(element);

单向数据流 

数据主要从父节点传到子节点(通过props),如果父级的某个props改变了,React会重新渲染所有子节点

组件化

可复用的代码可以抽成组件共同使用(UI,方法等) 

每个UI块都是一个组件,每个组件都有一个状态。

虚拟DOM(Virtual Dom)(同Vue)

虚拟 DOM,根据模板生成一个js对象(使用createElement,方法),取代真实的 DOM 。

当页面打开时浏览器会解析 HTML 元素,构建一颗 DOM 树,将状态全部保存起来

Vue和React框架都会自动控制DOM的更新,而直接操作真实DOM是非常耗性能的,所以才有了虚拟DOM的概念

React遵循可观察的模式,并监听状态变化。当组件的状态改变时,React更新虚拟DOM树。

缺点首次渲染大量DOM时,由于多了一层虚拟DOM的计算,会比innerHTML插入慢
 

Diff算法(同Vue)

通过同层的树节点进行比较的高效算法,比较方式:diff整体策略为:深度优先,同层比较

总的来说就是减少DOM,重绘回流


react生成的新虚拟DOM和旧虚拟DOM的比较规则:

  • 如果旧的虚拟DOM中找到了与新虚拟DOM相同的key:

如果内容没有变化,就直接只用之前旧的真实DOM
如果内容发生了变化,就生成新的真实DOM

  • 如果旧的虚拟DOM中没有找到与新虚拟DOM相同的key:

根据数据创建新的真实的DOM,随后渲染到页面上

组件属性

每个 React 组件强制要求必须有一个 render()。它返回一个 React 元素,是原生 DOM 组件的表示。

props

对外公开属性,只读

传递数据


    

传递函数

// 子组件
class Head extends React.Component {
    render(){
        this.props.getData('子组件的问候~~~')
        return (
            
Head Component
); } } // 父组件 class Welcome extends React.Component { getData = (data) => { console.log(data) } render(){ return (
hello world, {this.props.msg}
); } }

构造函数获取props

class Foo {
    constructor(props){
        this.props = props;
    }
}
class Bar extends Foo {
    constructor(props){
        super(props);
        console.log(this.props);
    }
    render(){
        console.log(this.props);
        return '';
    }
}
let props = {
    msg: 'hello world'
};
let b = new Bar(props);
b.props = props;
b.render();

多属性传递props

class Welcome extends React.Component {
    render(){
        //解构
        let { msg, username, age } = this.props;
        console.log( isChecked );
        return (
            
hello world, {msg}, {username}, {age}
); } } let info = { msg: 'hi react', username: 'xiaoming', age: 20 }; let element = ( );

设置props初始值和类型

import PropTypes from 'prop-types'
class Welcome extends React.Component {
    static defaultProps = {
        age: 0
    }
    static propTypes = {
        age: PropTypes.number
    }
    ...
}

state

组件的私有属性,值是对象(可以包含多个key-value的组合)

通过state的变化设置响应式视图受控于当前组件

class Welcome extends React.Component {
    state = {
        msg: 'hello',
        count: 0
    }
    handleClick = () => {   
        this.setState({
            msg: 'hi'
        });
    }
    render(){
        console.log('render');
        return (
            
{this.state.msg}, {this.state.count}
); } } let element = ( );

refs

React操作原生DOM跟Vue框架是类似的,都是通过ref属性来完成的

class Welcome extends React.Component {
    myRef = React.createRef()
    handleClick = () => {   
        //console.log(this.myRef.current);  // 原生DOM input
        this.myRef.current.focus();//获取焦点
    }
    render(){
        return (
            
); } }

总结

props


公开,单向数据流值,父子组件间的唯一通信不可改

1.每个组件对象都会有props(properties的简写)属性

2.组件标签的所有属性都保存在props中

3.内部读取某个属性值:this.props.propertyName

state


私有(通过Ajax获取回来的数据,一般都是私有数据),

React 把组件看成是一个状态机(State Machines),

只需更新组件的 state,然后根据新的 state 重新渲染用户界面(不要操作 DOM)。


refs


当需要获取某一个真实的DOM元素来交互,比如文本框的聚焦、触发强制动画等

当需要操作的元素和获取的元素是同一个时,无需ref

受控组件和非受控组件

非受控组件
现用现取,官方建议尽量少用ref,用多了有一定的效率影响

handleSubmit = (event) => {
            event.preventDefault() //阻止表单提交
            const {username, password} = this//拿到的是form下的username, password结点
            alert(`你输入的用户名是:${username.value},你输入的密码是:${password.value}`)
        }
 
render() {
return (
用户名: this.username = c} type="text" name="username"/> 密码: this.password = c} type="password" name="password"/>


受控组件
将输入维护到state,等需要时再从state取出来

    class Login extends React.Component {
 
//state最好要初始化状态
        state = {
            username: '', //用户名
            password: '' //密码
        }
 
//保存用户名到状态中
        saveUsername = (event) => {
this.setState({username: event.target.value})
        }
 
//保存密码到状态中
        savePassword = (event) => {
this.setState({password: event.target.value})
        }
 
//表单提交的回调
        handleSubmit = (event) => {
          event.preventDefault() //阻止表单提交
          const {username, password} = this.state//获得的是state下的username,password值
          alert(`你输入的用户名是:${username},你输入的密码是:${password}`)
        }

事件event

React中的事件都是采用事件委托的形式,所有的事件都挂载组件容器上,其次event对象是合成处理过的

事件处理的几种方法

import React from 'react'
class Test extends React.Component{
    
    handleClick2(){
        console.log('click2')
    }
 
    hangleClick4 = () =>{
        console.log('click4')
    }
    render(){
        return(
            
            
            
            
        )
    }
}
export default Test

事件中this的处理

class Welcome extends React.Component {
    handleClick = (ev) => {  //推荐 public class fields语法,箭头函数不会创建自己的                                      this,它只会从自己的作用域链的上一层继承 this。
        console.log(this);   //对象
        console.log(ev);
    }
    handleClick(){           //不推荐 要注意修正指向
        console.log(this);   //按钮 
    }
    render(){
        return (
            
hello world
); } } let element = ( );

事件传参处理


推荐采用函数的高阶方式,具体代码如下:

class Welcome extends React.Component {
    handleClick = (num) => {   // 高阶函数
        return (ev) => {
            console.log(num);
        }
    }
    render(){
        return (
            
                                hello world            
        );     } } let element = (     );

鼠标事件 mouseenter与mouseover区别

mouseenter: 鼠标进入被绑定事件监听元素节点时触发一次,再次触发是鼠标移出被绑定元素,再次进入时。而当鼠标进入被绑定元素节点触发一次后没有移出,即使鼠标动了也不再触发

mouseover: 鼠标进入被绑定事件监听元素节点时触发一次,如果目标元素包含子元素,鼠标移出子元素到目标元素上也会触发。

mouseenter 不支持事件冒泡 mouseover 会冒泡

跨组件通信

Welcome传递给Title:

let MyContext = React.createContext();
class Welcome extends React.Component {
    state = {
        msg: 'welcome组件的数据'
    }
    render(){
        return (
            
Hello Welcome
); } } class Head extends React.Component { render(){ return (
Hello Head </div> ); } } class Title extends React.Component { static contextType = MyContext componentDidMount = () => { console.log( this.context ); } render(){ return ( <div> Hello Title <MyContext.Consumer>{ value => value }</MyContext.Consumer> </div> ); } } let element = ( <Welcome /> );</code></pre> </div> <p>通过<code><MyContext.<strong>Provider</strong>></code>组件携带<code>value</code>属性进行向下传递的,</p> <p>那么接收的语法是通过<code><MyContext.<strong>Consumer</strong>></code>组件。</p> <p>也可以定义一个静态方法<code>static contextType = MyContext</code>,这样就可以在逻辑中通过<strong><code>this.context</code></strong>来拿到同样的值。</p> <h2 id="%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F">生命周期</h2> <p><strong>生命周期钩子函数</strong>就是<strong>回调函数</strong>,</p> <p><strong>挂载</strong></p> <ul> <li>constructor():在 React 组件<strong>挂载之前</strong>,会调用它的构造函数。(注:如果不<strong>初始化 state</strong> 或不进行<strong>方法绑定</strong>,则不需要为 React 组件实现构造函数。)</li> <li>render(): class 组件中唯一必须实现的方法。</li> <li>componentDidMount():在<strong>组件挂载后(插入 DOM 树中)</strong>立即调用。依赖于 DOM 节点的<strong>初始化</strong>应该放在这里。</li> </ul> <p><strong>更新</strong></p> <ul> <li>render(): class 组件中唯一必须实现的方法。</li> <li>componentDidUpdate():在<strong>更新</strong>后会被立即调用。<strong>首次渲染</strong>不会执行此方法。</li> </ul> <p><strong>卸载</strong></p> <ul> <li>componentWillUnmount():在组件卸载及销毁之前直接调用。在此方法中执行必要的清理操作,例如,清除 timer,取消网络请求或清除在 componentDidMount() 中创建的订阅等。<br>  </li> </ul> <p>可以看到挂载时和更新时都有<code>render</code>这个方法。这就是为什么<strong>state改变</strong>的时候,会触发<strong><code>render</code>重渲染操作</strong>。</p> <p><a href="http://img.e-com-net.com/image/info8/997d047a1fbd4e2097919e50836e424e.jpg" target="_blank"><img alt="2023年最全前端React18面试题考点_第1张图片" height="326" src="http://img.e-com-net.com/image/info8/997d047a1fbd4e2097919e50836e424e.jpg" width="650" style="border:1px solid black;"></a>​</p> <div> <pre><code class="language-javascript">class Welcome extends React.Component { state = { msg: 'hello world' } constructor(props){ super(props); console.log('constructor'); } componentDidMount = () => { // react中发起ajax请求的初始操作,在这个钩子中完成 console.log('componentDidMount'); } componentDidUpdate = () => { // 等DOM更新后触发的钩子 console.log('componentDidUpdate'); } componentWillUnmount = () => { console.log('componentWillUnmount'); } handleClick = () => { /* this.setState({ msg: 'hi react' }); */ //this.forceUpdate(); root.unmount(); // 触发卸载组件 } render(){ console.log('render'); return ( <div> <button onClick={this.handleClick}>点击</button> { this.state.msg } </div> ); } }</code></pre> </div> <h2 id="%E7%8A%B6%E6%80%81%E6%8F%90%E5%8D%87">状态提升</h2> <p><strong>多个组件</strong>需要<strong>共享</strong>的状态提升到它们最近的<strong>父组件</strong>上,在父组件上改变这个状态然后通过props分发给子组件。对子组件操作,子组件不改变自己的状态。</p> <h2 id="Hooks"><strong>复用组件</strong></h2> <h3 id="Render%20Props%E6%A8%A1%E5%BC%8F">Render Props模式</h3> <p><strong>组件之间</strong>使用一个<strong>值为函数</strong>的 <strong>prop 共享代码</strong>的简单技术。</p> <div> <pre><code class="language-javascript">class MouseXY extends React.Component { state = { x: 0, y: 0 } componentDidMount = () => { document.addEventListener('mousemove', this.move) } componentWillUnmount = () => { document.removeEventListener('mousemove', this.move) } move = (ev) => { this.setState({ x: ev.pageX, y: ev.pageY }); } render(){ return ( <React.Fragment> { this.props.render(this.state.x, this.state.y) } </React.Fragment> ); } } class Welcome extends React.Component { render(){ return ( <MouseXY render={(x, y)=> <div> hello world, {x}, {y} </div> } /> ); } } let element = ( <Welcome /> );</code></pre> </div> <p>render属性后面的值是一个<strong>回调函数</strong>,通过这个函数的形参可以得到组件中的数据,从而实现功能的复用。</p> <h3 id="HOC%E9%AB%98%E9%98%B6%E7%BB%84%E4%BB%B6%E6%A8%A1%E5%BC%8F">HOC高阶组件模式</h3> <p><strong>参数</strong>为<strong>组件</strong>,<strong>返回值</strong>为<strong>新组件</strong>的<strong>函数</strong></p> <div> <pre><code class="language-javascript">function withMouseXY(WithComponent){ return class extends React.Component { state = { x: 0, y: 0 } componentDidMount = () => { document.addEventListener('mousemove', this.move) } componentWillUnmount = () => { document.removeEventListener('mousemove', this.move) } move = (ev) => { this.setState({ x: ev.pageX, y: ev.pageY }) } render(){ return <WithComponent {...this.state} /> } } } class Welcome extends React.Component { render(){ return ( <div> hello world, { this.props.x }, { this.props.y } </div> ); } } const MouseWelcome = withMouseXY(Welcome) let element = ( <MouseWelcome /> );</code></pre> </div> <h2><strong>Hooks</strong></h2> <p>Hook 是 React 16.8 的新增特性,是一个特殊的<strong>函数</strong>,它可以在<strong>不写 class(</strong>即<strong>不用extends React.Component) </strong>的情况下“<strong>钩入</strong>” React 特性<strong>(</strong>即<strong>组件化模块</strong>的特性<strong>)</strong>。</p> <h3 id="useState"><strong>useState</strong></h3> <p>等同组件中的setState()</p> <div> <pre><code class="language-javascript">let { useState } = React;//只能在最顶层使用Hook let Welcome = (props) => {//只能在函数组件中使用Hook //count的初始值0,设置count的函数 const [count, setCount] = useState(0); const handleClick = () => { setCount(count + 1) } return ( <div> <button onClick={handleClick}>点击</button> <div>hello world, { count }</div> </div> ); }</code></pre> </div> <p>与组件中的state一样自动批处理(即合并修改,每次set只渲染一次),可用<code>flushSync</code>方法消除</p> <p>(flush synchronization清洗同步)</p> <div> <pre><code class="language-javascript">setCount((count)=> count+1) setCount((count)=> count+1) setCount((count)=> count+1) <div>{ count }</div> // 渲染 3 let { useState } = React; let { flushSync } = ReactDOM; let Welcome = (props) => {    const [count, setCount] = useState(0);    const [msg, setMsg] = useState('hello');    const handleClick = () => {        flushSync(()=>{          setCount(count + 1)       })        flushSync(()=>{          setMsg('hi')       })         }    return (        <div>            <button onClick={handleClick}>点击</button>            <div>hello world, { count }, { msg }</div>        </div>   ); }</code></pre> </div> <p>useState中的值在修改的时候,并<strong>不会进行原值的合并处理</strong>,所以使用的时候要注意。可利用扩展运算符的形式来解决合并的问题。</p> <div> <pre><code class="language-javascript">const [info, setInfo] = useState({    username: 'xiaoming',    age: 20 }) setInfo({    ...info,    username: 'xiaoqiang' })</code></pre> </div> <p>如果遇到<strong>初始值需要大量运算才能获取</strong>的话,可采用<strong>惰性初始state</strong>,useState()添加回调函数的形式来实现。</p> <div> <pre><code class="language-javascript">const initCount = () => {    console.log('initCount');    return 2*2*2; } const [count, setCount] = useState(()=>{    return initCount(); });</code></pre> </div> <p>这样初始只会计算一次,并不会<strong>每次都重新进行计算</strong>。</p> <h3 id="useReducer"><strong>useReducer</strong></h3> <p>useState 的替代方案。它接收一个形如 (state, action) => newState 的 reducer,并返回当前的 state 以及与其配套的 <strong>dispatch</strong> 方法。</p> <p>在某些场景下,useReducer 会比 useState 更适用,例如 state 逻辑较复杂且包含多个子值,或者下一个 state 依赖于之前的 state 等。</p> <div> <pre><code class="language-javascript">let { useReducer } = React; let loginState = {//体现整体关联性与统一性** isLogin: true, isLogout: false } let loginReducer = (state, action) => { switch(action.type){ case 'login': return { isLogin: true, isLogout: false } case 'logout': return { isLogin: false, isLogout: true } default: throw new Error() } } let Welcome = (props) => { const [ state, loginDispatch ] = useReducer(loginReducer, loginState); const handleLogin = () => { loginDispatch({ type: 'login' }); } const handleLogout = () => { loginDispatch({ type: 'logout' }); } return ( <div> { state.isLogin ? <button onClick={handleLogout}>退出</button> : <button onClick={handleLogin}>登录</button> } </div> ); }</code></pre> </div> <h3 id="useEffect"><strong>useEffect</strong></h3> <p>在函数组件中执行副作用操作,<strong>副作用</strong>即:<strong>DOM操作、获取数据、记录日志</strong>等</p> <p>代替类组件中的<strong>生命周期</strong>钩子函数。<br> 如果不传参:相当于render之后就会执行<br> 如果传空数组:相当于componentDidMount<br> 如果传数组:相当于componentDidUpdate<br> 如果返回回调函数:相当于componentWillUnmount,会在组件卸载的时候执行清除操作。</p> <p>effect 在每次渲染的时候都会执行。React 会在执行当前 effect 之前对上一个 effect 进行清除。</p> <div> <pre><code class="language-javascript">let Welcome = (props) => { const [count, setCount] = useState(0); //异步函数,在浏览器渲染DOM后触发的 useEffect(()=>{ // 初始 和 更新 数据的时候会触发回调函数 console.log('didMount or didUpdate'); return ()=>{ // 这里回调函数可以用来清理副作用 console.log('beforeUpdate or willUnmount'); } }) const handleClick = () => { //setCount(count + 1); root.unmount();//卸载 } return ( <div> <button onClick={handleClick}>点击</button> <div>hello world, { count }</div> </div> ); }</code></pre> </div> <p><strong>关注点分离</strong>后,改变一个数据后,例如count,那么msg相关的useEffect也会触发,</p> <p>给useEffect设置第二个参数,只重新触发自己的useEffect回调函数,即响应式的数据</p> <div> <pre><code class="language-javascript">const [count, setCount] = useState(0); useEffect(()=>{ console.log(count); }, [count]) const [msg, setMsg] = useState('hello'); useEffect(()=>{ console.log(msg); }, [msg])</code></pre> </div> <ul> <li>useEffect()是在<strong>渲染之后</strong>且<strong>屏幕更新之后</strong>,,是<strong>异步</strong>的;</li> <li>useLayoutEffect()是在<strong>渲染之后</strong>但在<strong>屏幕更新之前</strong>,是<strong>同步</strong>的。</li> </ul> <p>大部分情况下我们采用<strong>useEffect()</strong>,<strong>性能更好</strong>。</p> <p>但当你的useEffect里面的操作<strong>需要处理DOM</strong>,并且<strong>会改变页面的样式</strong>,</p> <p>就需要<strong>useLayoutEffect</strong>,否则可能会出现闪屏问题。</p> <h3 id="useRef"><strong>useRef</strong></h3> <div> <pre><code class="language-javascript">let { useRef } = React; let Welcome = (props) => {       const myRef = useRef() ...} 等同于 React.createRef()</code></pre> </div> <p><strong>函数转发</strong></p> <p>把ref添加到函数组件上,把ref对应的对象<strong>转发到子组件</strong>的内部元素身上。</p> <div> <pre><code class="language-javascript">let Head = React.forwardRef((props, ref) => { return ( <div> hello Head <input type="text" ref={ref} /> </div> ) }) let Welcome = (props) => { const myRef = useRef() const handleClick = () => { myRef.current.focus(); } return ( <div> <button onClick={handleClick}>点击</button> <Head ref={myRef} /> </div> ); }</code></pre> </div> <p>    let count = useRef(0);  // 与state类似,有记忆功能,可理解为全局操作<br>     const handleClick = () => {<br>         count.<strong>current</strong>++;</p> <p>...</p> <p>}</p> <h3 id="articleContentId">倒计时(⭐手写)</h3> <pre><code class="language-javascript">//利用setTimeOut,每秒将数值减一 //利用useRef设置定时器,方便清楚 const [time,setTime]=useState(null)//倒计时时间 const timeRef=useRef()//设置延时器 //倒计时 useEffect(()=>{ //如果设置倒计时且倒计时不为0 if(time&&time!==0) timeRef.current=setTimeout(()=>{ setTime(time=>time-1) },1000) //清楚延时器 return ()=>{ clearTimeout(timeRef.current) } },[time]) <button onClick={()=>{settime(60)}} >开始计时</button> </code></pre> <h3 id="useCallback"><strong>useCallback和useMemo</strong></h3> <p>React 使用 <strong><strong>Object.is 比较算法</strong></strong> 来比较 state。</p> <p>当组件数据没有变化时,是不会重新渲染试图,如下,cosole.log不会执行</p> <div> <pre><code class="language-javascript">let Welcome = (props) => { const [ count, setCount ] = useState(0); const handleClick= () => { setCount(0); } console.log(123); return ( <div> <button onClick={handleClick}>点击</button> hello Welcome { Math.random() } </div> ); }</code></pre> </div> <p>当<strong>变化后</strong>state与当前state<strong>相同</strong>时,包括变化前的渲染一共会<strong>渲染两次</strong></p> <p>因为React 可能仍需要在<strong>跳过渲染前 渲染该组件</strong>。</p> <p>但React <strong>不会对组件树的“深层”节点进行不必要的渲染</strong></p> <p><code>React.memo</code><strong>避免</strong>可以没有必要的重新渲染,类似于类组件中的<strong>纯函数</strong>概念。</p> <p>将{ Math.random() } 包装成函数组件</p> <div> <pre><code class="language-javascript">let Welcome = (props) => { const [ count, setCount ] = useState(0); const handleClick= () => { setCount(1); } return ( <div> <button onClick={handleClick}>点击</button> hello Welcome <Head count={count} /> </div> ); } let Head = React.memo(() => { return ( <div>hello Head, { Math.random() }</div> ) })</code></pre> </div> <p>在<strong>渲染期间</strong>执行了<strong>高开销</strong>的计算,则可以使用 <code>useMemo</code> 来进行<strong>优化</strong>。</p> <p>useCallback返回一个<strong>可记忆</strong>的<strong>函数</strong>,useMemo返回一个可记忆的<strong>值</strong>,useCallback只是useMemo的一种<strong>特殊形式</strong>。</p> <div> <pre><code class="language-javascript">let Welcome = (props) => { const [ count, setCount ] = useState(0); const handleClick= () => { setCount(count+1); } const foo = () => {} return ( <div> <button onClick={handleClick}>点击</button> hello Welcome <Head onClick={foo} /> </div> ); } let Head = React.memo(() => { return ( <div>hello Head, { Math.random() }</div> ) })</code></pre> </div> <p>当点击按钮的时候,<Head>组件会进行重新渲染,因为每次重新触发<Welcome>组件的时候,后会重新生成一个<strong>新的内存地址</strong>的foo函数。</p> <p>通过useCallback和useMemo可以不让foo函数重新生成,使用之前的函数地址</p> <p>从而<strong>减少子组件的渲染,提升性能</strong>。</p> <div> <pre><code class="language-javascript">const foo = useCallback(() => {}, []) const foo = useMemo(()=> ()=>{}, [])   // 针对函数 const bar = useMemo(()=> [1,2,3], [])  // 针对数组 const foo = useMemo(()=> ()=>{}, [count])   // 第二个参数为依赖项,当count改变时,函数重新创建</code></pre> </div> <h3 id="%E8%87%AA%E5%AE%9A%E4%B9%89Hook"><strong>自定义Hook</strong></h3> <p><strong>实现函数组件复用</strong></p> <div> <pre><code class="language-javascript">let { useState, useEffect } = React let useMouseXY = () => { const [x, setX] = useState(0) const [y, setY] = useState(0) useEffect(()=>{ function move(ev){ setX(ev.pageX) setY(ev.pageY) } document.addEventListener('mousemove', move) //如果返回回调函数:相当于componentWillUnmount,会在组件卸载的时候执行清除操作。 return () => { document.removeEventListener('mousemove', move) } }, [])//如果传空数组:相当于componentDidMount return { x, y } } let Welcome = ()=>{ const {x, y} = useMouseXY() return ( <div> hello Welcome, {x}, {y} </div> ) }</code></pre> </div> <h2 id="Redux">StrictMode严格模式</h2> <p><code>StrictMode</code> 是一个用来突出显示应用程序中<strong>潜在问题</strong>的工具。用于<strong>开发</strong>环境</p> <p>与 <code>Fragment</code> 一样,<code>StrictMode</code> <strong>不会渲染任何可见的 UI</strong>。它为其后代元素触发额外的检查和警告。例如:</p> <ul> <li>识别不安全的<strong>过时</strong>的生命周期</li> <li>关于使用<strong>过时</strong>字符串 ref API 的警告</li> </ul> <p><strong>发布环境</strong>下关闭严格模式,以避免<strong>性能</strong>损失。</p> <h2 id="Router">Router</h2> <p>路由是根据<strong>不同的url地址</strong>展示不同的内容或页面,是SPA(单页应用)的<strong>路径管理器</strong>,</p> <p></p> <p>1.一个路由就是一个映射关系(key:value)</p> <p>2.key为路径, value可能是function或component</p> <p>Router 用于定义多个路由,当用户定义特定的 URL 时,如果此 URL 与 Router 内定义的任何 “路由” 的路径匹配,则用户将<strong>重定向</strong>到该特定路由。</p> <h3 id="%E8%B7%AF%E7%94%B1%E6%A8%A1%E5%BC%8F">路由模式(同Vue)</h3> <p>React中的路由模式跟Vue中一样,分为history和hash模式。默认是hash</p> <p><strong>Hash模式</strong></p> <p>hash——即地址栏URL中的#符号(此hash不是密码学里的散列运算)。比如在 http://localhost:8080/#/donate 中,hash的值就是#/donate,我们在浏览器中可以通过BOM中的window.location.hash来获取当前URL的hash值</p> <p>注:BOM(Browser Object Model) 是指浏览器对象模型,BOM由多个对象组成,其中代表浏览器窗口的Window对象是BOM的顶层对象,其他对象都是该对象的子对象。</p> <p><a href="http://img.e-com-net.com/image/info8/6204a902d96647cabe097caacccec111.jpg" target="_blank"><img alt="2023年最全前端React18面试题考点_第2张图片" height="287" src="http://img.e-com-net.com/image/info8/6204a902d96647cabe097caacccec111.jpg" width="650" style="border:1px solid black;"></a>​</p> <p><strong>history模式</strong></p> <p>通过在<strong>host</strong>后,直接添加<strong>斜线</strong>和<strong>路径</strong>来<strong>请求后端</strong>的一种<strong>URL模式</strong>。</p> <p><a href="http://img.e-com-net.com/image/info8/af41845fc3684e04b97ed08bf621607f.jpg" target="_blank"><img alt="2023年最全前端React18面试题考点_第3张图片" height="280" src="http://img.e-com-net.com/image/info8/af41845fc3684e04b97ed08bf621607f.jpg" width="650" style="border:1px solid black;"></a>​</p> <p>图中pathname变量为/donate,而hash值为空。</p> <p><strong>原理</strong></p> <ul> <li>hash通过<strong>window.addEventListener</strong>监听浏览器的<strong>onhashchange()</strong>事件变化,查找对应的路由规则</li> <li><strong>HTML5</strong>的<strong>history API</strong>监听URL变化,所以有浏览器兼容问题</li> </ul> <p></p> <p><strong>区别</strong></p> <ul> <li>是否向后端传参:</li> </ul> <p>    在hash模式中,我们刷新一下上面的网页,可以看到请求的URL为http://localhost:8080/,没有带上#/donate,说明hash 虽然出现 URL 中,#后面的内容是不会包含在http请求中的,对后端完全没有影 响,因此改变 hash 不会重新加载页面。</p> <p><img alt="" height="0" src="http://img.e-com-net.com/image/info8/263e2912ee264011b1b3352f17e1f89d.jpg" width="0">​</p> <p>在history模式中,刷新一下网页,明显可以看到请求url为完整的url,url完整地请求了后端:</p> <p><a href="http://img.e-com-net.com/image/info8/48f77071b1ec4b2eaaa86c2c7145fdca.jpg" target="_blank"><img alt="2023年最全前端React18面试题考点_第4张图片" height="298" src="http://img.e-com-net.com/image/info8/48f77071b1ec4b2eaaa86c2c7145fdca.jpg" width="650" style="border:1px solid black;"></a>​</p> <p>前端的 URL 必须和实际向后端发起请求的 URL 一致,否则返回 404 错误<br><br>  </p> <p>在React中</p> <ul> <li> <p>history模式:createBrowserRouter</p> </li> </ul> <p>IE9及以下不兼容,需要由<strong>web server</strong>支持,在<strong>web client</strong>这边window.location.<strong>pathname</strong>被<strong>react router</strong>解析</p> <ul> <li> <p>hash模式:createHashRouter</p> </li> </ul> <p>不需要由web server支持,因为它的只有<strong>‘/’path</strong>需要由web server支持,而<strong>#/react/route URL</strong>不能被web server读取,在<strong>web client</strong>这边window,location.<strong>hash</strong>被<strong>react router</strong>解析</p> <p></p> <p>history的好处是可以进行修改历史记录,并且不会立刻像后端发起请求。不过如果对于项目没有硬性标准要求,可以直接使用hash模式开发。</p> <h3 id="%E5%9F%BA%E7%A1%80%E8%B7%AF%E7%94%B1%E6%90%AD%E5%BB%BA">基础路由搭建</h3> <div> <pre><code class="language-javascript">import { createBrowserRouter, createHashRouter } from 'react-router-dom' //路由表 export const routes = []; //路由对象 const router = createBrowserRouter(routes); export default router;</code></pre> </div> <p>接下来让路由配置文件与React结合,需要在主入口index.js进行操作,如下:</p> <div> <pre><code class="language-javascript">import { RouterProvider } from 'react-router-dom' import router from './router'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render(  <React.StrictMode>    <RouterProvider router={router}></RouterProvider>  </React.StrictMode> );</code></pre> </div> <p>路由表的配置字段如下:</p> <ul> <li> <p>path:指定路径</p> </li> <li> <p>element:对应组件</p> </li> <li> <p>children:嵌套路由</p> </li> </ul> <div> <pre><code class="language-javascript">//路由表 export const routes = [   {        path: '/',        element: <App />,        children: [           {                path: '',                element: <Home />           },   {                path: 'about',                element: <About />,                children: [                   {                        path: 'foo',                        element: <Foo />,                   },                   {                        path: 'bar',                        element: <Bar />,                   }   ]   }       ]   } ];</code></pre> </div> <p>接下来就是显示路由区域,利用<strong><outlet>组件占位</strong>,表明<strong>子路由渲染的位置</strong></p> <div> <pre><code class="language-javascript">import React from "react"; import { Outlet, Link } from 'react-router-dom' function App() {  return (    <div className="App">      <h2>hello react</h2>      <Link to="/">首页</Link> | <Link to="/about">关于</Link>      <Outlet />    </div> ); } export default App;</code></pre> </div> <p>可以看到 <Link>组件用于<strong>声明式</strong>路由切换使用。同样<outlet>组件也可以给嵌套路由页面进行使用,从而完成二级路由的切换操作。</p> <div> <pre><code class="language-javascript">import React from 'react' import './About.scss' import { Outlet, Link } from 'react-router-dom' export default function About() {  return (    <div>      <h3>About</h3>      <Link to="/about/foo">foo</Link> | <Link to="/about/bar">bar</Link>      <Outlet />    </div> ) } ​ </code></pre> </div> <h3 id="%E9%87%8D%E5%AE%9A%E5%90%91%E8%B7%AF%E7%94%B1">重定向路由</h3> <p>访问的URL跳转到另一个URL上,从而实现重定向的需求。</p> <p><Navigate>组件就是实现重定向需求的组件。</p> <div> <pre><code class="language-javascript">import { createBrowserRouter, createHashRouter, Navigate } from 'react-router-dom' children: [ { index: true,// 默认路由 element: <Navigate to="/about/foo/123" />, }, { path: 'foo', element: <Foo /> }, { path: 'bar', element: <Bar /> } ]</code></pre> </div> <h3 id="%E8%87%AA%E5%AE%9A%E4%B9%89%E5%85%A8%E5%B1%80%E5%AE%88%E5%8D%AB">自定义全局守卫</h3> <p>全局守卫:包裹根组件,访问根组件下面的所有子组件都要先通过守卫进行操作</p> <p>在React里面,它不像Vue一样,为我们提供和很多方便的功能,一些功能都需要自己去进行封装比如说路由拦截</p> <p>在/src/components/BeforeEach.jsx下创建守卫的组件。</p> <div> <pre><code class="language-javascript">import React from 'react' import { Navigate } from 'react-router-dom' import { routes } from '../../router'; export default function BeforeEach(props) {  if(true){    return <Navigate to="/login" /> }  else{    return (      <div>{ props.children }</div>   ) } }</code></pre> </div> <p>根据判断的结果,是否进入到组件内,还是重定向到其他的组件内。</p> <p>调用BeforeEach.jsx,index.js通过路由配置文件引入,如下:</p> <div> <pre><code class="language-javascript">export const routes = [ {    path: '/',    element: <BeforeEach><App /></BeforeEach>//包裹根组件APP } ]</code></pre> </div> <h3 id="%E5%8A%A8%E6%80%81%E8%B7%AF%E7%94%B1">动态路由</h3> <p>根据<strong>不同的UR</strong>L,可以访问<strong>同一个组件</strong>。在React路由中,通过<strong>path</strong>字段来指定动态路由的写法。</p> <p>foo/xxx都能访问到Foo组件,本身就有实现了动态路由</p> <div> <pre><code class="language-javascript">import { Outlet, Link } from 'react-router-dom' export default function About() { return ( <div> <Link to="/about/foo/123">foo 123</Link> | <Link to="/about/foo/456">foo 456</Link> </div> ) }</code></pre> </div> <div> <pre><code class="language-javascript">{ path: 'foo/:id', element: <Foo /> }</code></pre> </div> <p><code>id</code>就是<strong>变量名</strong>,可以在组件中用<code>useParams</code>来获取到对应的值。</p> <div> <pre><code class="language-javascript">import { useParams } from 'react-router-dom' export default function Foo() { const params = useParams() return ( <div>Foo, { params.id }</div> ) }</code></pre> </div> <h2 id="Redux%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E5%BA%93">Redux状态管理库</h2> <p>Redux就像Vue中的<strong>Vuex</strong>或<strong>Pinia</strong>是一样专门用于做<strong><strong>状态管理</strong></strong>的JS库(不是react插件库)。</p> <p>只不过Redux比较独立,可以跟很多框架结合使用,不过主要还是跟React配合比较好,也是最常见的React状态管理的库。</p> <p>redux相当于在<strong>顶层组件</strong>之上又加了一个<strong>组件</strong></p> <p></p> <p><a href="http://img.e-com-net.com/image/info8/ca80841dc35948008912665b9c78ca21.jpg" target="_blank"><img alt="2023年最全前端React18面试题考点_第5张图片" src="http://img.e-com-net.com/image/info8/ca80841dc35948008912665b9c78ca21.jpg" width="650" height="389" style="border:1px solid black;"></a>​</p> <div> <pre><code class="language-javascript">//state存储共享数据 function counterReducer(state={count: 0}, action) {//reducer修改state    switch(action.type){        case 'inc': return {count: state.count + state.payload}        default:            return state;   } } const store = createStore(counterReducer) export default store</code></pre> </div> <p>这样store对象就可以在其他组件中进行使用了,例如在<Bar>组件中。</p> <div> <pre><code class="language-javascript">import React from 'react' import './Bar.scss' import { useSelector,useDispatch } from 'react-redux' export default function Bar() {  const count = useSelector((state)=> state.count)//获取共享状态  const dispatch=useDispatch();//修改共享状态  const handleClick = () => {    dispatch({//dispatch触发Reducer,分发action      type: 'inc',      payload: 5   }) }  return (    <div>     <button onClick={handleClick}>修改count</button>         Bar, { count }    </div> ) }</code></pre> </div> <p>在主模块中进行注册。</p> <div> <pre><code class="language-javascript">import { RouterProvider } from 'react-router-dom' import router from './router'; import { Provider } from 'react-redux' import store from './store'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render(  <React.StrictMode>    <Provider store={store}>//注册状态管理与React结合,自动完成重渲染      <RouterProvider router={router}></RouterProvider>    </Provider>  </React.StrictMode> );</code></pre> </div> <h3 id="%E5%BA%94%E7%94%A8">应用</h3> <p>从项目的整体看</p> <ul> <li>不同身份的<strong>用户</strong>有不同的使用方式(比如普通用户和管理员)</li> <li>多个用户之间可以<strong>协作</strong></li> <li>与服务器大量<strong>交互</strong>,或者使用了 WebSocket</li> <li>View 要从<strong>多个来源</strong>获取数据</li> </ul> <p>从组件角度看</p> <ul> <li>某个组件的状态,需要<strong>共享</strong></li> <li>组件有相当<strong>大量</strong>的,<strong>随时间变化</strong>的数据</li> <li>state 需要有一个<strong>单一可靠</strong>数据源</li> </ul> <h2 id="Angular%2CVue%2CReact">React脚手架</h2> <p>开始一个react项目,<strong>不用手动配置</strong>,直接开发</p> <h2 id="Angular%2CVue%2CReact%E5%8C%BA%E5%88%AB">Angular,Vue,React对比</h2> <h3 id="Angular"><br> Angular</h3> <p>框架比较成熟<strong>完整</strong>,过于庞大,上手难;</p> <h3 id="React%E5%92%8CVue">React和Vue</h3> <p><strong>相同点</strong> :</p> <p>创建<strong>UI的js库</strong></p> <p>都是使用了<strong>虚拟dom</strong></p> <p><strong>组件化</strong>开发</p> <p><strong>父子</strong>之间通信<strong>单项数据流</strong></p> <p>都支持<strong>服务端渲染</strong></p> <p></p> <p><strong>不同点</strong>:</p> <p>vue轻量级框架,其核心库<strong>只关注视图层</strong>,简单小巧、易学易上手;</p> <p>个人维护项目; 适合于<strong>移动端</strong>开发; </p> <p>reacct 的jsx,可读性好</p> <p>vue的是 template</p> <p>数据变化,react <strong>手动 setState</strong> vue<strong>自动响应式处理</strong> proxy object.DefineProperty</p> <p>react 单向数据流 ,vue双向数据流</p> <p>react 的 redux mobx</p> <p>vue 的vuex  pinia</p> <h2 id="MVC%E3%80%81MVP%E3%80%81MVVM%E6%A8%A1%E5%BC%8F"><strong>MVC、MVP、MVVM模式</strong></h2> <h3 id="MVC%20%EF%BC%88Model%20View%20Controller%EF%BC%89-React">MVC (Model View Controller)</h3> <p></p> <ul> <li>Model(模型):<strong>提供数据</strong></li> <li>View(视图):<strong>显示数据</strong></li> <li>Controller(控制器):<strong>用户交互</strong></li> </ul> <p><strong>【优点】</strong></p> <p><strong>耦合性低,方便维护</strong>,可以利于分工协作 重用性高</p> <p><strong>【缺点】</strong></p> <p>使得项目架构变得<strong>复杂</strong>,对开发人员要求高</p> <h3 id="MVP%EF%BC%88Model%20View%20Presenter%EF%BC%89">MVP(Model View Presenter)</h3> <p>从MVC演变而来,它们的基本思想有相通的地方<strong>Controller/Presenter</strong>负责逻辑的处理,</p> <h3 id="MVVM%20%EF%BC%88Model-View-ViewModel%EF%BC%89-Vue">MVVM (Model View View Model)</h3> <p><strong>视图</strong>和<strong>业务逻辑</strong>分开。</p> <p><strong>View视图层</strong>,<strong>Model 数据模型</strong>,<strong>ViewModel </strong>是它们<strong>双向绑定的桥梁,自动同步更新</strong></p> <p><strong>【优点】</strong></p> <p>相比mvp各层的<strong>耦合度</strong>更低,一个viewmodel层可以给多个view层共用(<strong>一对多</strong>),提高代码的<strong>可重用性</strong>。</p> <p>*<strong>耦合度:模块间依赖的程度。</strong></p> <p><strong>【缺点】</strong></p> <p>因为使用了<strong>dataBinding</strong>,增加了大量的<strong>内存开销</strong>,增加了程序的<strong>编译</strong>时间,所以适合<strong>轻量级</strong>项目。</p> <p>数据绑定使得 <strong>Bug 很难被调试</strong>。你看到界面异常了,有可能是你 <strong>View</strong> 的代码有 Bug,也可能是 <strong>Model</strong> 的代码有问题</p> <p></p> <p>React和Vue都用了MVVM</p> <p>React单向数据流:只能由<strong>数据</strong>层的变化去影响<strong>视图</strong>层的变化</p> <p>Vue双向数据绑定</p> </div> </div> </div> </div> </div> <!--PC和WAP自适应版--> <div id="SOHUCS" sid="1644025783804551168"></div> <script type="text/javascript" src="/views/front/js/chanyan.js"></script> <!-- 文章页-底部 动态广告位 --> <div class="youdao-fixed-ad" id="detail_ad_bottom"></div> </div> <div class="col-md-3"> <div class="row" id="ad"> <!-- 文章页-右侧1 动态广告位 --> <div id="right-1" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_1"> </div> </div> <!-- 文章页-右侧2 动态广告位 --> <div id="right-2" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_2"></div> </div> <!-- 文章页-右侧3 动态广告位 --> <div id="right-3" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_3"></div> </div> </div> </div> </div> </div> </div> <div class="container"> <h4 class="pt20 mb15 mt0 border-top">你可能感兴趣的:(前端,javascript,前端,react.js)</h4> <div id="paradigm-article-related"> <div class="recommend-post mb30"> <ul class="widget-links"> <li><a href="/article/1950232820773351424.htm" title="移动端城市区县二级联动选择功能实现包" target="_blank">移动端城市区县二级联动选择功能实现包</a> <span class="text-muted">good2know</span> <div>本文还有配套的精品资源,点击获取简介:本项目是一套为移动端设计的jQuery实现方案,用于简化用户在选择城市和区县时的流程。它包括所有必需文件:HTML、JavaScript、CSS及图片资源。通过动态更新下拉菜单选项,实现城市到区县的联动效果,支持数据异步加载。开发者可以轻松集成此功能到移动网站或应用,并可基于需求进行扩展和优化。1.jQuery移动端解决方案概述jQuery技术简介jQuery</div> </li> <li><a href="/article/1950232190038110208.htm" title="day15|前端框架学习和算法" target="_blank">day15|前端框架学习和算法</a> <span class="text-muted">universe_01</span> <a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/%E7%AC%94%E8%AE%B0/1.htm">笔记</a> <div>T22括号生成先把所有情况都画出来,然后(在满足什么情况下)把不符合条件的删除。T78子集要画树状图,把思路清晰。可以用暴力法、回溯法和DFS做这个题DFS深度搜索:每个边都走完,再回溯应用:二叉树搜索,图搜索回溯算法=DFS+剪枝T200岛屿数量(非常经典BFS宽度把树状转化成队列形式,lambda匿名函数“一次性的小函数,没有名字”setup语法糖:让代码更简洁好写的语法ref创建:基本类型的</div> </li> <li><a href="/article/1950194742100815872.htm" title="用代码生成艺术字:设计个性化海报的秘密" target="_blank">用代码生成艺术字:设计个性化海报的秘密</a> <span class="text-muted"></span> <div>本文围绕“用代码生成艺术字:设计个性化海报的秘密”展开,先概述代码生成艺术字在海报设计中的独特价值,接着介绍常用的代码工具(如HTML、CSS、JavaScript等),详细阐述从构思到实现的完整流程,包括字体样式设计、动态效果添加等,还分享了提升艺术字质感的技巧及实际案例。最后总结代码生成艺术字的优势,为设计师提供打造个性化海报的实用指南,助力提升海报设计的独特性与吸引力,符合搜索引擎SEO标准</div> </li> <li><a href="/article/1950191208873652224.htm" title="vue element 封装表单" target="_blank">vue element 封装表单</a> <span class="text-muted">影子信息</span> <a class="tag" taget="_blank" href="/search/vue/1.htm">vue</a><a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a> <div>背景:在前端系统开发中,系统页面涉及到的表单组件比较多,所以进行了简单的封装。封装的包括一些Form表单组件,如下:input输入框、select下拉框、等实现效果:理论知识:表单组件官方链接:点击跳转封装组件:封装组件的思路:不封装element组件,每一个input组件绑定一个form对象,例如官网。简单封装element组件,利用for循环生成form表单的每一项el-form-item。进</div> </li> <li><a href="/article/1950191165710069760.htm" title="前端面试每日 3+1 —— 第39天" target="_blank">前端面试每日 3+1 —— 第39天</a> <span class="text-muted">浪子神剑</span> <div>今天的面试题(2019.05.25)——第39天[html]title与h1、b与strong、i与em的区别分别是什么?[css]写出你知道的CSS水平和垂直居中的方法[js]说说你对模块化的理解[软技能]公钥加密和私钥加密是什么?《论语》,曾子曰:“吾日三省吾身”(我每天多次反省自己)。前端面试每日3+1题,以面试题来驱动学习,每天进步一点!让努力成为一种习惯,让奋斗成为一种享受!欢迎在Iss</div> </li> <li><a href="/article/1950178477592342528.htm" title="前端数据库:IndexedDB从基础到高级使用指南" target="_blank">前端数据库:IndexedDB从基础到高级使用指南</a> <span class="text-muted"></span> <div>文章目录前端数据库:IndexedDB从基础到高级使用指南引言一、IndexedDB概述1.1什么是IndexedDB1.2与其他存储方案的比较二、基础使用2.1打开/创建数据库2.2基本CRUD操作添加数据读取数据更新数据删除数据三、高级特性3.1复杂查询与游标3.2事务高级用法3.3性能优化技巧四、实战案例:构建离线优先的待办事项应用4.1数据库设计4.2同步策略实现五、常见问题与解决方案5.</div> </li> <li><a href="/article/1950169524384886784.htm" title="【Java Web实战】从零到一打造企业级网上购书网站系统 | 完整开发实录(三)" target="_blank">【Java Web实战】从零到一打造企业级网上购书网站系统 | 完整开发实录(三)</a> <span class="text-muted">笙囧同学</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/%E7%8A%B6%E6%80%81%E6%A8%A1%E5%BC%8F/1.htm">状态模式</a> <div>核心功能设计用户管理系统用户管理是整个系统的基础,我设计了完整的用户生命周期管理:用户注册流程验证失败验证通过验证失败验证通过用户名已存在用户名可用失败成功用户访问注册页面填写注册信息前端表单验证显示错误提示提交到后端后端数据验证返回错误信息用户名唯一性检查提示用户名重复密码加密处理保存用户信息保存成功?显示系统错误注册成功跳转登录页面登录认证机制深度解析我实现了一套企业级的多层次安全认证机制:认</div> </li> <li><a href="/article/1950169526440095744.htm" title="从零到一:打造基于GigaChat AI的艺术创作平台 | 笙囧同学的全栈开发实战" target="_blank">从零到一:打造基于GigaChat AI的艺术创作平台 | 笙囧同学的全栈开发实战</a> <span class="text-muted"></span> <div>作者简介:笙囧同学,中科院计算机大模型方向硕士,全栈开发爱好者联系方式:3251736703@qq.com各大平台账号:笙囧同学座右铭:偷懒是人生进步的阶梯前言在AI技术飞速发展的今天,如何将前沿的大模型技术与实际应用相结合,一直是我们开发者关注的焦点。今天,笙囧同学将带大家从零开始,构建一个基于GigaChatAI的艺术创作平台,实现React前端+Django后端的完整全栈解决方案。这不仅仅是</div> </li> <li><a href="/article/1950164483057971200.htm" title="14.tornado操作之应用Websocket协议实现聊天室功能" target="_blank">14.tornado操作之应用Websocket协议实现聊天室功能</a> <span class="text-muted">孤寒者</span> <a class="tag" taget="_blank" href="/search/Tornado%E6%A1%86%E6%9E%B6%E4%BB%8E%E5%85%A5%E9%97%A8%E5%88%B0%E5%AE%9E%E6%88%98/1.htm">Tornado框架从入门到实战</a><a class="tag" taget="_blank" href="/search/websocket/1.htm">websocket</a><a class="tag" taget="_blank" href="/search/tornado/1.htm">tornado</a><a class="tag" taget="_blank" href="/search/%E8%81%8A%E5%A4%A9%E5%AE%A4%E5%8A%9F%E8%83%BD%E5%AE%9E%E7%8E%B0/1.htm">聊天室功能实现</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a> <div>目录:每篇前言:1.什么是WebSocket(1)定义(2)优点(3)和HTTP对比(4)适用场景2.WebSocket关键方法3.本tornado项目中使用WebSocket(1)准备一个聊天室的页面:第一步:编写视图:第二步:编写接口:(app.py中加入以下接口!)第三步:编写前端页面:测试接口——响应OK!(2)使用WebSocket:(3)聊天室的聊天功能的最终实现:第一步:战前准备第二</div> </li> <li><a href="/article/1950144218282389504.htm" title="为什么学习Web前端一定要掌握JavaScript?" target="_blank">为什么学习Web前端一定要掌握JavaScript?</a> <span class="text-muted">web前端学习指南</span> <div>为什么学习Web前端一定要掌握JavaScript?在前端的世界里,没有什么是JavaScript实现不了的,关于JS有一句话:凡是可以用JavaScript来写的应用,最终都会用JavaScript,JavaScript可运行在所有主要平台的所有主流浏览器上,也可运行在每一个主流操作系统的服务器端上。现如今我们在为网站写任何一个主要功能的时候都需要有懂能够用JavaScript写前端的开发人员。</div> </li> <li><a href="/article/1950143305194991616.htm" title="小架构step系列25:错误码" target="_blank">小架构step系列25:错误码</a> <span class="text-muted">秋千码途</span> <a class="tag" taget="_blank" href="/search/%E6%9E%B6%E6%9E%84/1.htm">架构</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div>1概述一个系统中,可能产生各种各样的错误,对这些错误进行编码。当错误发生时,通过这个错误码就有可能快速判断是什么错误,不一定需要查看代码就可以进行处理,提高问题处理效率。有了统一的错误码,还可以标准化错误信息,方便把错误信息纳入文档管理和对错误信息进行国际化等。没有错误码的管理,开发人员就会按自己的理解处理这些错误。有些直接把堆栈直接反馈到前端页面上,使用看不懂这些信息体验很差,也暴露了堆栈信息有</div> </li> <li><a href="/article/1950140903616212992.htm" title="Java朴实无华按天计划从入门到实战(强化速战版-66天)" target="_blank">Java朴实无华按天计划从入门到实战(强化速战版-66天)</a> <span class="text-muted">岫珩</span> <a class="tag" taget="_blank" href="/search/Java/1.htm">Java</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0/1.htm">学习</a><a class="tag" taget="_blank" href="/search/Java/1.htm">Java</a><a class="tag" taget="_blank" href="/search/%E6%97%B6%E9%97%B4%E5%AE%89%E6%8E%92/1.htm">时间安排</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0%E8%AE%A1%E5%88%92/1.htm">学习计划</a> <div>致敬读者感谢阅读笑口常开生日快乐⬛早点睡觉博主相关博主信息博客首页专栏推荐活动信息文章目录Java朴实无华按天计划从入门到实战(强化速战版-66天)1.基础(18)1.1JavaSE核心(5天)1.2数据库与SQL(5天)1.3前端基础(8天)2.进阶(17天)2.1JavaWeb核心(5天)2.2Mybatis与Spring全家桶(6天)2.3中间件入门(4天)2.4实践项目(2天)3.高阶(1</div> </li> <li><a href="/article/1950132204336115712.htm" title="《跨域资源共享CORS的深层逻辑与前端实践精要》" target="_blank">《跨域资源共享CORS的深层逻辑与前端实践精要》</a> <span class="text-muted"></span> <div>不同源头的资源交互已成为常态,而跨域资源共享(CORS)正是支撑这种交互的隐形架构。现代Web安全体系中平衡开放与防护的精妙设计。理解CORS的深层逻辑,不仅能解决实际开发中的跨域难题,更能触及网络安全与资源流通的核心矛盾,为前端工程师构建稳健的应用提供底层认知支撑。跨域资源共享的诞生,源于网络安全与应用发展的必然冲突。浏览器的同源策略,作为早期网络安全的基石,通过限制不同源文档的交互,有效阻挡了</div> </li> <li><a href="/article/1950131321980383232.htm" title="深入了解 Kubernetes(k8s):从概念到实践" target="_blank">深入了解 Kubernetes(k8s):从概念到实践</a> <span class="text-muted"></span> <div>目录一、k8s核心概念二、k8s的优势三、k8s架构组件控制平面组件节点组件四、k8s+docker运行前后端分离项目的例子1.准备前端项目2.准备后端项目3.创建k8s部署配置文件4.部署应用到k8s集群在当今云计算和容器化技术飞速发展的时代,Kubernetes(简称k8s)已成为容器编排领域的事实标准。无论是互联网巨头、传统企业还是初创公司,都在广泛采用k8s来管理和部署容器化应用。本文将带</div> </li> <li><a href="/article/1950130692448907264.htm" title="Vue CSR 到 Nuxt 3 SSR 迁移:技术实现与问题解决实录" target="_blank">Vue CSR 到 Nuxt 3 SSR 迁移:技术实现与问题解决实录</a> <span class="text-muted">二倍速播放</span> <a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a> <div>1.迁移动机与技术选型1.1CSR架构的局限性基于Vue3和Vite构建的客户端渲染(CSR)单页应用(SPA)提供了良好的开发体验和用户交互流畅性。但是其核心局限在于:搜索引擎优化(SEO):初始HTML响应仅包含一个根div元素,实际内容由JavaScript在浏览器端动态生成。虽然主流搜索引擎(如Google)能够执行部分JavaScript,但其抓取效率和稳定性不如直接获取完整HTML。非</div> </li> <li><a href="/article/1950119224630374400.htm" title="大厂都在用的前端缓存策略,你掌握了吗?" target="_blank">大厂都在用的前端缓存策略,你掌握了吗?</a> <span class="text-muted">AI架构全栈开发实战笔记</span> <a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/%E7%BC%93%E5%AD%98/1.htm">缓存</a><a class="tag" taget="_blank" href="/search/ai/1.htm">ai</a> <div>大厂都在用的前端缓存策略,你掌握了吗?关键词:前端缓存、HTTP缓存、ServiceWorker、CDN缓存、缓存策略、性能优化、浏览器缓存摘要:本文将深入探讨前端开发中常用的缓存策略,从浏览器缓存到ServiceWorker,从HTTP缓存头到CDN缓存,全面解析大厂都在使用的高效缓存技术。通过生动的比喻和实际代码示例,帮助开发者理解并掌握这些提升Web应用性能的关键技术。背景介绍目的和范围本文</div> </li> <li><a href="/article/1950115062781898752.htm" title="26. 什么是雪碧图,作用和原理了解吗" target="_blank">26. 什么是雪碧图,作用和原理了解吗</a> <span class="text-muted">yqcoder</span> <a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E9%9D%A2%E8%AF%95-CSS/1.htm">前端面试-CSS</a><a class="tag" taget="_blank" href="/search/css/1.htm">css</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/html/1.htm">html</a> <div>总结小图合成一张,使用background来使用,减少资源请求一、什么是雪碧图?雪碧图(CSSSprite)是一种前端优化技术,指的是将多个小图标合并成一张大图,通过CSS控制显示其中的某一部分。它常用于网站中图标、按钮等小图较多的场景。二、雪碧图的作用作用说明✅减少HTTP请求次数合并多个图片为一张图,减少请求资源数✅提升页面加载速度尤其在图片较多时效果明显✅避免图片加载闪烁鼠标悬停切换图片时不</div> </li> <li><a href="/article/1950114810557427712.htm" title="12. 什么是事件委托" target="_blank">12. 什么是事件委托</a> <span class="text-muted">yqcoder</span> <a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E9%9D%A2%E8%AF%95-CSS/1.htm">前端面试-CSS</a><a class="tag" taget="_blank" href="/search/css/1.htm">css</a><a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95/1.htm">面试</a> <div>总结事件委托(EventDelegation)是JavaScript中一种重要的事件处理机制,它利用了事件冒泡的特性,将事件的处理程序绑定到父元素或祖先元素上,而不是直接绑定到具体的子元素上。什么是事件委托?事件冒泡:在DOM中,事件通常会从触发元素开始,然后逐级向上冒泡到其父元素、祖先元素,直到window对象。核心思想:事件委托的核心思想是利用事件冒泡机制,在父元素上监听事件,而不是在每个子元</div> </li> <li><a href="/article/1950112039502409728.htm" title="H5UI微信小程序前端框架实战指南" target="_blank">H5UI微信小程序前端框架实战指南</a> <span class="text-muted">ai</span> <div>本文还有配套的精品资源,点击获取简介:H5UI是一个为微信小程序开发设计的前端框架,基于H5技术,提供简洁高效的组件库。框架集成了丰富的UI元素,如按钮、表格、导航栏等,简化了界面布局和交互的实现。通过安装、引入、使用组件和事件绑定四个步骤,开发者可以轻松构建功能齐全的应用。了解性能优化等注意事项对于高效开发同样重要。1.微信小程序前端开发框架介绍微信小程序概述微信小程序是微信官方推出的一种无需下</div> </li> <li><a href="/article/1950104854819041280.htm" title="Ubuntu安装LAMP" target="_blank">Ubuntu安装LAMP</a> <span class="text-muted">L_h1</span> <a class="tag" taget="_blank" href="/search/%E6%B5%8B%E8%AF%95/1.htm">测试</a><a class="tag" taget="_blank" href="/search/ubuntu/1.htm">ubuntu</a><a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a> <div>在安装vim时遇到了一个问题:E:无法获得锁/var/lib/dpkg/lock-frontend-open(11:资源暂时不可用)E:无法获取dpkg前端锁(/var/lib/dpkg/lock-frontend),是否有其他进程正占用它?解决办法:强制解锁sudorm/var/lib/dpkg/lock-frontendsudorm/var/cache/apt/archives/locksud</div> </li> <li><a href="/article/1950104727928762368.htm" title="震惊!DOM变化监控神器MutationObserver,前端开发必知的隐藏武器!" target="_blank">震惊!DOM变化监控神器MutationObserver,前端开发必知的隐藏武器!</a> <span class="text-muted">coding随想</span> <a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/html5/1.htm">html5</a> <div>一、什么是MutationObserver?如果你是一个前端开发者,一定会遇到这样的场景:页面动态加载内容后,某些操作失效了。比如,你写了一个监听按钮点击的代码,但按钮是通过AJAX动态加载的,你的代码根本无法触发。这个时候,你就需要一个“监控哨兵”——MutationObserver,它能实时监听DOM树的变化,帮你捕获那些“暗中作祟”的节点变动。MutationObserver是HTML5引入</div> </li> <li><a href="/article/1950094764498022400.htm" title="Coze Studio 架构拆解:AI Agent 开发平台项目结构全分析" target="_blank">Coze Studio 架构拆解:AI Agent 开发平台项目结构全分析</a> <span class="text-muted">代码简单说</span> <a class="tag" taget="_blank" href="/search/2025%E5%BC%80%E5%8F%91%E5%BF%85%E5%A4%87%28%E9%99%90%E6%97%B6%E7%89%B9%E6%83%A0%29/1.htm">2025开发必备(限时特惠)</a><a class="tag" taget="_blank" href="/search/%E6%9E%B6%E6%9E%84/1.htm">架构</a><a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a><a class="tag" taget="_blank" href="/search/Coze/1.htm">Coze</a><a class="tag" taget="_blank" href="/search/Studio/1.htm">Studio</a><a class="tag" taget="_blank" href="/search/%E6%9E%B6%E6%9E%84/1.htm">架构</a><a class="tag" taget="_blank" href="/search/AI/1.htm">AI</a><a class="tag" taget="_blank" href="/search/Agent/1.htm">Agent</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E5%B9%B3%E5%8F%B0/1.htm">开发平台</a><a class="tag" taget="_blank" href="/search/%E5%85%A8%E6%A0%88/1.htm">全栈</a><a class="tag" taget="_blank" href="/search/AI/1.htm">AI</a><a class="tag" taget="_blank" href="/search/%E5%B7%A5%E7%A8%8B%E5%8C%96/1.htm">工程化</a><a class="tag" taget="_blank" href="/search/%E5%9B%BE%E8%A7%A3%E6%9E%B6%E6%9E%84/1.htm">图解架构</a> <div>CozeStudio架构拆解:AIAgent开发平台项目结构全分析标签:CozeStudio项目架构、领域驱动设计DDD、全栈开发规范、Hertz框架、前后端协作、云原生容器、前端测试、IDL接口设计、微服务解耦、AI开发平台源码分析在最近研究AIAgent开发平台的过程中,我深入分析了刚刚开源的CozeStudio项目。这套系统是国内少有的开源全栈AI工程化项目,代码整洁、架构先进,特别是它基于</div> </li> <li><a href="/article/1950075480849838080.htm" title="关于前端的性能优化" target="_blank">关于前端的性能优化</a> <span class="text-muted"></span> <div>性能优化主要涵盖了以下四个方面:(tip:仅代表个人总结,如有不当,还希望看到的大佬多多指示)减少网络请求:合并文件、使用CDN、启用缓存。优化资源加载:代码分割、懒加载、图片压缩。提升渲染性能:减少重绘回流、防抖节流、使用WebWorker。监控和迭代:定期使用工具检测性能,持续优化。一、网络层面优化减少HTTP请求合并文件:将多个CSS或JavaScript文件合并成一个,减少请求次数。使用C</div> </li> <li><a href="/article/1950074093608955904.htm" title="时间组件库Day.js那些事" target="_blank">时间组件库Day.js那些事</a> <span class="text-muted">前端小白花</span> <a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/ecmascript/1.htm">ecmascript</a> <div>一、简介1.什么是Day.jsDay.js是一个轻量级,易于使用的JavaScript日期库,提供了强大的日期和时间处理功能,与Moment.js的API设计相似,但具有更高的性能和更小的体积。Day.js官网https://day.js.org/docs/zh-CN/installation/installation2.优势a.特点轻量级:Dayjs的压缩后大小只有2KB左右,远小于Moment</div> </li> <li><a href="/article/1950071066281963520.htm" title="JavaScript正则表达式去除括号但保留内容与去除括号与内容" target="_blank">JavaScript正则表达式去除括号但保留内容与去除括号与内容</a> <span class="text-muted">Selicens</span> <a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F/1.htm">正则表达式</a> <div>项目上碰到一个需求,是取多个递增文件的文件名,类似于test(1).txt、test(2).txt,但是不需要括号,只要test1、test2这种格式,最开始想到的办法就是js里的replace替换,先上一个比较笨但是也能实现效果的例子letname="test(1).txt"letdata=name.split('.')[0].replace('(','').replace(')','')con</div> </li> <li><a href="/article/1950059723604684800.htm" title="linux网卡显示未知未托管,linux有线网络显示设备未托管" target="_blank">linux网卡显示未知未托管,linux有线网络显示设备未托管</a> <span class="text-muted"></span> <div>NetworkManagerNetworkManager是为了使网络配置尽可能简单而开发的网络管理软件包,如果使用DHCP,NetworkManager会替换默认的路由表、从DHCP服务器获取IP地址并根据情况设置域名服务器,NetworkManager的目标是使网络能够开箱即用。NetworkManager由两部分组成:一个以超级用户运行的守护进程(network-manager);一个前端管理</div> </li> <li><a href="/article/1950053798433058816.htm" title="页面开发样式和布局入门:Vite + Vue 3 + Less" target="_blank">页面开发样式和布局入门:Vite + Vue 3 + Less</a> <span class="text-muted"></span> <div>页面开发样式和布局入门:Vite+Vue3+Less引言在现代前端开发中,样式和布局是页面开发的核心部分。随着技术的不断发展,Vite、Vue3和Less等工具和框架的出现,使得前端开发变得更加高效和灵活。然而,尽管这些工具和框架提供了强大的功能,但在实际开发中仍然会遇到各种样式和布局的问题。本文将结合Vite、Vue3和Less,详细介绍在页面开发中常见的样式和布局问题,并提供解决方案和最佳实践</div> </li> <li><a href="/article/1950046229840850944.htm" title="推客系统小程序机构版开发上线全攻略(2025年最新版)" target="_blank">推客系统小程序机构版开发上线全攻略(2025年最新版)</a> <span class="text-muted">vx_qutudy</span> <a class="tag" taget="_blank" href="/search/%E6%8E%A8%E5%AE%A2%E5%B0%8F%E7%A8%8B%E5%BA%8F/1.htm">推客小程序</a><a class="tag" taget="_blank" href="/search/%E6%8E%A8%E5%AE%A2%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91/1.htm">推客系统开发</a><a class="tag" taget="_blank" href="/search/%E6%8E%A8%E5%AE%A2%E7%B3%BB%E7%BB%9F%E6%BA%90%E7%A0%81/1.htm">推客系统源码</a> <div>一、开发前准备:筑牢基础,合规先行1.1注册与认证账号注册:登录微信公众平台注册小程序账号,选择“机构版”类型,获取唯一AppID。资质认证:基础资质:企业营业执照、法人身份证、对公账户信息。特殊资质:涉及支付功能:需办理《增值电信业务经营许可证》(ICP证)。涉及教育/医疗内容:需《互联网信息服务许可证》或相关行业资质。1.2技术选型:高效与扩展并重模块推荐方案前端框架微信原生框架(WXML+W</div> </li> <li><a href="/article/1950042324155297792.htm" title="网络安全第14集" target="_blank">网络安全第14集</a> <span class="text-muted">不灭锦鲤</span> <a class="tag" taget="_blank" href="/search/web%E5%AE%89%E5%85%A8/1.htm">web安全</a><a class="tag" taget="_blank" href="/search/%E5%AE%89%E5%85%A8/1.htm">安全</a> <div>前言:小迪安全14集,这集重点内容:0、什么是js渗透测试?在javascript中也存在变量和函数,存在可控变量和函数就有可能存在在漏洞,js开发的web应用和php、java开发的区别是,js能看得到的源代码,php看不到,但是风险就是未授权访问、配置信息泄露(加密算法、key秘钥等),源代码看得到,存在更多的url泄露,从而可能会出现未授权访问,从url,前提:web应用可以采用前端语言或后</div> </li> <li><a href="/article/1950040812469415936.htm" title="25年不倒的“犀牛书“:为什么《JavaScript权威指南第7版》仍是程序员的案头圣经?" target="_blank">25年不倒的“犀牛书“:为什么《JavaScript权威指南第7版》仍是程序员的案头圣经?</a> <span class="text-muted">阿蒙Armon</span> <a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/ecmascript/1.htm">ecmascript</a> <div>25年不倒的"犀牛书":为什么《JavaScript权威指南第7版》仍是程序员的案头圣经?当一本技术书能连续畅销25年,历经7次迭代仍稳坐领域第一梯队,它必然藏着超越时代的硬实力。《JavaScript权威指南(原书第7版)》就是这样一部传奇——豆瓣9.4分的封神之作,程序员口中的"犀牛书",从网景时代到ES2020,它始终是JavaScript开发者的终极参考书。如果你还在为原型链、闭包、异步编</div> </li> <li><a href="/article/75.htm" title="knob UI插件使用" target="_blank">knob UI插件使用</a> <span class="text-muted">换个号韩国红果果</span> <a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a><a class="tag" taget="_blank" href="/search/jsonp/1.htm">jsonp</a><a class="tag" taget="_blank" href="/search/knob/1.htm">knob</a> <div>图形是用canvas绘制的 js代码 var paras = { max:800, min:100, skin:'tron',//button type thickness:.3,//button width width:'200',//define canvas width.,canvas height displayInput:'tr</div> </li> <li><a href="/article/202.htm" title="Android+Jquery Mobile学习系列(5)-SQLite数据库" target="_blank">Android+Jquery Mobile学习系列(5)-SQLite数据库</a> <span class="text-muted">白糖_</span> <a class="tag" taget="_blank" href="/search/JQuery+Mobile/1.htm">JQuery Mobile</a> <div>目录导航   SQLite是轻量级的、嵌入式的、关系型数据库,目前已经在iPhone、Android等手机系统中使用,SQLite可移植性好,很容易使用,很小,高效而且可靠。   因为Android已经集成了SQLite,所以开发人员无需引入任何JAR包,而且Android也针对SQLite封装了专属的API,调用起来非常快捷方便。   我也是第一次接触S</div> </li> <li><a href="/article/329.htm" title="impala-2.1.2-CDH5.3.2" target="_blank">impala-2.1.2-CDH5.3.2</a> <span class="text-muted">dayutianfei</span> <a class="tag" taget="_blank" href="/search/impala/1.htm">impala</a> <div>最近在整理impala编译的东西,简单记录几个要点: 根据官网的信息(https://github.com/cloudera/Impala/wiki/How-to-build-Impala): 1. 首次编译impala,推荐使用命令: ${IMPALA_HOME}/buildall.sh -skiptests -build_shared_libs -format 2.仅编译BE ${I</div> </li> <li><a href="/article/456.htm" title="求二进制数中1的个数" target="_blank">求二进制数中1的个数</a> <span class="text-muted">周凡杨</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/%E4%BA%8C%E8%BF%9B%E5%88%B6/1.htm">二进制</a> <div>解法一: 对于一个正整数如果是偶数,该数的二进制数的最后一位是 0 ,反之若是奇数,则该数的二进制数的最后一位是 1 。因此,可以考虑利用位移、判断奇偶来实现。   public int bitCount(int x){ int count = 0; while(x!=0){ if(x%2!=0){ /</div> </li> <li><a href="/article/583.htm" title="spring中hibernate及事务配置" target="_blank">spring中hibernate及事务配置</a> <span class="text-muted">g21121</span> <a class="tag" taget="_blank" href="/search/Hibernate/1.htm">Hibernate</a> <div>hibernate的sessionFactory配置: <!-- hibernate sessionFactory配置 --> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <</div> </li> <li><a href="/article/710.htm" title="log4j.properties 使用" target="_blank">log4j.properties 使用</a> <span class="text-muted">510888780</span> <a class="tag" taget="_blank" href="/search/log4j/1.htm">log4j</a> <div>log4j.properties 使用 一.参数意义说明 输出级别的种类 ERROR、WARN、INFO、DEBUG ERROR 为严重错误 主要是程序的错误 WARN 为一般警告,比如session丢失 INFO 为一般要显示的信息,比如登录登出 DEBUG 为程序的调试信息 配置日志信息输出目的地 log4j.appender.appenderName = fully.qua</div> </li> <li><a href="/article/837.htm" title="Spring mvc-jfreeChart柱图(2)" target="_blank">Spring mvc-jfreeChart柱图(2)</a> <span class="text-muted">布衣凌宇</span> <a class="tag" taget="_blank" href="/search/jfreechart/1.htm">jfreechart</a> <div>上一篇中生成的图是静态的,这篇将按条件进行搜索,并统计成图表,左面为统计图,右面显示搜索出的结果。 第一步:导包 第二步;配置web.xml(上一篇有代码) 建BarRenderer类用于柱子颜色 import java.awt.Color; import java.awt.Paint; import org.jfree.chart.renderer.category.BarR</div> </li> <li><a href="/article/964.htm" title="我的spring学习笔记14-容器扩展点之PropertyPlaceholderConfigurer" target="_blank">我的spring学习笔记14-容器扩展点之PropertyPlaceholderConfigurer</a> <span class="text-muted">aijuans</span> <a class="tag" taget="_blank" href="/search/Spring3/1.htm">Spring3</a> <div>PropertyPlaceholderConfigurer是个bean工厂后置处理器的实现,也就是BeanFactoryPostProcessor接口的一个实现。关于BeanFactoryPostProcessor和BeanPostProcessor类似。我会在其他地方介绍。 PropertyPlaceholderConfigurer可以将上下文(配置文件)中的属性值放在另一个单独的标准java</div> </li> <li><a href="/article/1091.htm" title="maven 之 cobertura 简单使用" target="_blank">maven 之 cobertura 简单使用</a> <span class="text-muted">antlove</span> <a class="tag" taget="_blank" href="/search/maven/1.htm">maven</a><a class="tag" taget="_blank" href="/search/test/1.htm">test</a><a class="tag" taget="_blank" href="/search/unit/1.htm">unit</a><a class="tag" taget="_blank" href="/search/cobertura/1.htm">cobertura</a><a class="tag" taget="_blank" href="/search/report/1.htm">report</a> <div>1. 创建一个maven项目 2. 创建com.CoberturaStart.java package com; public class CoberturaStart { public void helloEveryone(){ System.out.println("=================================================</div> </li> <li><a href="/article/1218.htm" title="程序的执行顺序" target="_blank">程序的执行顺序</a> <span class="text-muted">百合不是茶</span> <a class="tag" taget="_blank" href="/search/JAVA%E6%89%A7%E8%A1%8C%E9%A1%BA%E5%BA%8F/1.htm">JAVA执行顺序</a> <div>      刚在看java核心技术时发现对java的执行顺序不是很明白了,百度一下也没有找到适合自己的资料,所以就简单的回顾一下吧   代码如下;     经典的程序执行面试题 //关于程序执行的顺序 //例如: //定义一个基类 public class A(){ public A(</div> </li> <li><a href="/article/1345.htm" title="设置session失效的几种方法" target="_blank">设置session失效的几种方法</a> <span class="text-muted">bijian1013</span> <a class="tag" taget="_blank" href="/search/web.xml/1.htm">web.xml</a><a class="tag" taget="_blank" href="/search/session%E5%A4%B1%E6%95%88/1.htm">session失效</a><a class="tag" taget="_blank" href="/search/%E7%9B%91%E5%90%AC%E5%99%A8/1.htm">监听器</a> <div>在系统登录后,都会设置一个当前session失效的时间,以确保在用户长时间不与服务器交互,自动退出登录,销毁session。具体设置很简单,方法有三种:(1)在主页面或者公共页面中加入:session.setMaxInactiveInterval(900);参数900单位是秒,即在没有活动15分钟后,session将失效。这里要注意这个session设置的时间是根据服务器来计算的,而不是客户端。所</div> </li> <li><a href="/article/1472.htm" title="java jvm常用命令工具" target="_blank">java jvm常用命令工具</a> <span class="text-muted">bijian1013</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/jvm/1.htm">jvm</a> <div>一.概述         程序运行中经常会遇到各种问题,定位问题时通常需要综合各种信息,如系统日志、堆dump文件、线程dump文件、GC日志等。通过虚拟机监控和诊断工具可以帮忙我们快速获取、分析需要的数据,进而提高问题解决速度。 本文将介绍虚拟机常用监控和问题诊断命令工具的使用方法,主要包含以下工具:       &nbs</div> </li> <li><a href="/article/1599.htm" title="【Spring框架一】Spring常用注解之Autowired和Resource注解" target="_blank">【Spring框架一】Spring常用注解之Autowired和Resource注解</a> <span class="text-muted">bit1129</span> <a class="tag" taget="_blank" href="/search/Spring%E5%B8%B8%E7%94%A8%E6%B3%A8%E8%A7%A3/1.htm">Spring常用注解</a> <div>Spring自从2.0引入注解的方式取代XML配置的方式来做IOC之后,对Spring一些常用注解的含义行为一直处于比较模糊的状态,写几篇总结下Spring常用的注解。本篇包含的注解有如下几个: Autowired Resource Component Service Controller Transactional 根据它们的功能、目的,可以分为三组,Autow</div> </li> <li><a href="/article/1726.htm" title="mysql 操作遇到safe update mode问题" target="_blank">mysql 操作遇到safe update mode问题</a> <span class="text-muted">bitray</span> <a class="tag" taget="_blank" href="/search/update/1.htm">update</a> <div>    我并不知道出现这个问题的实际原理,只是通过其他朋友的博客,文章得知的一个解决方案,目前先记录一个解决方法,未来要是真了解以后,还会继续补全.     在mysql5中有一个safe update mode,这个模式让sql操作更加安全,据说要求有where条件,防止全表更新操作.如果必须要进行全表操作,我们可以执行 SET</div> </li> <li><a href="/article/1853.htm" title="nginx_perl试用" target="_blank">nginx_perl试用</a> <span class="text-muted">ronin47</span> <a class="tag" taget="_blank" href="/search/nginx_perl%E8%AF%95%E7%94%A8/1.htm">nginx_perl试用</a> <div>因为空闲时间比较多,所以在CPAN上乱翻,看到了nginx_perl这个项目(原名Nginx::Engine),现在托管在github.com上。地址见:https://github.com/zzzcpan/nginx-perl 这个模块的目的,是在nginx内置官方perl模块的基础上,实现一系列异步非阻塞的api。用connector/writer/reader完成类似proxy的功能(这里</div> </li> <li><a href="/article/1980.htm" title="java-63-在字符串中删除特定的字符" target="_blank">java-63-在字符串中删除特定的字符</a> <span class="text-muted">bylijinnan</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div> public class DeleteSpecificChars { /** * Q 63 在字符串中删除特定的字符 * 输入两个字符串,从第一字符串中删除第二个字符串中所有的字符。 * 例如,输入”They are students.”和”aeiou”,则删除之后的第一个字符串变成”Thy r stdnts.” */ public static voi</div> </li> <li><a href="/article/2107.htm" title="EffectiveJava--创建和销毁对象" target="_blank">EffectiveJava--创建和销毁对象</a> <span class="text-muted">ccii</span> <a class="tag" taget="_blank" href="/search/%E5%88%9B%E5%BB%BA%E5%92%8C%E9%94%80%E6%AF%81%E5%AF%B9%E8%B1%A1/1.htm">创建和销毁对象</a> <div>本章内容: 1. 考虑用静态工厂方法代替构造器 2. 遇到多个构造器参数时要考虑用构建器(Builder模式) 3. 用私有构造器或者枚举类型强化Singleton属性 4. 通过私有构造器强化不可实例化的能力 5. 避免创建不必要的对象 6. 消除过期的对象引用 7. 避免使用终结方法 1. 考虑用静态工厂方法代替构造器     类可以通过</div> </li> <li><a href="/article/2234.htm" title="[宇宙时代]四边形理论与光速飞行" target="_blank">[宇宙时代]四边形理论与光速飞行</a> <span class="text-muted">comsci</span> <div>   从四边形理论来推论 为什么光子飞船必须获得星光信号才能够进行光速飞行?    一组星体组成星座  向空间辐射一组由复杂星光信号组成的辐射频带,按照四边形-频率假说  一组频率就代表一个时空的入口    那么这种由星光信号组成的辐射频带就代表由这些星体所控制的时空通道,该时空通道在三维空间的投影是一</div> </li> <li><a href="/article/2361.htm" title="ubuntu server下python脚本迁移数据" target="_blank">ubuntu server下python脚本迁移数据</a> <span class="text-muted">cywhoyi</span> <a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/Kettle/1.htm">Kettle</a><a class="tag" taget="_blank" href="/search/pymysql/1.htm">pymysql</a><a class="tag" taget="_blank" href="/search/cx_Oracle/1.htm">cx_Oracle</a><a class="tag" taget="_blank" href="/search/ubuntu+server/1.htm">ubuntu server</a> <div>因为是在Ubuntu下,所以安装python、pip、pymysql等都极其方便,sudo apt-get install pymysql, 但是在安装cx_Oracle(连接oracle的模块)出现许多问题,查阅相关资料,发现这边文章能够帮我解决,希望大家少走点弯路。http://www.tbdazhe.com/archives/602 1.安装python 2.安装pip、pymysql</div> </li> <li><a href="/article/2488.htm" title="Ajax正确但是请求不到值解决方案" target="_blank">Ajax正确但是请求不到值解决方案</a> <span class="text-muted">dashuaifu</span> <a class="tag" taget="_blank" href="/search/Ajax/1.htm">Ajax</a><a class="tag" taget="_blank" href="/search/async/1.htm">async</a> <div>Ajax正确但是请求不到值解决方案   解决方案:1 .     async: false ,    2.     设置延时执行js里的ajax或者延时后台java方法!!!!!!!   例如:   $.ajax({     &</div> </li> <li><a href="/article/2615.htm" title="windows安装配置php+memcached" target="_blank">windows安装配置php+memcached</a> <span class="text-muted">dcj3sjt126com</span> <a class="tag" taget="_blank" href="/search/PHP/1.htm">PHP</a><a class="tag" taget="_blank" href="/search/Install/1.htm">Install</a><a class="tag" taget="_blank" href="/search/memcache/1.htm">memcache</a> <div>Windows下Memcached的安装配置方法 1、将第一个包解压放某个盘下面,比如在c:\memcached。 2、在终端(也即cmd命令界面)下输入 'c:\memcached\memcached.exe -d install' 安装。 3、再输入: 'c:\memcached\memcached.exe -d start' 启动。(需要注意的: 以后memcached将作为windo</div> </li> <li><a href="/article/2742.htm" title="iOS开发学习路径的一些建议" target="_blank">iOS开发学习路径的一些建议</a> <span class="text-muted">dcj3sjt126com</span> <a class="tag" taget="_blank" href="/search/ios/1.htm">ios</a> <div>iOS论坛里有朋友要求回答帖子,帖子的标题是: 想学IOS开发高阶一点的东西,从何开始,然后我吧啦吧啦回答写了很多。既然敲了那么多字,我就把我写的回复也贴到博客里来分享,希望能对大家有帮助。欢迎大家也到帖子里讨论和分享,地址:http://bbs.csdn.net/topics/390920759   下面是我回复的内容:   结合自己情况聊下iOS学习建议,</div> </li> <li><a href="/article/2869.htm" title="Javascript闭包概念" target="_blank">Javascript闭包概念</a> <span class="text-muted">fanfanlovey</span> <a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a><a class="tag" taget="_blank" href="/search/%E9%97%AD%E5%8C%85/1.htm">闭包</a> <div>1.参考资料 http://www.jb51.net/article/24101.htm http://blog.csdn.net/yn49782026/article/details/8549462 2.内容概述 要理解闭包,首先需要理解变量作用域问题 内部函数可以饮用外面全局变量 var n=999;   functio</div> </li> <li><a href="/article/2996.htm" title="yum安装mysql5.6" target="_blank">yum安装mysql5.6</a> <span class="text-muted">haisheng</span> <a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a> <div>1、安装http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm   2、yum install mysql   3、yum install mysql-server   4、vi /etc/my.cnf   添加character_set_server=utf8</div> </li> <li><a href="/article/3123.htm" title="po/bo/vo/dao/pojo的详介" target="_blank">po/bo/vo/dao/pojo的详介</a> <span class="text-muted">IT_zhlp80</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/BO/1.htm">BO</a><a class="tag" taget="_blank" href="/search/VO/1.htm">VO</a><a class="tag" taget="_blank" href="/search/DAO/1.htm">DAO</a><a class="tag" taget="_blank" href="/search/POJO/1.htm">POJO</a><a class="tag" taget="_blank" href="/search/po/1.htm">po</a> <div>    JAVA几种对象的解释 PO:persistant object持久对象,可以看成是与数据库中的表相映射的java对象。最简单的PO就是对应数据库中某个表中的一条记录,多个记录可以用PO的集合。PO中应该不包含任何对数据库的操作. VO:value object值对象。通常用于业务层之间的数据传递,和PO一样也是仅仅包含数据而已。但应是抽象出的业务对象,可</div> </li> <li><a href="/article/3250.htm" title="java设计模式" target="_blank">java设计模式</a> <span class="text-muted">kerryg</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/1.htm">设计模式</a> <div>设计模式的分类:    一、 设计模式总体分为三大类: 1、创建型模式(5种):工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式。 2、结构型模式(7种):适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模式,享元模式。 3、行为型模式(11种):策略模式,模版方法模式,观察者模式,迭代子模式,责任链模式,命令模式,备忘录模式,状态模式,访问者</div> </li> <li><a href="/article/3377.htm" title="[1]CXF3.1整合Spring开发webservice——helloworld篇" target="_blank">[1]CXF3.1整合Spring开发webservice——helloworld篇</a> <span class="text-muted">木头.java</span> <a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/webservice/1.htm">webservice</a><a class="tag" taget="_blank" href="/search/CXF/1.htm">CXF</a> <div>Spring 版本3.2.10 CXF 版本3.1.1 项目采用MAVEN组织依赖jar 我这里是有parent的pom,为了简洁明了,我直接把所有的依赖都列一起了,所以都没version,反正上面已经写了版本 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="ht</div> </li> <li><a href="/article/3504.htm" title="Google 工程师亲授:菜鸟开发者一定要投资的十大目标" target="_blank">Google 工程师亲授:菜鸟开发者一定要投资的十大目标</a> <span class="text-muted">qindongliang1922</span> <a class="tag" taget="_blank" href="/search/%E5%B7%A5%E4%BD%9C/1.htm">工作</a><a class="tag" taget="_blank" href="/search/%E6%84%9F%E6%82%9F/1.htm">感悟</a><a class="tag" taget="_blank" href="/search/%E4%BA%BA%E7%94%9F/1.htm">人生</a> <div>身为软件开发者,有什么是一定得投资的? Google 软件工程师 Emanuel Saringan 整理了十项他认为必要的投资,第一项就是身体健康,英文与数学也都是必备能力吗?来看看他怎么说。(以下文字以作者第一人称撰写)) 你的健康 无疑地,软件开发者是世界上最久坐不动的职业之一。 每天连坐八到十六小时,休息时间只有一点点,绝对会让你的鲔鱼肚肆无忌惮的生长。肥胖容易扩大罹患其他疾病的风险,</div> </li> <li><a href="/article/3631.htm" title="linux打开最大文件数量1,048,576" target="_blank">linux打开最大文件数量1,048,576</a> <span class="text-muted">tianzhihehe</span> <a class="tag" taget="_blank" href="/search/c/1.htm">c</a><a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a> <div>File descriptors are represented by the C int type. Not using a special type is often  considered odd, but is, historically, the Unix way. Each Linux process has a maximum number of files th</div> </li> <li><a href="/article/3758.htm" title="java语言中PO、VO、DAO、BO、POJO几种对象的解释" target="_blank">java语言中PO、VO、DAO、BO、POJO几种对象的解释</a> <span class="text-muted">衞酆夼</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/VO/1.htm">VO</a><a class="tag" taget="_blank" href="/search/BO/1.htm">BO</a><a class="tag" taget="_blank" href="/search/POJO/1.htm">POJO</a><a class="tag" taget="_blank" href="/search/po/1.htm">po</a> <div>PO:persistant object持久对象 最形象的理解就是一个PO就是数据库中的一条记录。好处是可以把一条记录作为一个对象处理,可以方便的转为其它对象。可以看成是与数据库中的表相映射的java对象。最简单的PO就是对应数据库中某个表中的一条记录,多个记录可以用PO的集合。PO中应该不包含任何对数据库的操作。 BO:business object业务对象 封装业务逻辑的java对象</div> </li> </ul> </div> </div> </div> <div> <div class="container"> <div class="indexes"> <strong>按字母分类:</strong> <a href="/tags/A/1.htm" target="_blank">A</a><a href="/tags/B/1.htm" target="_blank">B</a><a href="/tags/C/1.htm" target="_blank">C</a><a href="/tags/D/1.htm" target="_blank">D</a><a href="/tags/E/1.htm" target="_blank">E</a><a href="/tags/F/1.htm" target="_blank">F</a><a href="/tags/G/1.htm" target="_blank">G</a><a href="/tags/H/1.htm" target="_blank">H</a><a href="/tags/I/1.htm" target="_blank">I</a><a href="/tags/J/1.htm" target="_blank">J</a><a href="/tags/K/1.htm" target="_blank">K</a><a href="/tags/L/1.htm" target="_blank">L</a><a href="/tags/M/1.htm" target="_blank">M</a><a href="/tags/N/1.htm" target="_blank">N</a><a href="/tags/O/1.htm" target="_blank">O</a><a href="/tags/P/1.htm" target="_blank">P</a><a href="/tags/Q/1.htm" target="_blank">Q</a><a href="/tags/R/1.htm" target="_blank">R</a><a href="/tags/S/1.htm" target="_blank">S</a><a href="/tags/T/1.htm" target="_blank">T</a><a href="/tags/U/1.htm" target="_blank">U</a><a href="/tags/V/1.htm" target="_blank">V</a><a href="/tags/W/1.htm" target="_blank">W</a><a href="/tags/X/1.htm" target="_blank">X</a><a href="/tags/Y/1.htm" target="_blank">Y</a><a href="/tags/Z/1.htm" target="_blank">Z</a><a href="/tags/0/1.htm" target="_blank">其他</a> </div> </div> </div> <footer id="footer" class="mb30 mt30"> <div class="container"> <div class="footBglm"> <a target="_blank" href="/">首页</a> - <a target="_blank" href="/custom/about.htm">关于我们</a> - <a target="_blank" href="/search/Java/1.htm">站内搜索</a> - <a target="_blank" href="/sitemap.txt">Sitemap</a> - <a target="_blank" href="/custom/delete.htm">侵权投诉</a> </div> <div class="copyright">版权所有 IT知识库 CopyRight © 2000-2050 E-COM-NET.COM , All Rights Reserved. <!-- <a href="https://beian.miit.gov.cn/" rel="nofollow" target="_blank">京ICP备09083238号</a><br>--> </div> </div> </footer> <!-- 代码高亮 --> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shCore.js"></script> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shLegacy.js"></script> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shAutoloader.js"></script> <link type="text/css" rel="stylesheet" href="/static/syntaxhighlighter/styles/shCoreDefault.css"/> <script type="text/javascript" src="/static/syntaxhighlighter/src/my_start_1.js"></script> </body> </html>