Skip to content
Mithril.js 2
Main Navigation 指南API

繁體中文

English
简体中文
Español
Français
Русский
Português – Brasil
Deutsch
日本語
한국어
Italiano
Polski
Türkçe
čeština
magyar

繁體中文

English
简体中文
Español
Français
Русский
Português – Brasil
Deutsch
日本語
한국어
Italiano
Polski
Türkçe
čeština
magyar

外觀

Sidebar Navigation

入門

安裝

簡單應用程式

資源

JSX

在舊版瀏覽器上使用 ES6+

動畫

測試

範例集

第三方整合

路徑處理

關鍵概念

虛擬 DOM 節點

組件

生命周期方法

Keys

自動重繪系統

雜項

框架比較

從 v1.x 遷移

從 v0.2.x 遷移

API

本頁導覽

從 v1.x 遷移 ​

v2.x 幾乎完全與 v1.x 的 API 相容,但仍存在一些破壞性變更。

賦值給 vnode.state ​

在 v1.x 中,您可以操作 vnode.state 並賦值為您想要的任何值。在 v2.x 中,如果嘗試直接賦值給 vnode.state,將會拋出錯誤。遷移方式可能因情況而異,但在大多數情況下,只需將 vnode.state 的引用更改為 vnode.state.foo,並為 foo 選擇一個適當的名稱(例如,如果它是一個計數器的當前值,則可以命名為 count)。

v1.x ​

javascript
var Counter = {
  oninit: function (vnode) {
    vnode.state = 0;
  },
  view: function (vnode) {
    return m('.counter', [
      m(
        'button',
        {
          onclick: function () {
            vnode.state--;
          },
        },
        '-'
      ),
      vnode.state,
      m(
        'button',
        {
          onclick: function () {
            vnode.state++;
          },
        },
        '+'
      ),
    ]);
  },
};

v2.x ​

javascript
var Counter = {
  oninit: function (vnode) {
    vnode.state.count = 0;
  },
  view: function (vnode) {
    return m('.counter', [
      m(
        'button',
        {
          onclick: function () {
            vnode.state.count--;
          },
        },
        '-'
      ),
      vnode.state.count,
      m(
        'button',
        {
          onclick: function () {
            vnode.state.count++;
          },
        },
        '+'
      ),
    ]);
  },
};

當 v1.0 首次發布時,類別與閉包元件並不存在,因此它只是從 vnode.tag 中提取它需要的東西。這個實現細節使得您能夠這樣做的原因,而且在文檔中的某些地方也暗示了這種可能性。現在,情況不同了,這使得從實作的角度來看,管理起來更容易一些,因為只有一個對狀態的引用,而不是兩個。

路由錨點的變更 ​

在 v1.x 中,您可以使用 oncreate: m.route.link,如果連結可能會更改,則也使用 onupdate: m.route.link,每個都作為 vnode 上的生命週期鉤子(hook),可以用於導航。在 v2.x 中,您現在使用 m.route.Link 元件。如果您使用的不是 m("a", ...),則可以透過 selector: 屬性指定選擇器,可以透過 options: 指定選項,可以透過 disabled: 禁用它,並且可以內聯指定其他屬性,包括 href:(必需)。selector: 本身可以包含任何有效的選擇器,作為 m 的第一個參數,並且屬性 [href=...] 和 [disabled] 可以在選擇器以及普通選項中指定。

v1.x ​

javascript
m('a', {
  href: '/path',
  oncreate: m.route.link,
});

m('button', {
  href: '/path',
  oncreate: m.route.link,
});

m('button.btn[href=/path]', {
  oncreate: m.route.link,
});

v2.x ​

javascript
m(m.route.Link, {
  href: '/path',
});

m(m.route.Link, {
  selector: 'button',
  href: '/path',
});

m(m.route.Link, {
  selector: 'button.btn[href=/path]',
});

m.request 錯誤的變更 ​

在 v1.x 中,m.request 解析來自 JSON 呼叫的錯誤,並將產生的已解析物件的屬性,賦值到回應物件上。因此,如果您收到狀態為 403 的回應,並且主體為 {"code": "backoff", "timeout": 1000},則該錯誤將具有兩個額外的屬性:err.code = "backoff" 和 err.timeout = 1000。

在 v2.x 中,回應會被賦值給結果的 response 屬性,而 code 屬性包含產生的狀態碼。因此,如果您收到狀態為 403 的回應,並且主體為 {"code": "backoff", "timeout": 1000},則該錯誤將被賦予兩個屬性:err.response = {code: "backoff", timeout: 1000} 和 err.code = 403。

m.withAttr 已移除 ​

