倉庫地址:javascript
/* npm 倉庫地址 */ // https://www.npmjs.com/package/vue-property-decorator /* github地址 */ // https://github.com/kaorun343/vue-property-decorator
這一個是與另外一個 vue 的庫 vue-class-component同樣的用法. 這個裝飾器庫源自 class 庫, 只是再封裝了一層, 使代碼更爲簡潔明瞭. options 裏面須要配置 decorator 庫不支持的屬性, 哪些是不支持的呢?html
那就請看徹底文, 凡是沒寫的都是不支持的. 好比components
, filters
, directives
等vue
表示該組件引入了哪些子組件java
<template> <div id="app"> <HelloWorld /> </div> </template> <script lang="ts"> @Component({ components: { HelloWorld, // 聲明子組件的引用 } }) export default class App extends Vue {} </script>
filter 表示對數據的篩選, 跟 linux 中的管道符十分類似, 數據經過 filter 進行處理變成新的數據.node
注意, 在這裏配置時必定要使用 filters, 不要忘了 s, 不然不會報錯可是也沒做用.react
<template> <div>{{msg | filterA}}</div> </template> <script lang="ts"> @Component({ filters: { addWorld: (value: string) => `${value} world`, }, }) export default class App extends Vue { private msg = 'Hello' // filter 以後顯示 hello world } </script>
具體的介紹能夠看 Vue 的官方介紹. 簡單來講就是 DOM 節點在一些特定鉤子觸發時添加一些額外的功能linux
鉤子函數有:git
若是bind 和 update 時調用同樣能夠進行簡寫, 不用指定某個鉤子github
鉤子函數參數:express
v-demo="1+1"
爲 "demo"v-demo="1+1"
爲 2v-demo="1+1"
爲 "1+1"v-demo:foo
爲 'foo', 注意要在 modifier 前使用 arg, 否則會將 arg 做爲 modifier 的一部分, 如v-demo.a:foo
arg 爲 undefined, modifier 爲{'a:foo': true}
v-demo.a
這個值爲 {a:true}
看個簡單的實例:
<template> <span v-demo:foo.a="1+1">test</span> </template> <script lang="ts"> @Component({ directives: { demo: { bind(el, binding, vnode) { console.log(`bindingName: ${binding.name}, value: ${binding.value}, args: ${binding.arg}, expression: ${binding.expression}`); // bindingName: demo, value: 2, args: foo, expression: 1+1 console.log('modifier:', binding.modifiers); // {a:true}, 沒法轉爲 primitive, 因此單獨打印 }, }, demoSimplify(el, binding, vnode) { // do stuff }, }, }) export default class App extends Vue {} </script>
父子組件傳遞數據 props的修飾符, 參數能夠傳
String, Number, Boolean
Invalid prop: type check failed for prop "xxx". Expected Function, got String with value "xxx".
@Prop() name = 1
來表示默認值 1, 雖然看起來同樣, 可是會在 console 裏報錯, 不容許修改 props 中的值[Vue warn]: Missing required prop: "xxx"
(value) => value > 100
父組件:
<template> <div id="app"> <PropComponent :count='count' /> </div> </template> <script lang="ts"> @Component class Parent extends Vue { private count = 101 } </script>
子組件:
<template> <div>{{count}}</div> </template> <script lang="ts"> @Component export default class PropsComponent extends Vue { @Prop({ type: Number, validator: (value) => { return value > 100; }, required: true }) private count!: string // !表示有值, 不然 ts 會告警未初始化 } </script>
與 Prop 的區別是子組件能夠對 props 進行更改, 並同步給父組件,
子組件:
<template> <div> <p>{{count}}</p> <button @click="innerCount += 1">increment</button> </div> </template> <script lang="ts"> @Component export default class PropSyncComponent extends Vue { @PropSync('count') private innerCount!: number // 注意@PropSync 裏的參數不能與定義的實例屬性同名, 由於仍是那個原理, props 是隻讀的. } </script>
父組件: 注意父組件裏綁定 props 時須要加修飾符 .sync
<template> <PropSyncComponent :count.sync="count"/> </template> <script lang="ts"> @Component({ components: PropSyncComponent }) export default class PropSyncComponent extends Vue { @PropSync('count') private innerCount!: number // 注意@PropSync 裏的參數不能與定義的實例屬性同名, 由於仍是那個原理, props 是隻讀的. } </script>
也可結合 input 元素的 v-model
綁定數據, 實時更新. 由讀者自行實現.
監聽屬性發生更改時被觸發. 可接受配置參數 options
immediate?: boolean
是否在偵聽開始以後當即調用該函數deep?: boolean
是否深度監聽.<template> <div> <button @click="innerName.name.firstName = 'lorry'">change deeper</button> <button @click="innerName.name = 'lorry'">change deep</button> </div> </template> <script lang="ts"> @Component export default class PropSyncComponent extends Vue { private person = { name: { firstName: 'jiang' } } @Watch('person', { deep: true, }) private firstNameChange(person: number, oldPerson:number) { console.log(`count change from${oldName.name.first}to: ${oldName.name.}`); } } </script>
event?: string
, 若是沒有的話會自動將 camelCase 轉爲 dash-case 做爲事件名.event
, 會在返回值以後, 也就是第三個參數.子組件:
<template> <div> <button @click="emitChange">Emit!!</button> </div> </template> <script lang="ts"> @Component export default class EmitComponent extends Vue { private count = 0; @Emit('button-click') private emitChange() { this.count += 1; return this.count; } } </script>
父組件, 父組件的對應元素上綁定事件便可:
<template> <EmitComponent v-on:button-click='listenChange'/> </template> <script lang="ts"> @Component({ components: { EmitComponent, }, }) export default class App extends Vue { private listenChange(value: number, event: any) { console.log(value, e); } } </script>
跟 react 中的同樣, ref 是用於引用實際的 DOM 元素或者子組件.應儘量避免直接使用, 但若是不得不用 ref 比 document 拿要方便不少, 參數傳一個字符串refKey?:string
, 注意這裏若是省略傳輸參數, 那麼會自動將屬性名做爲參數, 注意與@Emit
的區別, @Emit
在不傳參數的狀況下會轉爲 dash-case, 而 @Ref
不會轉, 爲原屬性名
<template> <div> <span>Name:</span> <input type="text" v-model="value" ref='name' /> </div> </template> <script lang="ts"> @Component export default class RefComponent extends Vue { @Ref('name') readonly name!: string; private value = 'lorry' private mounted() { console.log(this.inputName); // <input type="text"> // do stuff to ref } } </script>
其本質是轉換爲 inject
和 provide
, 這是 vue 中元素向更深層的子組件傳遞數據的方式.二者須要一塊兒使用.與 react 的 context
十分的像.
任意代的子組件:
<template> <span>Inject deeper: {{bar}}</span> </template> <script lang="ts"> @Component export default class InjectComponent extends Vue { @Inject() private bar!: string private mounted() { console.log(this.bar); } } </script>
任意祖先元素:
<script> export default class App extends Vue { @Provide() private bar = 'deeper lorry' } </script>
方便不少, 若是爲了不命名衝突, 可使用 ES6 的 Symbol
特性做爲 key, 以祖先元素舉例:
須要注意的是避免相互引用的問題, symbol 的引用最好放到組件外單獨有個文件存起來.
export const s = Symbol()
父組件:
<script> export default class App extends Vue { @Provide(s) private bar = 'deeper lorry' } </script>
子組件:
<script> @Component export default class App extends Vue { @Inject(s) private baz = 'deeper lorry' } </script>
@ProvideReactive/@InjectReactive
顧名思義就是響應式的注入, 會同步更新到子組件中.好比下例能夠實如今 input
中的輸入實時注入到子組件中 父組件
<template> <div id="app"> <input type="text" v-model="bar"> <InjectComponent /> </div> </template> <script> @Component({ InjectComponent }) export default class App extends Vue { @ProvideReactive(s) private bar = 'deeper lorry' } </script>
子組件:
<script> @Component export default class InjectComponent extends Vue { @InjectReactive(s) private baz!: string } </script>
歡迎關注公衆號,進一步技術交流: