閱讀951 返回首頁    go 阿裏雲 go 技術社區[雲棲]


vue的可複用性和組合

混合

基礎

混合(mixins)是一種分發Vue組件中可複用功能的非常靈活的方式。混合對象可以包含任意組件選項。以組件使用混合對象時,所有混合對象的選項將被混入該組件本身的選項。例如:

var myMixin = { // 定義一個混合對象
  created: function () {
    this.hello()
  },
  methods: {
    hello: function () {
      console.log('hello from mixin!')
    }
  }
}
var Component = Vue.extend({ // 定義一個使用混合對象的組件
  mixins: [myMixin]
})
var component = new Component() // => "hello from mixin!"

選項合並

當組件和混合對象含有同名選項時,這些選項將以恰當的方式混合。比如,同名鉤子函數將混合為一個數組,因此都將被調用。另外,混合對象的鉤子將在組件自身鉤子之前調用:

var mixin = {
  created: function () {
    console.log('混合對象的鉤子被調用')
  }
}
new Vue({
  mixins: [mixin],
  created: function () {
    console.log('組件鉤子被調用')
  }
})

值為對象的選項,例如methods, components和directives,將被混合為同一個對象。兩個對象鍵名衝突時取組件對象的鍵值對

var mixin = {
  methods: {
    foo: function () {
      console.log('foo')
    },
    conflicting: function () {
      console.log('from mixin')
    }
  }
}
var vm = new Vue({
  mixins: [mixin],
  methods: {
    bar: function () {
      console.log('bar')
    },
    conflicting: function () {
      console.log('from self')
    }
  }
})
vm.foo() // => "foo"
vm.bar() // => "bar"
vm.conflicting() // => "from self"

注意:Vue.extend()也使用同樣的策略進行合並

全局混合

也可以全局注冊混合對象。 注意使用!一旦使用全局混合對象,將會影響到所有之後創建的Vue實例。使用恰當時可以為自定義對象注入處理邏輯

Vue.mixin({ // 為自定義選項 'myOption' 注入一個處理器
  created: function () {
    var myOption = this.$options.myOption
    if (myOption) {
      console.log(myOption)
    }
  }
})
new Vue({
  myOption: 'hello!'
}) // => "hello!"

謹慎使用全局混合對象,因為會影響到每個單獨創建的Vue實例(包括第三方模板)。大多數情況下,隻應當應用於自定義選項,就像上麵示例一樣。也可以將其用作Plugins以避免產生重複應用

自定義選項合並策略

自定義選項將使用默認策略,即簡單地覆蓋已有值。如果想讓自定義選項以自定義邏輯合並,可以向Vue.config.optionMergeStrategies添加一個函數:

Vue.config.optionMergeStrategies.myOption = function (toVal, fromVal) {
  // return mergedVal
}

對於大多數對象選項,可以使用methods的合並策略:

var strategies = Vue.config.optionMergeStrategies
strategies.myOption = strategies.methods

更多高級的例子可以在 Vuex 的 1.x 混合策略裏找到:

const merge = Vue.config.optionMergeStrategies.computed
Vue.config.optionMergeStrategies.vuex = function (toVal, fromVal) {
  if (!toVal) return fromVal
  if (!fromVal) return toVal
  return {
    getters: merge(toVal.getters, fromVal.getters),
    state: merge(toVal.state, fromVal.state),
    actions: merge(toVal.actions, fromVal.actions)
  }
}

自定義指令

簡介

除了默認設置的核心指令(v-model和v-show),Vue也允許注冊自定義指令。注意:在Vue2.0裏,代碼複用的主要形式和抽象是組件——然而,有的情況下,你仍然需要對純DOM元素進行底層操作,這時候就會用到自定義指令,例如聚焦一個input元素。頁麵加載時,元素將獲得焦點(注意:autofocus在移動版Safari上不工作)。事實上,訪問後還沒點擊任何內容input就獲得了焦點。現在讓我們完善這個指令:

const merge = Vue.config.optionMergeStrategies.computed
Vue.config.optionMergeStrategies.vuex = function(toVal, fromVal) {
  if (!toVal) return fromVal
  if (!fromVal) return toVal
  return {
    getters: merge(toVal.getters, fromVal.getters),
    state: merge(toVal.state, fromVal.state),
    actions: merge(toVal.actions, fromVal.actions)
  }
}

也可以注冊局部指令,組件中接受一個directives的選項:

