搜尋
首頁web前端js教程從路由開始深入理解react-router 4.0源碼

從路由開始深入理解react-router 4.0源碼

Sep 18, 2018 pm 02:35 PM
html5javascript

這篇文章帶給大家的內容是關於從路由開始深入理解react-router 4.0源碼,有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

react-router等前端路由的原理大致相同,可以實現無刷新的條件下切換顯示不同的頁面。路由的本質就是頁面的URL發生改變時,頁面的顯示結果可以根據URL的變化而變化,但是頁面不會刷新。透過前端路由可以實現單頁(SPA)應用,本文首先從前端路由的原理出發,詳細介紹了前端路由原理的變遷。接著從react-router4.0的源碼出發,深入理解react-router4.0是如何實現前端路由的。

  • 透過Hash實作前端路由

  • 透過H5的history實作前端路由

  • React- router4.0的使用

  • React-router4.0源碼分析

一、透過Hash實作前端路由

#1 、hash的原理

  早期的前端路由是透過hash來實現的:

改變url的hash值是不會刷新頁面的。

  因此可以透過hash來實現前端路由,從而實現無刷新的效果。 hash屬性位於location物件中,在目前頁面中,可以透過:

window.location.hash='edit'

來實現改變目前url的hash值。執行上述的hash賦值後,頁面的url改變。

賦值前:http://localhost:3000
賦值後:http://localhost:3000/#edit

在url中多了以#結尾的hash值,但是賦值前後雖然頁面的hash值改變導致頁面完整的url改變了,但是頁面是不會刷新的。此外,還有一個名為hashchange的事件,可以監聽hash的變化,我們可以透過下面兩種方式來監聽hash的變化:

window.onhashchange=function(event){
   console.log(event);
}
window.addEventListener('hashchange',function(event){
   console.log(event);
})

當hash值改變時,輸出一個HashChangeEvent。此HashChangeEvent的具體值為:

{isTrusted: true, oldURL: "http://localhost:3000/", newURL:   "http://localhost:3000/#teg", type: "hashchange".....}

  有了監聽事件,且改變hash頁面不刷新,這樣我們就可以在監聽事件的回調函數中,執行我們展示和隱藏不同UI顯示的功能,從而實現前端路由。

此外,除了可以透過window.location.hash來改變目前頁面的hash值外,還可以透過html的a標籤來實現:

<a>edit</a>

2、hash的缺點

hash的兼容性較好,因此在早期的前端路由中大量的採用,但是使用hash也有很多缺點。

  • 搜尋引擎對有hash的頁面不友善

  • #有hash的頁面內難以追蹤使用者行為

#二、透過history實作前端路由

HTML5的History接口,History物件是一個底層接口,不繼承於任何的介面。 History介面允許我們操作瀏覽器會話歷史記錄。

(1)History的屬性和方法

History提供了一些屬性和方法。

History的屬性:

  • History.length: 傳回在會話歷史中有多少筆記錄,包含了目前會話頁面。另外如果開啟新的Tab,那麼這個length的值為1

  • History.state:

##儲存了會出發popState事件的方法,所傳遞過來的屬性物件(後面會在pushState和replaceState方法中詳細的介紹)

#History方法:

  • History.back(): 傳回瀏覽器會話歷史中的上一頁,跟瀏覽器的回退按鈕功能相同

  • History.forward():指向瀏覽器會話歷史記錄中的下一頁,跟瀏覽器的前進按鈕相同

  • History.go(): 可以跳到瀏覽器會話歷史中的指定的某一個記錄頁

  • History.pushState():pushState可以將給定的資料壓入到瀏覽器會話歷史棧中,該方法接收3個參數,對象,title和一串url。 pushState後面會改變當前頁面url,但是不會伴隨著刷新

  • History.replaceState():replaceState將當前的會話頁面的url替換成指定的數據,replaceState後也會改變目前頁面的url,但是也不會刷新頁面。

上面的方法中,pushState和repalce的相同點:

就是都會改變目前頁面顯示的url,但都不會刷新頁面。

不同點:

pushState是壓入瀏覽器的會話歷史堆疊中,會使得History.length加1,而replaceState是取代目前的這條會話歷史,因此不會增加History.length.

(2)BOM物件history

history在瀏覽器的BOM物件模型中的重要屬性,history完全繼承了History接口,因此擁有History中的所有的屬性和方法。

這裡我們主要來看看history.length屬性以及history.pushState、history.replaceState方法。

  • history.pushState(stateObj,title,url) or history.replaceState(stateObj,title,url)

#pushState和replaceState接受3個參數,分別為state對象,title標題,改變的url。

window.history.pushState({foo:'bar'}, "page 2", "bar.html");

此时,当前的url变为:

执行上述方法前:http://localhost:3000
执行上述方法后:http://localhost:3000/bar.html

如果我们输出window.history.state:

console.log(window.history.state);
// {foo:'bar'}

window.history.state就是我们pushState的第一个对象参数。

  • history.replaceState()方法不会改变hitroy的长度

    console.log(window.history.length);
    window.history.replaceState({foo:'bar'}, "page 2", "bar.html");
    console.log(window.history.length);

上述前后两次输出的window.history.length是相等的。

此外。

每次触发history.back()或者浏览器的后退按钮等,会触发一个popstate事件,这个事件在后退或者前进的时候发生:

window.onpopstate=function(event){

}

注意:
history.pushState和history.replaceState方法并不会触发popstate事件。

如果用history做为路由的基础,那么需要用到的是history.pushState和history.replaceState,在不刷新的情况下可以改变url的地址,且如果页面发生回退back或者forward时,会触发popstate事件。

hisory为依据来实现路由的优点:

  • 对搜索引擎友好

  • 方便统计用户行为

缺点:

  • 兼容性不如hash

  • 需要后端做相应的配置,否则直接访问子页面会出现404错误

三、React-router4.0的使用

了解了前端路由实现的原理之后,下面来介绍一下React-router4.0。在React-router4.0的代码库中,根据使用场景包含了以下几个独立的包:

  • react-router : react-router4.0的核心代码

  • react-router-dom : 构建网页应用,存在DOM对象场景下的核心包

  • react-router-native : 适用于构建react-native应用

  • react-router-config : 配置静态路由

  • react-router-redux : 结合redux来配置路由,已废弃,不推荐使用。

在react-router4.0中,遵循Just Component的设计理念:

所提供的API都是以组件的形式给出。

比如BrowserRouter、Router、Link、Switch等API都是以组件的形式来使用。

1、React-router-dom常用的组件API

下面我们以React-router4.0中的React-router-dom包来介绍常用的BrowserRouter、HashRouter、Link和Router等。

(1)  <browserrouter></browserrouter>

组件包裹整个App系统后,就是通过html5的history来实现无刷新条件下的前端路由。

组件具有以下几个属性:

  • basename: string  这个属性,是为当前的url再增加名为basename的值的子目录。

     <browserrouter></browserrouter>

如果设置了basename属性,那么此时的:

http://localhost:3000 和 http://localhost:3000/test  表示的是同一个地址,渲染的内容相同。

  • getUserConfirmation: func 这个属性,用于确认导航的功能。默认使用window.confirm

  • forceRefresh: bool 默认为false,表示改变路由的时候页面不会重新刷新,如果当前浏览器不支持history,那么当forceRefresh设置为true的时候,此时每次去改变url都会重新刷新整个页面。

  • keyLength: number 表示location的key属性的长度,在react-router中每个url下都有为一个location与其对应,并且每一个url的location的key值都不相同,这个属性一般都使用默认值,设置的意义不大。

  • children: node children的属性必须是一个ReactNode节点,表示唯一渲染一个元素。

对应的是,使用url中的hash属性来保证不重新刷新的情况下同时渲染页面。

(2)  <route></route>

组件十分重要, 做的事情就是匹配相应的location中的地址,匹配成功后渲染对应的组件。下面我们来看中的属性。

首先来看如何执行匹配,决定地址匹配的属性:

  • path:当location中的url改变后,会与Route中的path属性做匹配,path决定了与路由或者url相关的渲染效果。

  • exact: 如果有exact,只有url地址完全与path相同,才会匹配。如果没有exact属性,url的地址不完全相同,也会匹配。

举例来说,当exact不设置时:

<route></route> 
<route></route>

此时url地址为:http://localhost:3000/home/first  的时候,不仅仅会匹配到 path='/home/first'时的组件First,同时还会匹配到path='home'时候的Router。

如果设置了exact:

 <route></route>

只有http://localhost:3000/home/first 不会匹配Home组件,只有url地址完全与path相同,只有http://localhost:3000/home才能匹配Home组件成功。

  • strict :与exact不同,strict属性仅仅是对exact属性的一个补充,设置了strict属性后,严格限制了但斜线“/”。

举例来说,当不设置strict的时候:

 <route></route>

此时http://localhost:3000/home 和 http://localhost:3000/home/
都能匹配到组件Home。匹配对于斜线“/”比较宽松。如果设置了strict属性:

<route></route>

那么此时严格匹配斜线是否存在,http://localhost:3000/home 将无法匹配到Home组件。

当Route组件与某一url匹配成功后,就会继续去渲染。那么什么属性决定去渲染哪个组件或者样式呢,Route的component、render、children决定渲染的内容。

  • component:该属性接受一个React组件,当url匹配成功,就会渲染该组件

  • render:func 该属性接受一个返回React Element的函数,当url匹配成功,渲染覆该返回的元素

  • children:与render相似,接受一个返回React Element的函数,但是不同点是,无论url与当前的Route的path匹配与否,children的内容始终会被渲染出来。

并且这3个属性所接受的方法或者组件,都会有location,match和history这3个参数。如果组件,那么组件的props中会存在从Link传递过来的location,match以及history。

(3)

定义了匹配规则和渲染规则,而 决定的是如何在页面内改变url,从而与相应的匹配。类似于html中的a标签,此外在改变url的时候,可以将一些属性传递给匹配成功的Route,供相应的组件渲染的时候使用。

  • to: string

to属性的值可以为一个字符串,跟html中的a标签的href一样,即使to属性的值是一个字符串,点击Link标签跳转从而匹配相应path的Route,也会将history,location,match这3个对象传递给Route所对应的组件的props中。

举例来说:

<link>Home

如上所示,当to接受一个string,跳转到url为'/home'所匹配的Route,并渲染其关联的组件内接受3个对象history,location,match。
这3个对象会在下一小节会详细介绍。

  • to: object

to属性的值也可以是一个对象,该对象可以包含一下几个属性:pathname、seacth、hash和state,其中前3个参数与如何改变url有关,最后一个state参数是给相应的改变url时,传递一个对象参数。

举例来说:

 <link>Home

在上个例子中,to为一个对象,点击Link标签跳转后,改变后的url为:'/home?sort=name#edit'。 但是在与相应的Route匹配时,只匹配path为'/home'的组件,'/home?sort=name#edit'。在'/home'后所带的参数不作为匹配标准,仅仅是做为参数传递到所匹配到的组件中,此外,state={a:1}也同样做为参数传递到新渲染的组件中。

(4) React-router中传递给组件props的history对象

介绍了 之后,使用这3个组件API就可以构建一个简单的React-router应用。这里我们之前说,每当点击Link标签跳转或者在js中使用React-router的方法跳转,从当前渲染的组件,进入新组件。在新组件被渲染的时候,会接受一个从旧组件传递过来的参数。

我们前面提到,Route匹配到相应的改变后的url,会渲染新组件,该新组件中的props中有history、location、match3个对象属性,其中hisotry对象属性最为关键。

同样以下面的例子来说明:

<link>Home

<route></route>

我们使用了,该组件利用了window.history对象,当点击Link标签跳转后,会渲染新的组件Home,我们可以在Home组件中输出props中的history:

// props中的history
action: "PUSH"
block: ƒ block()
createHref: ƒ createHref(location)
go: ƒ go(n)
goBack: ƒ goBack()
goForward: ƒ goForward()
length: 12
listen: ƒ listen(listener)
location: {pathname: "/home", search: "?sort=name", hash: "#edit", state: {…}, key: "uxs9r5"}
push: ƒ push(path, state)
replace: ƒ replace(path, state)

从上面的属性明细中:

  • push:f  这个方法用于在js中改变url,之前在Link组件中可以类似于HTML标签的形式改变url。push方法映射于window.history中的pushState方法。

  • replace: f 这个方法也是用于在js中改变url,replace方法映射于window.history中的replaceState方法。

  • block:f 这个方法也很有用,比如当用户离开当前页面的时候,给用户一个文字提示,就可以采用history.block("你确定要离开当前页吗?")这样的提示。

  • go / goBack / goForward

在组件props中history的go、goBack、goForward方法,分别window.history.go、window.history.back、window.history.forward对应。

  • action: "PUSH" || "POP"

action这个属性左右很大,如果是通过Link标签或者在js中通过this.props.push方法来改变当前的url,那么在新组件中的action就是"PUSH",否则就是"POP".

action属性很有用,比如我们在做翻页动画的时候,前进的动画是SlideIn,后退的动画是SlideOut,我们可以根据组件中的action来判断采用何种动画:

function newComponent (props)=>{
   return (
     <reactcsstransitiongroup>
           <component></component>
    </reactcsstransitiongroup>
   )
}
  • location:object

在新组件的location属性中,就记录了从就组件中传递过来的参数,从上面的例子中,我们看到此时的location的值为:

    hash: "#edit"
    key: "uxs9r5"
    pathname: "/home"
    search: "?sort=name"
    state: {a:1}

除了key这个用作唯一表示外,其他的属性都是我们从上一个Link标签中传递过来的参数。

四、React-router4.0源码分析

在第三节中我们介绍了React-router的大致使用方法,读一读React-router4.0的源码。

这里我们主要分析一下React-router4.0中是如何根据window.history来实现前端路由的,因此设计到的组件为BrowserRouter、Router、Route和Link

1、React-router中的history

从上一节的介绍中我们知道,点击Link标签传递给新渲染的组件的props中有一个history对象,这个对象的内容很丰富,比如:action、goBack、go、location、push和replace方法等。

React-router构建了一个History类,用于在window.history的基础上,构建属性更为丰富的实例。该History类实例化后具有action、goBack、location等等方法。

React-router中将这个新的History类的构建方法,独立成一个node包,包名为history。

npm install history -s

可以通过上述方法来引入,我们来看看这个History类的实现。

const createBrowserHistory = (props = {}) => {
    const globalHistory = window.history;
    ......
    //默认props中属性的值
    const {
      forceRefresh = false,
      getUserConfirmation = getConfirmation,
      keyLength = 6,
      basename = '',
    } = props;
    const history = {
        length: globalHistory.length,
        action: "POP",
        location: initialLocation,
        createHref,
        push,
        replace,
        go,
        goBack,
        goForward,
        block,
        listen
    };                                         ---- (1)
    const basename = props.basename;   
    const canUseHistory = supportsHistory();   ----(2)
            
    const createKey = () =>Math.random().toString(36).substr(2, keyLength);    ----(3)
    
    const transitionManager = createTransitionManager();  ----(4)
    const setState = nextState => {
        Object.assign(history, nextState);
    
        history.length = globalHistory.length;
    
        transitionManager.notifyListeners(history.location, history.action);
    };                                      ----(5)
    
    const handlePopState = event => {
        handlePop(getDOMLocation(event.state));
    };
    const handlePop = location => {
    if (forceNextPop) {
      forceNextPop = false;
      setState();
    } else {
      const action = "POP";
      
      transitionManager.confirmTransitionTo(
            location,
            action,
            getUserConfirmation,
            ok => {
              if (ok) {
                setState({ action, location });
              } else {
                revertPop(location);
              }
            }
          );
        }
    };                                    ------(6)
    const initialLocation = getDOMLocation(getHistoryState());
    let allKeys = [initialLocation.key]; ------(7)
    
  
    // 与pop相对应,类似的push和replace方法
    const push ... replace ...            ------(8)
    
    return history                        ------ (9)
    
}
  • (1) 中指明了新的构建方法History所返回的history对象中所具有的属性。

  • (2)中的supportsHistory的方法判断当前的浏览器对于window.history的兼容性,具体方法如下:

    export const supportsHistory = () => {
      const ua = window.navigator.userAgent;
    
      if (
        (ua.indexOf("Android 2.") !== -1 || ua.indexOf("Android 4.0") !== -1) &&
        ua.indexOf("Mobile Safari") !== -1 &&
        ua.indexOf("Chrome") === -1 &&
        ua.indexOf("Windows Phone") === -1
      )
        return false;
    
      return window.history && "pushState" in window.history;
    };

从上述判别式我们可以看出,window.history在chrome、mobile safari和windows phone下是绝对支持的,但不支持安卓2.x以及安卓4.0

  • (3)中用于创建与history中每一个url记录相关联的指定位数的唯一标识key, 默认的keyLength为6位

  • (4)中 createTransitionManager方法,返回一个集成对象,对象中包含了关于history地址或者对象改变时候的监听函数等,具体代码如下:

         const createTransitionManager = () => {
             const setPrompt = nextPrompt => {
               
             };
       
             const confirmTransitionTo = (
               location,
               action,
               getUserConfirmation,
               callback
             ) => {
                if (typeof getUserConfirmation === "function") {
                     getUserConfirmation(result, callback);
                   } else {
                     callback(true);
                   }
                 } 
             };
             
             
             let listeners = [];
             const appendListener = fn => {
               let isActive = true;
           
               const listener = (...args) => {
                 if (isActive) fn(...args);
               };
           
               listeners.push(listener);
           
               return () => {
                 isActive = false;
                 listeners = listeners.filter(item => item !== listener);
               };
             };
           
             const notifyListeners = (...args) => {
               listeners.forEach(listener => listener(...args));
             };
           
             return {
               setPrompt,
               confirmTransitionTo,
               appendListener,
               notifyListeners
             };

};

