{"id":7551,"date":"2019-11-03T20:40:12","date_gmt":"2019-11-03T20:40:12","guid":{"rendered":"http:\/\/putridparrot.com\/blog\/?p=7551"},"modified":"2019-11-03T20:40:12","modified_gmt":"2019-11-03T20:40:12","slug":"vue-components","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/vue-components\/","title":{"rendered":"Vue components"},"content":{"rendered":"<p>In a previous post we looked at creating a Vue application. Let&#8217;s now look a little more in depth by looking at creating Vue components.<\/p>\n<p><em>Note: I will be using TypeScript and classes for this, so called &#8220;Class-Style component&#8221;.<\/em><\/p>\n<p>A Vue component would be stored within a .vue file, hence MyComponent.vue for example. Vue components take the form of a template which is made up of HTML with embedded Vue values etc. Styles may also be defined within a style element which will hold standard CSS). Next up we&#8217;d have a script tag if our component does anything more than just being a template with or without styles. <\/p>\n<p>Hence we might layout our component like this<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n&lt;template&gt;\r\n  &lt;div class=&quot;hello&quot;&gt;\r\n    &lt;h1&gt;{{ greeting }} World&lt;\/h1&gt;\r\n  &lt;\/div&gt;\r\n&lt;\/template&gt;\r\n\r\n&lt;style scoped&gt;\r\nh1 {\r\n  color: red;\r\n}\r\n&lt;\/style&gt;\r\n\r\n&lt;script lang=&quot;ts&quot;&gt;\r\nimport { Component, Vue } from 'vue-property-decorator';\r\n\r\n@Component\r\nexport default class MyComponent extends Vue {\r\n  private greeting: string = 'Hello';\r\n}\r\n&lt;\/script&gt;\r\n<\/pre>\n<p>What we&#8217;ve done is create a template for our HTML which is ultimately a div with an h1 element with the text <em>Hello World<\/em> being displayed. Obviously the <em>greeting<\/em> part is supplied by the component as it&#8217;s wrapped in the {{ }} (Mustache) syntax.<\/p>\n<p>Next we&#8217;ve got the style (these sections need not be in any specific order). We obviously don&#8217;t need a style nor script if no style or logic is required. However to demonstrate it&#8217;s usage we&#8217;ve got it here and style scoped to the component (i.e. not global). Ofcourse this will display our template text in H1 font and red text colour.<\/p>\n<p>Now to the slightly more interesting bit. The script contains our code. First off we import the Component decorator and the Vue base class in the standard way.<\/p>\n<p><em>Obviously as Vue uses the @Component decorators you&#8217;ll need the experimental features of TypeScript enabled, which is what the vue client did when creating our application.<\/em><\/p>\n<p>As is pretty obvious, we derive our component from Vue and then implement data and methods. In this case we simply have a constant string with our greeting, before we make this editable, let&#8217;s look at how we render\/use this component.<\/p>\n<p>In our App.vue for example, we add the following to the app template, i.e.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n&lt;template&gt;\r\n  &lt;div id=&quot;app&quot;&gt;\r\n      &lt;MyComponent \/&gt;\r\n  &lt;\/div&gt;\r\n&lt;\/template&gt;\r\n<\/pre>\n<p>The next bit is dependent upon whether you&#8217;re using a router or not. We need to register our component, so without a router our App.vue would contain the following script tag<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n&lt;script lang=&quot;ts&quot;&gt;\r\nimport { Component, Vue } from 'vue-property-decorator';\r\nimport MyComponent from '.\/components\/MyComponent.vue';\r\n\r\n@Component({\r\n  components: {\r\n    MyComponent,\r\n  },\r\n})\r\nexport default class App extends Vue {}\r\n&lt;\/script&gt;\r\n<\/pre>\n<p>If we&#8217;re using a router we probably be using views and hence would declare the following with the view (here&#8217;s an example view)<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n&lt;template&gt;\r\n  &lt;div class=&quot;home&quot;&gt;\r\n    &lt;MyComponent \/&gt;\r\n  &lt;\/div&gt;\r\n&lt;\/template&gt;\r\n\r\n&lt;script&gt;\r\nimport MyComponent from '@\/components\/MyComponent.vue';\r\n\r\nexport default {\r\n  name: 'home',\r\n  components: {\r\n    MyComponent,\r\n  },\r\n};\r\n&lt;\/script&gt;\r\n<\/pre>\n<p><strong>Adding properties<\/strong><\/p>\n<p>Now we&#8217;ve seen how to create a component we&#8217;ll want to extend it by adding properties (attributes in HTML terms). So for example, instead of fixing our greeting string to &#8220;Hello&#8221; we&#8217;ll let the user of our component set the greeting.<\/p>\n<p>To do this we need to add the Prop decorator to the greeting string with MyComponent, i.e. <\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n&lt;script lang=&quot;ts&quot;&gt;\r\nimport { Component, Vue, Prop } from 'vue-property-decorator';\r\n\r\n@Component\r\nexport default class MyComponent extends Vue {\r\n  @Prop() private greeting!: string;\r\n}\r\n&lt;\/script&gt;\r\n<\/pre>\n<p>and now from the code using MyComponent we would write<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n&lt;MyComponent greeting=&quot;Hello&quot; \/&gt;\r\n<\/pre>\n<p><strong>Adding methods\/handlers<\/strong><\/p>\n<p>Let&#8217;s extend our component with a button which, when clicked, increments a counter. So our component script now looks like this<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nimport { Component, Vue, Prop } from 'vue-property-decorator';\r\n\r\n@Component\r\nexport default class MyComponent extends Vue {\r\n  private count: number = 0;\r\n\r\n  @Prop() private greeting: string = 'Hello';\r\n\r\n  handleClick(): void {\r\n    this.count = this.count + 1;\r\n  }\r\n}\r\n<\/pre>\n<p>Now our template is changed to this<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n&lt;template&gt;\r\n  &lt;div class=&quot;hello&quot;&gt;\r\n    &lt;h1&gt;{{ greeting }} World&lt;\/h1&gt;\r\n    &lt;button @click=&quot;handleClick&quot;&gt;Click&lt;\/button&gt;\r\n    &lt;h1&gt;{{ count }}&lt;\/h1&gt;\r\n  &lt;\/div&gt;\r\n&lt;\/template&gt;\r\n<\/pre>\n<p><em>Note: We can use the @click or v-on:click &#8211; the @ is just a shorthand for v-on: in this instance<\/em>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In a previous post we looked at creating a Vue application. Let&#8217;s now look a little more in depth by looking at creating Vue components. Note: I will be using TypeScript and classes for this, so called &#8220;Class-Style component&#8221;. A Vue component would be stored within a .vue file, hence MyComponent.vue for example. Vue components [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[272],"tags":[],"class_list":["post-7551","post","type-post","status-publish","format-standard","hentry","category-vue"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/7551","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=7551"}],"version-history":[{"count":5,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/7551\/revisions"}],"predecessor-version":[{"id":7593,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/7551\/revisions\/7593"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=7551"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=7551"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=7551"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}