directives: {
  focus: {
    // 指令的定義---
  }
}

然後你可以在模板中任何元素上使用新的v-focus屬性:

<input v-focus>

鉤子函數

指令定義函數提供了幾個鉤子函數(可選):

1.bind: 隻調用一次,指令第一次綁定到元素時調用,用這個鉤子函數可以定義一個在綁定時執行一次的初始化動作

2.inserted: 被綁定元素插入父節點時調用(父節點存在即可調用,不必存在於document中)

3.update: 所在組件的VNode更新時調用,但是可能發生在其孩子的VNode更新之前。指令的值可能發生了改變也可能沒有。但是你可以通過比較更新前後的值來忽略不必要的模板更新

4.componentUpdated: 所在組件的VNode及其孩子的VNode全部更新時調用

5.unbind: 隻調用一次, 指令與元素解綁時調用

接下來我們來看一下鉤子函數的參數 (包括 el,binding,vnode,oldVnode)

鉤子函數參數

鉤子函數被賦予了以下參數:

el: 指令所綁定的元素,可以用來直接操作DOM

binding: 一個對象,包含以下屬性:

1.name: 指令名,不包括v-前綴。

2.value: 指令的綁定值,例如:v-my-directive="1+1", value的值是2

3.oldValue: 指令綁定的前一個值,僅在update和componentUpdated鉤子中可用。無論值是否改變都可用

4.expression: 綁定值的字符串形式。 例如v-my-directive="1+1" , expression的值是"1+1"

5.arg: 傳給指令的參數。例如v-my-directive:foo,arg的值是"foo"

6.modifiers: 一個包含修飾符的對象。例如v-my-directive.foo.bar,修飾符對象modifiers的值是{foo:true, bar:true}

7.vnode: Vue編譯生成的虛擬節點,查閱VNode API了解更多詳情

8.oldVnode: 上一個虛擬節點,僅在update和componentUpdated 子中可用

除el外,其它參數都應是隻讀的,盡量不要修改他們。如果需要在鉤子之間共享數據,建議通過元素的dataset來進行

一個使用了這些參數的自定義鉤子樣例:

<div  v-demo:foo.a.b="message"></div>
<script>
  Vue.directive('demo', {
    bind: function (el, binding, vnode) {
      var s = JSON.stringify
      el.innerHTML =
        'name: '       + s(binding.name) + '<br>' +
        'value: '      + s(binding.value) + '<br>' +
        'expression: ' + s(binding.expression) + '<br>' +
        'argument: '   + s(binding.arg) + '<br>' +
        'modifiers: '  + s(binding.modifiers) + '<br>' +
        'vnode keys: ' + Object.keys(vnode).join(', ')
    }
  })
  new Vue({
    el: '#hook-arguments-example',
    data: {
      message: 'hello!'
    }
  })
</script>

函數簡寫

大多數情況下,我們可能想在bind和update鉤子上做重複動作,並且不想關心其它的鉤子函數。可以這樣寫:

Vue.directive('color-swatch', function (el, binding) {
  el.style.backgroundColor = binding.value
})

對象字麵量

如果指令需要多個值,可以傳入一個JS對象字麵量。記住:指令函數能夠接受所有合法類型的JavaScript表達式

<div v-demo="{ color: 'white', text: 'hello!' }"></div>
<script>
  Vue.directive('demo', function (el, binding) {
    console.log(binding.value.color) // => "white"
    console.log(binding.value.text)  // => "hello!"
  })
</script>

渲染函數 & JSX

基礎

Vue推薦在絕大多數情況下使用template來創建你的HTML。然而在一些場景中,你真的需要JavaScript的完全編程的能力,這就是render函數,它比template更接近編譯器

<h1>
  <a name="hello-world" href="#hello-world"> Hello world! </a>
</h1>

在 HTML 層,我們決定這樣定義組件接口:

<anchored-heading :level="1">Hello world!</anchored-heading>

當我們開始寫一個通過level prop動態生成heading標簽的組件,你可能很快想到這樣實現:

<script type="text/x-template" >
  <h1 v-if="level === 1"> <slot></slot> </h1>
  <h2 v-else-if="level === 2"> <slot></slot> </h2>
  <h3 v-else-if="level === 3"> <slot></slot> </h3>
  <h4 v-else-if="level === 4"> <slot></slot> </h4>
  <h5 v-else-if="level === 5"> <slot></slot> </h5>
  <h6 v-else-if="level === 6"> <slot></slot> </h6>  