setPrompt函数,用于设置url跳转时弹出的文字提示,confirmTransaction函数,会将当前生成新的history对象中的location,action,callback等参数,作用就是在回调的callback方法中,根据要求,改变传入的location和action对象。

接着我们看到有一个listeners数组,保存了一系列与url相关的监听事件数组,通过接下来的appendListener方法,可以往这个数组中增加事件,通过notifyListeners方法可以遍历执行listeners数组中的所有事件。

  • (5) setState方法,发生在history的url或者history的action发生改变的时候,此方法会更新history对象中的属性,同时会触发notifyListeners方法,传入当前的history.location和history.action。遍历并执行所有监听url改变的事件数组listeners。

  • (6)这个getDOMLocation方法就是根据当前在window.state中的值,生成新history的location属性对象,allKeys这是始终保持了在url改变时候的历史url相关联的key,保存在全局,allKeys在执行生“POP”或者“PUSH”、“Repalce”等会改变url的方法时,会保持一个实时的更新。

  • (7) handlePop方法,用于处理“POP”事件,我们知道在window.history中点击后退等会触发“POP”事件,这里也是一样,执行action为“POP”,当后退的时候就会触发该函数。

  • (8)中包含了与pop方法类似的,push和replace方法,push方法同样做的事情就是执行action为“PUSH”(“REPLACE”),该变allKeys数组中的值,唯一不同的是actio为“PUSH”的方法push是往allKeys数组中添加,而action为“REPLACE”的方法replace则是替换掉当前的元素。

  • (9)返回这个新生成的history对象。

2、React-router中Link组件

其实最难弄懂的是React-router中如何重新构建了一个history工厂函数,在第一小节中我们已经详细的介绍了history生成函数createBrowserHistory的源码,接着来看Link组件就很容易了。

首先Link组件类似于HTML中的a标签,目的也很简单,就是去主动触发改变url的方法,主动改变url的方法,从上述的history的介绍中可知为push和replace方法,因此Link组件的源码为:

class Link extends React.Component {

    
   handleClick = event => {
   ...

     const { history } = this.context.router;
     const { replace, to } = this.props;
     if (replace) {
       history.replace(replace);
     } else {
      history.push(to);
     }
   }
  };
  render(){
    const { replace, to, innerRef, ...props } = this.props;
     <a></a>
  }
}

上述代码很简单,从React的context API全局对象中拿到history,然后如果传递给Link组件的属性中有replace为true,则执行history.replace(to),to 是一个包含pathname的对象,如果传递给Link组件的replace属性为false,则执行history.push(to)方法。

3、React-router中Route组件

Route组件也很简单,其props中接受一个最主要的属性path,Route做的事情只有一件:

当url改变的时候,将path属性与改变后的url做对比,如果匹配成功,则渲染该组件的componet或者children属性所赋值的那个组件。

具体源码如下:

class Route extends React.Component {


  ....
  constructor(){
  
  
  }
  render() {
    const { match } = this.state;
    const { children, component, render } = this.props;
    const { history, route, staticContext } = this.context.router;
    const location = this.props.location || route.location;
    const props = { match, location, history, staticContext };

    if (component) return match ? React.createElement(component, props) : null;

    if (render) return match ? render(props) : null;

    if (typeof children === "function") return children(props);

    if (children && !isEmptyChildren(children))
      return React.Children.only(children);

    return null;
  }

}

state中的match就是是否匹配的标记,如果匹配当前的Route的path,那么根据优先级顺序component属性、render属性和children属性来渲染其所指向的React组件。

4、React-router中Router组件

Router组件中,是BrowserRouter、HashRouter等组件的底层组件。该组件中,定义了包含匹配规则match函数,以及使用了新history中的listener方法,来监听url的改变,从而,当url改变时,更改Router下不同path组件的isMatch结果。

class Router extends React.Component {
    componentWillMount() {
        const { children, history } = this.props
        
        //调用history.listen监听方法,该方法的返回函数是一个移除监听的函数
        
        this.unlisten = history.listen(() => {
          this.setState({
            match: this.computeMatch(history.location.pathname)
          });
        });
    }
    componentWillUnmount() {
      this.unlisten();
    }
    render() {
    
    }
}