在 v1.x 中,事件監聽器可以使用 oninput: m.withAttr("value", func) 這樣的寫法。在 v2.x 中,只需直接從事件目標讀取即可。它與流 (stream) 協同工作得很好,但由於 m.withAttr("value", stream) 的慣用法不如 m.withAttr("value", prop) 那麼常見,因此 m.withAttr 失去了大部分用處,因此它被移除了。

v1.x ​

javascript
var value = '';

// 在您的視圖中
m('input[type=text]', {
  value: value(),
  oninput: m.withAttr('value', function (v) {
    value = v;
  }),
});

// 或者

var value = m.stream('');

// 在您的視圖中
m('input[type=text]', {
  value: value(),
  oninput: m.withAttr('value', value),
});

v2.x ​

javascript
var value = '';

// 在您的視圖中
m('input[type=text]', {
  value: value,
  oninput: function (ev) {
    value = ev.target.value;
  },
});

// 或者

var value = m.stream('');

// 在您的視圖中
m('input[type=text]', {
  value: value(),
  oninput: function (ev) {
    value(ev.target.value);
  },
});

m.route.prefix ​

在 v1.x 中,m.route.prefix 是一個透過 m.route.prefix(prefix) 呼叫的函式。它現在是一個您可以透過 m.route.prefix = prefix 設定的屬性。

v1.x ​

javascript
m.route.prefix('/root');

v2.x ​

javascript
m.route.prefix = '/root';

m.request/m.jsonp 參數和主體 ​

data 和 useBody 已重構為 params(查詢參數會被插入到 URL 中,並附加到請求上)和 body(要在底層 XHR 中發送的主體)。這使您可以更好地控制發送的實際請求,並允許您使用 POST 請求插入到查詢參數中,並建立帶有主體的 GET 請求。

m.jsonp 沒有有意義的「主體」,因此僅使用 params,因此將 data 重新命名為 params 對於該方法來說就足夠了。

v1.x ​

javascript
m.request('https://example.com/api/user/:id', {
  method: 'GET',
  data: { id: user.id },
});

m.request('https://example.com/api/user/create', {
  method: 'POST',
  data: userData,
});

v2.x ​

javascript
m.request('https://example.com/api/user/:id', {
  method: 'GET',
  params: { id: user.id },
});

m.request('https://example.com/api/user/create', {
  method: 'POST',
  body: userData,
});

路徑模板 ​

在 v1.x 中,有三個獨立的路徑模板語法,雖然它們很相似,但有 2 個單獨設計的語法和 3 個不同的實作。它的定義方式相當特殊,並且參數通常沒有被轉義。現在,如果它是 :key,則所有內容都會被編碼;如果它是 :key...,則所有內容都是原始的。如果事情出乎意料地被編碼,請使用 :path...。就這麼簡單。

具體來說,以下是它如何影響每個方法:

m.request 和 m.jsonp URL,m.route.set 路徑 ​

v2.x 中的路徑元件在插入時會自動轉義。假設您呼叫 m.route.set("/user/:name/photos/:id", {name: user.name, id: user.id})。以前,如果 user 是 {name: "a/b", id: "c/d"},這會將路由設定為 /user/a%2Fb/photos/c/d,但現在會將其設定為 /user/a%2Fb/photos/c%2Fd。如果您故意_想要_插入一個未轉義的鍵,請改用 :key...。

v2.x 中的鍵不能包含任何 . 或 - 的實例。在 v1.x 中,它們可以包含除 / 之外的任何內容。

內嵌查詢字串中的插值(例如 /api/search?q=:query)不會在 v2.x 中執行。請改為透過 params 傳遞這些插值,並使用適當的鍵名,而無需在查詢字串中指定它。

m.route 路由模式 ​

:key... 形式的路徑鍵在 v1.x 中回傳其 URL 解碼,但在 v2.x 中傳回原始 URL。

以前,像 :key.md 這樣的東西被錯誤地接受,導致產生的參數值設定為 keymd: "..."。現在情況並非如此 - .md 現在是模式的一部分,而不是名稱。

生命週期呼叫順序 ​

在 v1.x 中,在所有情況下,元件 vnode 上的屬性生命週期鉤子(hook),都會在元件自身的生命週期鉤子(hook)之前被呼叫。在 v2.x 中,只有 onbeforeupdate 才是這種情況。因此,您可能需要相應地調整您的程式碼。

v1.x ​

javascript
var Comp = {
  oncreate: function () {
    console.log('Component oncreate');
  },
  view: function () {
    return m('div');
  },
};

m.mount(document.body, {
  view: function () {
    return m(Comp, {
      oncreate: function () {
        console.log('Attrs oncreate');
      },
    });
  },
});

// 記錄:
// Attrs oncreate
// Component oncreate

v2.x ​

javascript
var Comp = {
  oncreate: function () {
    console.log('Component oncreate');
  },
  view: function () {
    return m('div');
  },
};