</script>
Vue.component('anchored-heading', {
  template: '#anchored-heading-template',
  props: {
    level: {
      type: Number,
      required: true
    }
  }
})

在這種場景中使用template並不是最好的選擇:首先代碼冗長,為了在不同級別的標題中插入錨點元素,我們需要重複地使用。雖然模板在大多數組件中都非常好用,但在這裏就不是很簡潔的了。那麼,我們來嚐試使用render函數重寫上麵的例子:

Vue.component('anchored-heading', {
  render: function (createElement) {
    return createElement(
      'h' + this.level,   // tag name 標簽名稱
      this.$slots.default // 子組件中的陣列
    )
  },
  props: {
    level: {
      type: Number,
      required: true
    }
  }
})

這樣代碼精簡很多,但是需要非常熟悉Vue的實例屬性。在這個例子中,你需要知道當你不使用slot屬性向組件中傳遞內容時,比如anchored-heading中的Hello world!,這些子元素被存儲在組件實例中的$slots.default中

節點、樹以及虛擬DOM

在深入渲染函數之前,了解一些瀏覽器的工作原理是很重要的。以下麵這段HTML為例:

<div>
  <h1>My title</h1>
  Some text content
  <!-- TODO: Add tagline -->
</div>

瀏覽器讀到這些代碼時,會建立一個“DOM節點”樹來保持追蹤,如同畫一張家譜樹來追蹤家庭成員的發展一樣

每個元素都是一個節點。每片文字也是一個節點。甚至注釋也都是節點。一個節點就是頁麵的一個部分。就像家譜樹一樣,每個節點都可以有孩子節點 (也就是說每個部分可以包含其它的一些部分)

高效的更新所有這些節點會是比較困難的,不過你不必再手動完成這個工作了。隻需要告訴Vue希望頁麵上的HTML是什麼,這可以是在一個模板裏:

<h1>{{ blogTitle }}</h1>

或者一個渲染函數裏:

render: function (createElement) {
  return createElement('h1', this.blogTitle)
}

兩種情況下,Vue都會自動保持頁麵的更新,即便blogTitle發生了改變

虛擬DOM

Vue通過建立一個虛擬DOM對真實DOM發生的變化保持追蹤。請近距離看一下這行代碼:

return createElement('h1', this.blogTitle)

createElement到底會返回什麼呢?其實不是一個實際的DOM元素。它更準確的名字可能是createNodeDescription,因為它所包含的信息會告訴Vue頁麵上需要渲染什麼樣的節點及其子節點。我們把這樣的節點描述為“虛擬節點(Virtual DOM)”,也常簡寫它為“VNode”。“虛擬DOM”是我們對由Vue組件樹建立起來的整個VNode樹的稱唿

createElement參數

接下來你需要熟悉的是如何在createElement函數中生成模板

深入data對象

正如在模板語法中,v-bind:class和v-bind:style會被特別對待一樣,在VNode數據對象中,下列屬性名是級別最高的字段。該對象也允許你綁定普通的HTML特性,就像DOM屬性一樣,比如innerHTML(這會取代v-html指令)

{
  // 和`v-bind:class`一樣的 API
  'class': {
    foo: true,
    bar: false
  },
  // 和`v-bind:style`一樣的 API
  style: {
    color: 'red',
    fontSize: '14px'
  },
  // 正常的 HTML 特性
  attrs: {
    id: 'foo'
  },
  // 組件 props
  props: {
    myProp: 'bar'
  },
  // DOM 屬性
  domProps: {
    innerHTML: 'baz'
  },
  // 事件監聽器基於 `on`,所以不再支持如 `v-on:keyup.enter` 修飾器,需要手動匹配keyCode
  on: {
    click: this.clickHandler
  },
  // 僅對於組件,用於監聽原生事件,而不是組件內部使用 `vm.$emit` 觸發的事件
  nativeOn: {
    click: this.nativeClickHandler
  },
  // 自定義指令。注意事項:不能對綁定的舊值設值;Vue會為您持續追蹤
  directives: [
    {
      name: 'my-custom-directive',
      value: '2',
      expression: '1 + 1',
      arg: 'foo',
      modifiers: {
        bar: true
      }
    }
  ],
  // Scoped slots in the form of
  // { name: props => VNode | Array<VNode> }
  scopedSlots: {
    default: props => createElement('span', props.text)
  },
  // 如果組件是其他組件的子組件,需為插槽指定名稱
  slot: 'name-of-slot',
  // 其他特殊頂層屬性
  key: 'myKey',
  ref: 'myRef'
}

