options-test.ts 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. import Vue, { PropType, VNode } from "../index";
  2. import { ComponentOptions, Component } from "../index";
  3. import { CreateElement } from "../vue";
  4. interface MyComponent extends Vue {
  5. a: number;
  6. }
  7. const option: ComponentOptions<MyComponent> = {
  8. data() {
  9. return {
  10. a: 123
  11. }
  12. }
  13. }
  14. // contravariant generic should use never
  15. const anotherOption: ComponentOptions<never> = option
  16. const componentType: Component = option
  17. Vue.component('sub-component', {
  18. components: {
  19. a: Vue.component(""),
  20. b: {}
  21. }
  22. });
  23. Vue.component('prop-component', {
  24. props: {
  25. size: Number,
  26. name: {
  27. type: String,
  28. default: '0',
  29. required: true,
  30. }
  31. },
  32. data() {
  33. return {
  34. fixedSize: this.size.toFixed(),
  35. capName: this.name.toUpperCase()
  36. }
  37. }
  38. });
  39. Vue.component('string-prop', {
  40. props: ['size', 'name'],
  41. data() {
  42. return {
  43. fixedSize: this.size.whatever,
  44. capName: this.name.isany
  45. }
  46. }
  47. });
  48. class User {
  49. private u = 1
  50. }
  51. class Cat {
  52. private u = 1
  53. }
  54. interface IUser {
  55. foo: string,
  56. bar: number
  57. }
  58. interface ICat {
  59. foo: any,
  60. bar: object
  61. }
  62. type ConfirmCallback = (confirm: boolean) => void;
  63. Vue.component('union-prop', {
  64. props: {
  65. cat: Object as PropType<ICat>,
  66. complexUnion: { type: [User, Number] as PropType<User | number> },
  67. kittyUser: Object as PropType<ICat & IUser>,
  68. callback: Function as PropType<ConfirmCallback>,
  69. mixed: [RegExp, Array],
  70. object: [Cat, User],
  71. primitive: [String, Number],
  72. regex: RegExp,
  73. union: [User, Number] as PropType<User | number>
  74. },
  75. data() {
  76. this.cat;
  77. this.complexUnion;
  78. this.kittyUser;
  79. this.callback(true);
  80. this.mixed;
  81. this.object;
  82. this.primitive;
  83. this.regex.compile;
  84. this.union;
  85. return {
  86. fixedSize: this.union,
  87. }
  88. }
  89. });
  90. Vue.component('prop-with-primitive-default', {
  91. props: {
  92. id: {
  93. type: String,
  94. default: () => String(Math.round(Math.random() * 10000000))
  95. }
  96. },
  97. created() {
  98. this.id;
  99. }
  100. });
  101. Vue.component('component', {
  102. data() {
  103. this.$mount
  104. this.size
  105. return {
  106. a: 1
  107. }
  108. },
  109. props: {
  110. size: Number,
  111. name: {
  112. type: String,
  113. default: '0',
  114. required: true,
  115. }
  116. },
  117. propsData: {
  118. msg: "Hello"
  119. },
  120. computed: {
  121. aDouble(): number {
  122. return this.a * 2;
  123. },
  124. aPlus: {
  125. get(): number {
  126. return this.a + 1;
  127. },
  128. set(v: number) {
  129. this.a = v - 1;
  130. },
  131. cache: false
  132. }
  133. },
  134. methods: {
  135. plus() {
  136. this.a++;
  137. this.aDouble.toFixed();
  138. this.aPlus = 1;
  139. this.size.toFixed();
  140. }
  141. },
  142. watch: {
  143. 'a': function(val: number, oldVal: number) {
  144. console.log(`new: ${val}, old: ${oldVal}`);
  145. },
  146. 'b': 'someMethod',
  147. 'c': {
  148. handler(val, oldVal) {
  149. this.a = val
  150. },
  151. deep: true
  152. }
  153. },
  154. el: "#app",
  155. template: "<div>{{ message }}</div>",
  156. render(createElement) {
  157. return createElement("div", {
  158. attrs: {
  159. id: "foo"
  160. },
  161. props: {
  162. myProp: "bar"
  163. },
  164. directives: [{
  165. name: 'a',
  166. value: 'foo'
  167. }],
  168. domProps: {
  169. innerHTML: "baz"
  170. },
  171. on: {
  172. click: new Function
  173. },
  174. nativeOn: {
  175. click: new Function
  176. },
  177. class: {
  178. foo: true,
  179. bar: false
  180. },
  181. style: {
  182. color: 'red',
  183. fontSize: '14px'
  184. },
  185. key: 'myKey',
  186. ref: 'myRef',
  187. refInFor: true
  188. }, [
  189. createElement(),
  190. createElement("div", "message"),
  191. createElement(Vue.component("component")),
  192. createElement({} as ComponentOptions<Vue>),
  193. createElement({
  194. functional: true,
  195. render(c: CreateElement) {
  196. return createElement()
  197. }
  198. }),
  199. createElement(() => Vue.component("component")),
  200. createElement(() => ( {} as ComponentOptions<Vue> )),
  201. createElement((resolve, reject) => {
  202. resolve({} as ComponentOptions<Vue>);
  203. reject();
  204. }),
  205. "message",
  206. [createElement("div", "message")]
  207. ]);
  208. },
  209. renderError(createElement, err) {
  210. return createElement('pre', { style: { color: 'red' }}, err.stack)
  211. },
  212. staticRenderFns: [],
  213. beforeCreate() {
  214. (this as any).a = 1;
  215. },
  216. created() {},
  217. beforeDestroy() {},
  218. destroyed() {},
  219. beforeMount() {},
  220. mounted() {},
  221. beforeUpdate() {},
  222. updated() {},
  223. activated() {},
  224. deactivated() {},
  225. errorCaptured(err, vm, info) {
  226. err.message
  227. vm.$emit('error')
  228. info.toUpperCase()
  229. return true
  230. },
  231. serverPrefetch () {
  232. return Promise.resolve()
  233. },
  234. directives: {
  235. a: {
  236. bind() {},
  237. inserted() {},
  238. update() {},
  239. componentUpdated() {},
  240. unbind() {}
  241. },
  242. b(el, binding, vnode, oldVnode) {
  243. el.textContent;
  244. binding.name;
  245. binding.value;
  246. binding.oldValue;
  247. binding.expression;
  248. binding.arg;
  249. binding.modifiers["modifier"];
  250. }
  251. },
  252. components: {
  253. a: Vue.component(""),
  254. b: {} as ComponentOptions<Vue>
  255. },
  256. transitions: {},
  257. filters: {
  258. double(value: number) {
  259. return value * 2;
  260. }
  261. },
  262. parent: new Vue,
  263. mixins: [Vue.component(""), ({} as ComponentOptions<Vue>)],
  264. name: "Component",
  265. extends: {} as ComponentOptions<Vue>,
  266. delimiters: ["${", "}"]
  267. });
  268. Vue.component('custom-prop-type-function', {
  269. props: {
  270. callback: Function as PropType<(confirm: boolean) => void>,
  271. },
  272. methods: {
  273. confirm(){
  274. this.callback(true);
  275. }
  276. }
  277. });
  278. Vue.component('provide-inject', {
  279. provide: {
  280. foo: 1
  281. },
  282. inject: {
  283. injectFoo: 'foo',
  284. injectBar: Symbol(),
  285. injectBaz: { from: 'baz' },
  286. injectQux: { default: 1 },
  287. injectQuux: { from: 'quuz', default: () => ({ value: 1 })}
  288. }
  289. })
  290. Vue.component('provide-function', {
  291. provide: () => ({
  292. foo: 1
  293. })
  294. })
  295. Vue.component('component-with-slot', {
  296. render (h): VNode {
  297. return h('div', this.$slots.default)
  298. }
  299. })
  300. Vue.component('component-with-scoped-slot', {
  301. render (h) {
  302. interface ScopedSlotProps {
  303. msg: string
  304. }
  305. return h('div', [
  306. h('child', [
  307. // default scoped slot as children
  308. (props: ScopedSlotProps) => [h('span', [props.msg])]
  309. ]),
  310. h('child', {
  311. scopedSlots: {
  312. // named scoped slot as vnode data
  313. item: (props: ScopedSlotProps) => [h('span', [props.msg])]
  314. }
  315. }),
  316. h('child', [
  317. // return single VNode (will be normalized to an array)
  318. (props: ScopedSlotProps) => h('span', [props.msg])
  319. ]),
  320. h('child', {
  321. // Passing down all slots from parent
  322. scopedSlots: this.$scopedSlots
  323. }),
  324. h('child', {
  325. // Passing down single slot from parent
  326. scopedSlots: {
  327. default: this.$scopedSlots.default
  328. }
  329. })
  330. ])
  331. },
  332. components: {
  333. child: {
  334. render (this: Vue, h: CreateElement) {
  335. const defaultSlot = this.$scopedSlots['default']!({ msg: 'hi' })
  336. defaultSlot && defaultSlot.forEach(vnode => {
  337. vnode.tag
  338. })
  339. return h('div', [
  340. defaultSlot,
  341. this.$scopedSlots['item']!({ msg: 'hello' })
  342. ])
  343. }
  344. }
  345. }
  346. })
  347. Vue.component('narrow-array-of-vnode-type', {
  348. render (h): VNode {
  349. const slot = this.$scopedSlots.default!({})
  350. if (typeof slot === 'string') {
  351. // <template slot-scope="data">bare string</template>
  352. return h('span', slot)
  353. } else if (Array.isArray(slot)) {
  354. // template with multiple children
  355. const first = slot[0]
  356. if (!Array.isArray(first) && typeof first !== 'string' && first) {
  357. return first
  358. } else {
  359. return h()
  360. }
  361. } else if (slot) {
  362. // <div slot-scope="data">bare VNode</div>
  363. return slot
  364. } else {
  365. // empty template, slot === undefined
  366. return h()
  367. }
  368. }
  369. })
  370. Vue.component('functional-component', {
  371. props: ['prop'],
  372. functional: true,
  373. inject: ['foo'],
  374. render(createElement, context) {
  375. context.props;
  376. context.children;
  377. context.slots();
  378. context.data;
  379. context.parent;
  380. context.scopedSlots;
  381. context.listeners.click;
  382. return createElement("div", {}, context.children);
  383. }
  384. });
  385. Vue.component('functional-component-object-inject', {
  386. functional: true,
  387. inject: {
  388. foo: 'foo',
  389. bar: Symbol(),
  390. baz: { from: 'baz' },
  391. qux: { default: 1 },
  392. quux: { from: 'quuz', default: () => ({ value: 1 })}
  393. },
  394. render(h) {
  395. return h('div')
  396. }
  397. })
  398. Vue.component('functional-component-check-optional', {
  399. functional: true
  400. })
  401. Vue.component('functional-component-multi-root', {
  402. functional: true,
  403. render(h) {
  404. return [
  405. h("tr", [h("td", "foo"), h("td", "bar")]),
  406. h("tr", [h("td", "lorem"), h("td", "ipsum")])
  407. ]
  408. }
  409. })
  410. Vue.component("async-component", ((resolve, reject) => {
  411. setTimeout(() => {
  412. resolve(Vue.component("component"));
  413. }, 0);
  414. return new Promise((resolve) => {
  415. resolve({
  416. functional: true,
  417. render(h: CreateElement) { return h('div') }
  418. });
  419. })
  420. }));
  421. Vue.component('functional-component-v-model', {
  422. props: ['foo'],
  423. functional: true,
  424. model: {
  425. prop: 'foo',
  426. event: 'change'
  427. },
  428. render(createElement, context) {
  429. return createElement("input", {
  430. on: {
  431. input: new Function()
  432. },
  433. domProps: {
  434. value: context.props.foo
  435. }
  436. });
  437. }
  438. });
  439. Vue.component('async-es-module-component', () => import('./es-module'))