options-test.ts 8.3 KB

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