完整示例

有了這些知識,我們現在可以完成我們最開始想實現的組件:

var getChildrenTextContent = function (children) {
  return children.map(function (node) {
    return node.children ? getChildrenTextContent(node.children) : node.text
  }).join('')
}
Vue.component('anchored-heading', {
  render: function (createElement) {
    var headingId = getChildrenTextContent(this.$slots.default).toLowerCase().replace(/\W+/g, '-').replace(/(^\-|\-$)/g, '')
    return createElement(
      'h' + this.level,
      [
        createElement('a', {
          attrs: {
            name: headingId,
            href: '#' + headingId
          }
        }, this.$slots.default)
      ]
    )
  },
  props: {
    level: {
      type: Number,
      required: true
    }
  }
})

約束

VNodes必須唯一:組件樹中的所有VNodes必須是唯一的。這意味著,下麵的render function是無效的:

render: function (createElement) {
  var myParagraphVNode = createElement('p', 'hi')
  return createElement('div', [
    // 錯誤-重複的 VNodes
    myParagraphVNode, myParagraphVNode
  ])
}

如果真的需要重複很多次的元素/組件,可以使用工廠函數來實現。例如,下麵這個例子render函數完美有效地渲染了20個重複的段落:

render: function (createElement) {
  return createElement('div',
    Array.apply(null, { length: 20 }).map(function () {
      return createElement('p', 'hi')
    })
  )
}

使用js代替模板功能

v-if和v-for

由於使用原生的JavaScript來實現某些東西很簡單,Vue的render函數沒有提供專用的API。比如,template中的v-if和v-for:

<ul v-if="items.length">
  <li v-for="item in items">{{ item.name }}</li>
</ul>
<p v-else>No items found.</p>

這些都會在render函數中被JavaScript的if/else和map重寫:

render: function (createElement) {
  if (this.items.length) {
    return createElement('ul', this.items.map(function (item) {
      return createElement('li', item.name)
    }))
  } else {
    return createElement('p', 'No items found.')
  }
}

v-model

render函數中沒有與v-model相應的api - 你必須自己來實現相應的邏輯:

render: function (createElement) {
  var self = this
  return createElement('input', {
    domProps: {
      value: self.value
    },
    on: {
      input: function (event) {
        self.value = event.target.value
        self.$emit('input', event.target.value)
      }
    }
  })
}

這就是深入底層要付出的,盡管麻煩了一些,但相對於v-model來說,你可以更靈活地控製

事件&按鍵修飾符

對於.passive、.capture和.once事件修飾符, Vue提供了相應的前綴可以用於on:

Modifier(s) Prefix
.passive &
.capture !
.once ~
.capture.once or .once.capture ~!

例如:

on: {
  '!click': this.doThisInCapturingMode,
  '~keyup': this.doThisOnce,
  `~!mouseover`: this.doThisOnceInCapturingMode
}

對於其他的修飾符,前綴不是很重要,因為你可以直接在事件處理函數中使用事件方法:

Modifier(s) Equivalent in Handler
.stop event.stopPropagation()
.prevent event.preventDefault()
.self if (event.target !== event.currentTarget) return
Keys:.enter,.13 if (event.keyCode !== 13) return (change 13 to another key code for other key modifiers)
Modifiers Keys:.ctrl,.alt,.shift,.meta if (!event.ctrlKey) return (change ctrlKey to altKey, shiftKey, or metaKey, respectively)

這裏是一個使用所有修飾符的例子:

on: {
  keyup: function (event) {
    // 如果觸發事件的元素不是事件綁定的元素則返回
    if (event.target !== event.currentTarget) return
    // 如果按下去的不是enter鍵或者沒有同時按下shift鍵則返回
    if (!event.shiftKey || event.keyCode !== 13) return
    // 阻止 事件冒泡
    event.stopPropagation()
    // 阻止該元素默認的 keyup 事件
    event.preventDefault()
    // ...
  }
}

插槽

你可以從this.$slots獲取VNodes列表中的靜態內容:

render: function (createElement) {
  // `<div><slot></slot></div>`
  return createElement('div', this.$slots.default)
}

還可以從this.$scopedSlots中獲得能用作函數的作用域插槽,這個函數返回VNodes:

