options-test.ts 8.8 KB

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