上述首先在组件创建前调用了listener监听方法,来监听url的改变,实时的更新isMatch的结果。

5、总结

本文从前端路由的原理出发,先后介绍了两种前端路由常用的方法,接着介绍了React-router的基本组件API以及用法,详细介绍了React-router的组件中新构建的history对象,最后结合React-router的API阅读了一下React-router的源码。

以上是從路由開始深入理解react-router 4.0源碼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
JavaScript框架:為現代網絡開發提供動力JavaScript框架:為現代網絡開發提供動力May 02, 2025 am 12:04 AM

JavaScript框架的強大之處在於簡化開發、提升用戶體驗和應用性能。選擇框架時應考慮:1.項目規模和復雜度,2.團隊經驗,3.生態系統和社區支持。

JavaScript,C和瀏覽器之間的關係JavaScript,C和瀏覽器之間的關係May 01, 2025 am 12:06 AM

引言我知道你可能會覺得奇怪,JavaScript、C 和瀏覽器之間到底有什麼關係?它們之間看似毫無關聯,但實際上,它們在現代網絡開發中扮演著非常重要的角色。今天我們就來深入探討一下這三者之間的緊密聯繫。通過這篇文章,你將了解到JavaScript如何在瀏覽器中運行,C 在瀏覽器引擎中的作用,以及它們如何共同推動網頁的渲染和交互。 JavaScript與瀏覽器的關係我們都知道,JavaScript是前端開發的核心語言,它直接在瀏覽器中運行,讓網頁變得生動有趣。你是否曾經想過,為什麼JavaScr

node.js流帶打字稿node.js流帶打字稿Apr 30, 2025 am 08:22 AM

Node.js擅長於高效I/O,這在很大程度上要歸功於流。 流媒體匯總處理數據,避免內存過載 - 大型文件,網絡任務和實時應用程序的理想。將流與打字稿的類型安全結合起來創建POWE

Python vs. JavaScript:性能和效率注意事項Python vs. JavaScript:性能和效率注意事項Apr 30, 2025 am 12:08 AM

Python和JavaScript在性能和效率方面的差異主要體現在:1)Python作為解釋型語言,運行速度較慢,但開發效率高,適合快速原型開發;2)JavaScript在瀏覽器中受限於單線程,但在Node.js中可利用多線程和異步I/O提升性能,兩者在實際項目中各有優勢。

JavaScript的起源:探索其實施語言JavaScript的起源:探索其實施語言Apr 29, 2025 am 12:51 AM

JavaScript起源於1995年,由布蘭登·艾克創造,實現語言為C語言。 1.C語言為JavaScript提供了高性能和系統級編程能力。 2.JavaScript的內存管理和性能優化依賴於C語言。 3.C語言的跨平台特性幫助JavaScript在不同操作系統上高效運行。

幕後:什麼語言能力JavaScript?幕後:什麼語言能力JavaScript?Apr 28, 2025 am 12:01 AM

JavaScript在瀏覽器和Node.js環境中運行,依賴JavaScript引擎解析和執行代碼。 1)解析階段生成抽象語法樹(AST);2)編譯階段將AST轉換為字節碼或機器碼;3)執行階段執行編譯後的代碼。

Python和JavaScript的未來:趨勢和預測Python和JavaScript的未來:趨勢和預測Apr 27, 2025 am 12:21 AM

Python和JavaScript的未來趨勢包括:1.Python將鞏固在科學計算和AI領域的地位,2.JavaScript將推動Web技術發展,3.跨平台開發將成為熱門,4.性能優化將是重點。兩者都將繼續在各自領域擴展應用場景,並在性能上有更多突破。

Python vs. JavaScript:開發環境和工具Python vs. JavaScript:開發環境和工具Apr 26, 2025 am 12:09 AM

Python和JavaScript在開發環境上的選擇都很重要。 1)Python的開發環境包括PyCharm、JupyterNotebook和Anaconda,適合數據科學和快速原型開發。 2)JavaScript的開發環境包括Node.js、VSCode和Webpack,適用於前端和後端開發。根據項目需求選擇合適的工具可以提高開發效率和項目成功率。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器

EditPlus 中文破解版

EditPlus 中文破解版

體積小,語法高亮,不支援程式碼提示功能

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )專業的PHP整合開發工具

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中