render: function (createElement) {
  // `<div><slot :text="msg"></slot></div>`
  return createElement('div', [
    this.$scopedSlots.default({
      text: this.msg
    })
  ])
}

如果要用渲染函數向子組件中傳遞作用域插槽,可以利用VNode數據中的scopedSlots域:

render (createElement) {
  return createElement('div', [
    createElement('child', {
      // pass `scopedSlots` in the data object
      // in the form of { name: props => VNode | Array<VNode> }
      scopedSlots: {
        default: function (props) {
          return createElement('span', props.text)
        }
      }
    })
  ])
}

JSX

如果寫了很多render函數,可能會覺得痛苦:

createElement(
  'anchored-heading', {
    props: {
      level: 1
    }
  }, [
    createElement('span', 'Hello'),
    ' world!'
  ]
)

特別是模板如此簡單的情況下:

<anchored-heading :level="1">
  <span>Hello</span> world!
</anchored-heading>

這就是為什麼會有一個Babel插件,用於在Vue中使用JSX語法的原因,它可以讓我們回到更接近於模板的語法上

import AnchoredHeading from './AnchoredHeading.vue'
new Vue({
  el: '#demo',
  render (h) {
    return (
      <AnchoredHeading level={1}>
        <span>Hello</span> world!
      </AnchoredHeading>
    )
  }
})

將h作為createElement的別名是Vue生態係統中的一個通用慣例,實際上也是JSX所要求的,如果在作用域中h失去作用,在應用中會觸發報錯

函數式組件

之前創建的錨點標題組件比較簡單,沒有管理或監聽任何傳遞給他的狀態,也沒有生命周期方法。它隻是一個接收參數的函數。在這個例子中,我們標記組件為functional,這意味它是無狀態(沒有data),無實例(沒有this上下文)。一個函數式組件就像這樣:

Vue.component('my-component', {
  functional: true,
  // 為了彌補缺少的實例,提供第二個參數作為上下文
  render: function (createElement, context) {
    // ...
  },
  // Props 可選
  props: {
    // ...
  }
})

注意:在2.3.0之前的版本中,如果一個函數式組件想要接受props,則props選項是必須的。在2.3.0或以上的版本中,可以省略props選項,所有組件上的屬性都會被自動解析為props

組件需要的一切都是通過上下文傳遞,包括:

props:提供props的對象

children: VNode子節點的數組
slots: slots對象
data:傳遞給組件的data對象
parent:對父組件的引用
listeners: (2.3.0+)一個包含了組件上所注冊的v-on偵聽器的對象。這隻是一個指向data.on的別名。
injections: (2.3.0+)如果使用了 inject 選項,則該對象包含了應當被注入的屬性。

在添加functional: true之後,錨點標題組件的render函數之間簡單更新增加context參數,this.$slots.default更新為context.children,之後this.level更新為context.props.level

因為函數式組件隻是一個函數,所以渲染開銷也低很多。然而,對持久化實例的缺乏也意味著函數式組件不會出現在Vue devtools的組件樹裏。在作為包裝組件時它們也同樣非常有用,比如,當你需要做這些時:程序化地在多個組件中選擇一個,在將children, props, data傳遞給子組件之前操作它們。

下麵是一個依賴傳入props的值的smart-list組件例子,它能代表更多具體的組件:

var EmptyList = { /* ... */ }
var TableList = { /* ... */ }
var OrderedList = { /* ... */ }
var UnorderedList = { /* ... */ }
Vue.component('smart-list', {
  functional: true,
  render: function (createElement, context) {
    function appropriateListComponent () {
      var items = context.props.items
      if (items.length === 0)           return EmptyList
      if (typeof items[0] === 'object') return TableList
      if (context.props.isOrdered)      return OrderedList
      return UnorderedList
    }
    return createElement(
      appropriateListComponent(),
      context.data,
      context.children
    )
  },
  props: {
    items: {
      type: Array,
      required: true
    },
    isOrdered: Boolean
  }
})

slots()和childre對比

你可能想知道為什麼同時需要slots()和children。slots().default不是和children類似的嗎?但是如果是函數式組件和下麵這樣的children呢?

<my-functional-component>
  <p slot="foo"> first </p>
  <p>second</p>
</my-functional-component>

對於這個組件,children會給你兩個段落標簽,而slots().default隻會傳遞第二個匿名段落標簽,slots().foo會傳遞第一個具名段落標簽。同時擁有children和slots(),因此你可以選擇讓組件通過slot() 係統分發或者簡單的通過children接收,讓其他組件去處理