m.mount(document.body, {
  view: function () {
    return m(Comp, {
      oncreate: function () {
        console.log('Attrs oncreate');
      },
    });
  },
});

// 記錄:
// Component oncreate
// Attrs oncreate

m.redraw 同步性 ​

v2.x 中的 m.redraw() 始終是非同步的。如果目前沒有發生重繪,您可以透過 m.redraw.sync() 專門請求同步重繪。

選擇器屬性優先順序 ​

在 v1.x 中,選擇器屬性的優先順序高於屬性物件中指定的屬性。例如,m("[a=b]", {a: "c"}).attrs 傳回 {a: "b"}。

在 v2.x 中,屬性物件中指定的屬性的優先順序高於選擇器屬性。例如,m("[a=b]", {a: "c"}).attrs 傳回 {a: "c"}。

請注意,這在技術上是恢復到 v0.2.x 的行為。

子節點正規化 ​

在 v1.x 中,元件 vnode 子節點像其他 vnode 一樣被正規化。在 v2.x 中,情況不再如此,您需要相應地調整程式碼。這不會影響在渲染時完成的正規化。

m.request 標頭 ​

在 v1.x 中,Mithril.js 在所有非 GET 請求上設定了這兩個標頭,但僅當 useBody 設定為 true(預設值)並且列出的其他條件成立時:

  • 對於具有 JSON 主體的請求,Content-Type: application/json; charset=utf-8
  • 對於期望 JSON 回應的請求,Accept: application/json, text/*

在 v2.x 中,Mithril.js 為所有具有 != null 的 JSON 主體的請求設定第一個標頭,否則預設情況下會省略它,並且這是獨立於選擇哪種方法完成的,包括在 GET 請求上。

這兩個標頭中的第一個標頭 Content-Type 將觸發 CORS 預先檢查,因為它不是 CORS 安全列出的請求標頭,因為指定了內容類型,並且這可能會引入新的錯誤,具體取決於 CORS 在您的伺服器上的配置方式。如果您遇到此問題,您可能需要透過傳遞 headers: {"Content-Type": "text/plain"} 來覆寫有問題的標頭。(Accept 標頭不會觸發任何內容,因此您無需覆蓋它。)

Fetch 規範允許避免 CORS 預先檢查檢查的唯一內容類型是 application/x-www-form-urlencoded、multipart/form-data 和 text/plain。它不允許任何其他內容,並且它有意不允許 JSON。

路由中雜湊字串中的查詢參數 ​

在 v1.x 中,您可以在查詢字串和雜湊字串中為路由指定查詢參數,因此 m.route.set("/route?foo=1&bar=2")、m.route.set("/route?foo=1#bar=2") 和 m.route.set("/route#foo=1&bar=2") 都是等效的,並且從它們中提取的屬性將是 {foo: "1", bar: "2"}。

在 v2.x 中,雜湊字串的內容將會被忽略,但會被保留下來。因此,從每個字串中提取的屬性將是:

  • m.route.set("/route?foo=1&bar=2") → {foo: "1", bar: "2"}
  • m.route.set("/route?foo=1#bar=2") → {foo: "1"}
  • m.route.set("/route#foo=1&bar=2") → {}

這樣做的原因是像 https://example.com/#!/route#key 這樣的 URL 在技術上根據 URL 規範 是無效的,甚至根據 之前的 RFC 也是無效的,並且只有 HTML 規範的一個怪癖允許它們。(如果 HTML 規範想要遵循規範,它應該從一開始就要求 ID 和位置片段是有效的 URL 片段。)

或者簡而言之,停止使用無效的 URL!

鍵 ​

在 v1.x 中,您可以自由地混合鍵控和未鍵控的 vnode。如果第一個節點是鍵控的,則執行鍵控差異,假設每個元素都有一個鍵,並且在執行時忽略這些空隙。否則,執行迭代差異,如果一個節點有一個鍵,則會檢查它是否在檢查標籤和類似內容的同時發生了更改。

在 v2.x 中,片段和元素的子節點列表必須全部鍵控或全部未鍵控。為了此檢查的目的,孔也被認為是未鍵控的 - 它不再忽略它們。

如果您需要解決它,請使用包含單個 vnode 的片段的慣用法,例如 [m("div", {key: whatever})]。

m.version 已移除 ​

它通常沒有太多用途,您可以隨時自己將其添加回去。您應該更喜歡使用功能檢測來了解哪些功能可用,並且 v2.x API 旨在更好地啟用此功能。

Pager
上一頁框架比較
下一頁從 v0.2.x 遷移

以 MIT 授權條款 發布。

版權所有 (c) 2024 Mithril Contributors

https://mithril.js.org/migration-v1x.html

以 MIT 授權條款 發布。

版權所有 (c) 2024 Mithril Contributors