模板編譯

你可能有興趣知道,Vue的模板實際是編譯成了render函數。這是一個實現細節,通常不需要關心,但如果你想看看模板的功能是怎樣被編譯的,下麵是一個使用Vue.compile來實時編譯模板字符串的簡單demo:

<div>
  <header> <h1>I'm a template!</h1> </header>
  <p v-if="message"> {{ message }} </p>
  <p v-else> No message. </p>
</div>   

render:

function anonymous() {
  with(this){return _c('div',[_m(0),(message)?_c('p',[_v(_s(message))]):_c('p',[_v("No message.")])])}
}  

staticRenderFns:

_m(0): function anonymous() {
  with(this){return _c('header',[_c('h1',[_v("I'm a template!")])])}
}  

插件

開發插件

1.添加全局方法或者屬性,如:vue-custom-element

2.添加全局資源:指令/過濾器/過渡等,如vue-touch

3.通過全局mixin方法添加一些組件選項,如:vue-router

4.添加Vue實例方法,通過把它們添加到Vue.prototype上實現。

5.一個庫,提供自己的API,同時提供上麵提到的一個或多個功能,如vue-router

Vue.js的插件應當有一個公開方法install。這個方法的第一個參數是Vue構造器,第二個參數是一個可選的選項對象:

MyPlugin.install = function (Vue, options) {
  // 1. 添加全局方法或屬性
  Vue.myGlobalMethod = function () {
    // 邏輯...
  }
  // 2. 添加全局資源
  Vue.directive('my-directive', {
    bind (el, binding, vnode, oldVnode) {
      // 邏輯...
    }
    ...
  })
  // 3. 注入組件
  Vue.mixin({
    created: function () {
      // 邏輯...
    }
    ...
  })
  // 4. 添加實例方法
  Vue.prototype.$myMethod = function (methodOptions) {
    // 邏輯...
  }
}

使用插件

通過全局方法Vue.use()使用插件:

// 調用 `MyPlugin.install(Vue)`
Vue.use(MyPlugin)

也可以傳入一個選項對象:

Vue.use(MyPlugin, { someOption: true })

Vue.use會自動阻止注冊相同插件多次,屆時隻會注冊一次該插件

Vue.js官方提供的一些插件(例如vue-router)在檢測到Vue是可訪問的全局變量時會自動調用Vue.use()。然而在例如CommonJS的模塊環境中,你應該始終顯式地調用Vue.use():

// 用 Browserify 或 webpack 提供的 CommonJS 模塊環境時
var Vue = require('vue')
var VueRouter = require('vue-router')
// 不要忘了調用此方法
Vue.use(VueRouter)

過濾器

Vue.js允許你自定義過濾器,可被用作一些常見的文本格式化。過濾器可以用在兩個地方:mustache插值和v-bind表達式(後者從2.1.0+開始支持)。過濾器應該被添加在JavaScript表達式的尾部,由“管道”符指示:

<!-- in mustaches -->
{{ message | capitalize }}
<!-- in v-bind -->
<div v-bind:></div>

過濾器函數總接收表達式的值(之前的操作鏈的結果)作為第一個參數。在這個例子中,capitalize過濾器函數將會收到message的值作為第一個參數

new Vue({
  // ...
  filters: {
    capitalize: function (value) {
      if (!value) return ''
      value = value.toString()
      return value.charAt(0).toUpperCase() + value.slice(1)
    }
  }
})

過濾器可以串聯:

{{ message | filterA | filterB }}

filterA被定義為接收單個參數的過濾器函數,表達式message的值將作為參數傳入到函數中,然後繼續調用同樣被定義為接收單個參數的過濾器函數filterB,將filterA的結果傳遞到filterB中。過濾器是JavaScript函數,因此可以接收參數:

{{ message | filterA('arg1', arg2) }}

這裏,filterA 被定義為接收三個參數的過濾器函數。其中message的值作為第一個參數,普通字符串'arg1'作為第二個參數,表達式arg2取值後的值作為第三個參數

最後更新:2017-09-14 19:33:03

  上一篇:go  探索阿裏巴巴如何打造共享服務中台的穩定性——走進《企業IT架構轉型之道》係列3
  下一篇:go  阿裏雲ESC 部署 GitLab-ce 並配置使用外部 nginx