vue.js手册_Vue手册:Vue.js的完整介绍
vue.js手冊
Get this post in PDF/ePub/MOBI format at vuehandbook.com
在vuehandbook.com上以PDF / ePub / MOBI格式獲取此帖子
Vue is a very popular JavaScript front-end framework, one that’s experiencing a huge amount of growth.
Vue是一種非常流行JavaScript前端框架,正在經歷巨大的增長。
It is simple, tiny (~24KB), and very performant. It feels different from all the other JavaScript front-end frameworks and view libraries. Let’s find out why.
它簡單,小巧(?24KB),并且性能很高。 感覺與所有其他JavaScript前端框架和視圖庫不同。 讓我們找出原因。
首先,什么是JavaScript前端框架? (First, what is a JavaScript front-end framework?)
If you’re unsure what a JavaScript framework is, Vue is the perfect first encounter with one.
如果不確定JavaScript框架是什么,Vue是一個完美的初次接觸。
A JavaScript framework helps us to create modern applications. Modern JavaScript applications are mostly used on the Web, but also power a lot of Desktop and Mobile applications.
JavaScript框架可幫助我們創建現代應用程序。 現代JavaScript應用程序主要在Web上使用,但也為許多桌面和移動應用程序提供支持。
Until the early 2000s, browsers didn’t have the capabilities they have now. They were a lot less powerful, and building complex applications inside them was not feasible performance-wise. The tooling was not even something that people thought about.
直到2000年代初,瀏覽器才具備現在所沒有的功能。 它們的功能要弱得多,并且在它們內部構建復雜的應用程序在性能上是不可行的。 人們甚至都沒有想到過這種工具。
Everything changed when Google unveiled Google Maps and GMail, two applications that ran inside the browser. Ajax made asynchronous network requests possible. Over time, developers started building on top of the Web platform, while engineers worked on the platform itself — browsers, the Web standards, the browser APIs, and the JavaScript language.
當Google推出瀏覽器中運行的兩個應用程序Google Maps和GMail時 ,一切都發生了變化。 Ajax使異步網絡請求成為可能。 隨著時間的流逝,開發人員開始在Web平臺之上進行構建,而工程師則在平臺本身上進行工作-瀏覽器,Web標準,瀏覽器API和JavaScript語言。
Libraries like jQuery and Mootools were the first big projects that built upon JavaScript and were hugely popular for a while. They basically provided a nicer API to interact with the browser and provided workarounds for bugs and inconsistencies among the various browsers.
像jQuery和Mootools這樣的庫是第一個基于JavaScript的大型項目,并在一段時間內大受歡迎。 他們基本上提供了一個更好的API與瀏覽器進行交互,并提供了各種瀏覽器之間的錯誤和不一致的解決方法。
Frameworks like Backbone, Ember, Knockout, and AngularJS were the first wave of modern JavaScript frameworks.
諸如Backbone , Ember , Knockout和AngularJS之類的框架是現代JavaScript框架的第一波潮流。
The second wave, which is the current one, has React, Angular, and Vue as its main actors.
第二波是當前波,其主要參與者是React , Angular和Vue 。
Note that jQuery, Ember and the other projects I mentioned are still being heavily used, actively maintained, and millions of websites rely on them.
請注意,jQuery,Ember和我提到的其他項目仍在大量使用,積極維護和數百萬個網站依賴它們。
That said, techniques and tools evolve, and as a JavaScript developer, you’re now likely to be required to know React, Angular or Vue rather than those older frameworks.
也就是說,技術和工具不斷發展,作為JavaScript開發人員,您現在可能需要了解React,Angular或Vue,而不是那些較舊的框架。
Frameworks abstract the interaction with the browser and the DOM. Instead of manipulating elements by referencing them in the DOM, we declaratively define and interact with them, at a higher level.
框架抽象了與瀏覽器和DOM的交互。 我們不是在DOM中通過引用元素來操作元素,而是在更高的級別上以聲明方式定義它們并與之交互。
Using a framework is like using the C programming language instead of using the Assembly language to write system programs. It’s like using a computer to write a document instead of using a typewriter. It’s like having a self-driving car instead of driving the car yourself.
使用框架就像使用C編程語言而不是使用匯編語言編寫系統程序一樣。 就像使用計算機來編寫文檔而不是使用打字機一樣。 這就像擁有自動駕駛汽車,而不是自己駕駛汽車。
Well, not that far, but you get the idea. Instead of using low-level APIs offered by the browser to manipulate elements, and building hugely complex systems to write an application, you use tools built by very smart people that make our life easier.
好吧,不是很遠,但是您知道了。 您不必使用由瀏覽器提供的低級API來操縱元素,而是使用非常聰明的人構建的工具來使我們的生活更輕松,這些工具可以構建非常復雜的系統來編寫應用程序。
Vue的受歡迎程度 (The popularity of Vue)
How popular is Vue.js?
Vue.js的受歡迎程度如何?
Vue had:
Vue有:
- 7,600 stars on GitHub in 2016 2016年在GitHub上獲得7,600星
- 36,700 stars on GitHub in 2017 2017年在GitHub上有36,700星
and it has more than 100,000+ stars on GitHub, as of June 2018.
截至2018年6月,它在GitHub上擁有超過100,000個星星。
Its npm download count is growing every day, and now it’s at ~350,000 downloads per week.
它的npm下載數量每天都在增長,現在每周大約有350,000次下載。
I would say Vue is very popular, given those numbers.
鑒于這些數字,我會說Vue非常受歡迎。
In relative terms, it has approximately the same numbers of GitHub stars as React, which was born years before.
相對而言,它的GitHub星星數量與幾年前誕生的React大致相同。
Numbers are not everything, of course. The impression I have of Vue is that developers love it.
當然,數字不是萬能的。 我對Vue的印象是開發人員喜歡它。
A key point in time of the rise of Vue has been the adoption in the Laravel ecosystem, a hugely popular PHP web application framework. But since then it has become widespread among many other development communities.
Vue興起的關鍵時刻是在Laravel生態系統中的采用,Laravel生態系統是一種非常流行PHP Web應用程序框架。 但是從那以后,它已經在許多其他開發社區中廣泛傳播。
為什么開發人員喜歡Vue (Why developers love Vue)
First, Vue is called a progressive framework.
首先,Vue被稱為漸進框架。
This means that it adapts to the needs of the developer. Other frameworks require a complete buy-in from a developer or team and often want you to rewrite an existing application because they require some specific set of conventions. Vue happily lands inside your app with a simple script tag to start with, and it can grow along with your needs, spreading from 3 lines to managing your entire view layer.
這意味著它可以適應開發人員的需求。 其他框架則需要開發人員或團隊的全面支持,并且由于它們需要一些特定的約定集,因此常常希望您重寫現有的應用程序。 Vue可以通過一個簡單的script標簽輕松地進入您的應用程序,它可以隨著您的需求而增長,從3行擴展到管理整個視圖層。
You don’t need to know about webpack, Babel, npm or anything to get started with Vue. But when you’re ready, Vue makes it simple for you to rely on them.
您不需要了解webpack , Babel ,npm或任何有關Vue入門的知識。 但是當您準備就緒時,Vue使您可以輕松依賴它們。
This is one great selling point, especially in the current ecosystem of JavaScript front-end frameworks and libraries that tend to alienate newcomers and also experienced developers that feel lost in the ocean of possibilities and choices.
這是一個很大的賣點,特別是在當前JavaScript前端框架和庫生態系統中,這些生態系統傾向于疏遠新手和經驗豐富的開發人員,他們迷失在可能性和選擇的海洋中。
Vue.js is probably the most approachable front-end framework around. Some people call Vue the new jQuery, because it easily gets in the application via a script tag, and gradually gains space from there. Think of it as a compliment, since jQuery dominated the Web in the past few years, and it still does its job on a huge number of sites.
Vue.js可能是最容易接近的前端框架。 有人稱Vue為新的jQuery ,因為它很容易通過script標簽進入應用程序,并從那里逐漸獲得空間。 自從jQuery在過去幾年中統治了Web以來,它一直是一種贊美,現在它仍然在大量站點上發揮作用。
Vue was built by picking the best ideas of frameworks like Angular, React and Knockout, and by cherry-picking the best choices those frameworks made. And by excluding some less brilliant ones, it kind of started as a “best-of” set and grew from there.
Vue的構建是通過選擇Angular,React和Knockout等框架的最佳思想,并挑選這些框架的最佳選擇來進行的。 通過排除一些不太出色的產品,它開始成為“最佳”產品,并從那里發展起來。
Vue.js在框架環境中的什么位置? (Where does Vue.js position itself in the frameworks landscape?)
The two elephants in the room, when talking about web development, are React and Angular. How does Vue position itself relative to those two big and popular frameworks?
在談論Web開發時,會議室中的兩個大象是React和Angular。 Vue如何相對于這兩個流行的大型框架定位自己?
Vue was created by Evan You when he was working at Google on AngularJS (Angular 1.0) apps. It was born out of a need to create more performant applications. Vue picked some of the Angular templating syntax, but removed the opinionated, complex stack that Angular required, and made it very performant.
Vue是由Evan You在Google上使用AngularJS(Angular 1.0)應用程序創建的。 它源于創建更多高性能應用程序的需要。 Vue選擇了一些Angular模板語法,但刪除了Angular所需的,自以為是的復雜堆棧,并使其表現出色。
The new Angular (Angular 2.0) also solved many of the AngularJS issues, but in very different ways. It also requires a buy-in to TypeScript which not all developers enjoy using (or want to learn).
新的Angular(Angular 2.0)也解決了許多AngularJS問題,但是方式卻截然不同。 它還需要TypeScript的支持 ,并非所有開發人員都喜歡使用(或想學習)。
What about React? Vue took many good ideas from React, most importantly the Virtual DOM. But Vue implements it with some sort of automatic dependency management. This tracks which components are affected by a change of the state so that only those components are re-rendered when that state property changes.
那React呢? Vue從React獲得了很多好主意,最重要的是虛擬DOM。 但是Vue通過某種自動依賴管理來實現它。 這跟蹤狀態更改影響哪些組件,以便在狀態屬性更改時僅重新呈現那些組件。
In React, on the other hand, when a part of the state that affects a component changes, the component will be re-rendered. By default all its children will be re-rendered as well. To avoid this you need to use the shouldComponentUpdate method of each component and determine if that component should be re-rendered. This gives Vue a bit of an advantage in terms of ease of use, and out of the box performance gains.
另一方面,在React中,當影響組件的狀態的一部分發生變化時,組件將被重新渲染。 默認情況下,其所有子級也會重新渲染。 為了避免這種情況,您需要使用每個組件的shouldComponentUpdate方法,并確定是否應重新呈現該組件。 就易用性和開箱即用的性能而言,這給Vue帶來了一些優勢。
One big difference with React is JSX. While you can technically use JSX in Vue, it’s not a popular approach and instead the templating system is used. Any HTML file is a valid Vue template. JSX is very different than HTML, and has a learning curve for people on the team that might only need to work with the HTML part of the app, like designers.
與React的一大不同是JSX 。 盡管您可以在Vue中使用JSX,但它并不是一種流行的方法,而是使用了模板系統 。 任何HTML文件都是有效的Vue模板。 JSX與HTML截然不同,它為團隊中的人員提供了學習曲線,他們可能只需要使用應用程序HTML部分,例如設計師。
Vue templates are very similar to Mustache and Handlebars (although they differ in terms of flexibility). As such, they are more familiar to developers that already used frameworks like Angular and Ember.
Vue模板與Moustache和Handlebars非常相似(盡管它們在靈活性方面有所不同)。 因此,對于已經使用Angular和Ember等框架的開發人員來說,它們更加熟悉。
The official state management library, Vuex, follows the Flux architecture and is somewhat similar to Redux in its concepts. Again, this is part of the positive things about Vue, which saw this good pattern in React and borrowed it for its ecosystem. And while you can use Redux with Vue, Vuex is specifically tailored for Vue and its inner workings.
官方狀態管理庫Vuex遵循Flux架構,其概念在某種程度上類似于Redux 。 再次,這是關于Vue的積極事情的一部分,Vue在React中看到了這種良好模式,并將其借用于其生態系統。 盡管可以將Redux與Vue結合使用,但Vuex是專門針對Vue及其內部功能而量身定制的。
Vue is flexible, but the fact that the core team maintains two packages that are very important for any web app (like routing and state management) makes it a lot less fragmented than React. For example: vue-router and vuex are key to the success of Vue.
Vue非常靈活,但是核心團隊維護著兩個軟件包,這對于任何Web應用程序(如路由和狀態管理)都非常重要,這使得它比React更加零碎。 例如: vue-router和vuex是Vue成功的關鍵。
You don't need to choose or worry if that library you chose is going to be maintained in the future and will keep up with framework updates. Since they are official, they are the canonical go-to libraries for their niche (but you can choose to use what you like, of course).
您無需選擇或擔心您將來選擇的那個庫是否將要維護,并會跟上框架更新的步伐。 由于它們是官方的,因此它們是其利基市場的規范性去庫(但您當然可以選擇使用喜歡的庫)。
One thing that puts Vue in a different bucket compared to React and Angular is that Vue is an indie project: it’s not backed by a huge corporation like Facebook or Google.
與React和Angular相比,使Vue處于不同的類別的一件事是Vue是一個獨立項目:它沒有像Facebook或Google這樣的大型公司的支持。
Instead, it’s completely backed by the community, which fosters development through donations and sponsors. This makes sure the roadmap of Vue is not driven by a single company’s agenda.
相反,它得到了社區的完全支持,該社區通過捐贈和贊助者促進發展。 這可以確保Vue的路線圖不受單個公司議程的驅動。
您的第一個Vue應用 (Your first Vue App)
If you’ve never created a Vue.js application, I am going to guide you through the task of creating one so that you understand how it works.
如果您從未創建過Vue.js應用程序,那么我將指導您完成創建應用程序的任務,以便您了解其工作方式。
第一個例子 (First example)
First I’ll go through the most basic example of using Vue.
首先,我將介紹使用Vue的最基本示例。
You create an HTML file which contains:
您創建一個HTML文件,其中包含:
<html><body><div id="example"><p>{{ hello }}</p></div><script src="https://unpkg.com/vue"></script><script>new Vue({el: '#example',data: { hello: 'Hello World!' }})</script></body> </html>and you open it in the browser. That’s your first Vue app! The page should show a “Hello World!” message.
然后在瀏覽器中將其打開。 這是您的第一個Vue應用! 該頁面應顯示“ Hello World!” 信息。
I put the script tags at the end of the body so that they are executed in order after the DOM is loaded.
我將腳本標簽放在正文的末尾,以便在加載DOM之后按順序執行它們。
What this code does is instantiate a new Vue app, linked to the #example element as its template. It's defined using a CSS selector usually, but you can also pass in an HTMLElement.
該代碼的作用是實例化一個新的Vue應用程序,該應用程序鏈接到#example元素作為其模板。 通常是使用CSS選擇器定義的,但是您也可以傳入HTMLElement 。
Then, it associates that template to the data object. That is a special object that hosts the data we want Vue to render.
然后,它將該模板與data對象相關聯。 這是一個特殊的對象,用于承載我們要Vue渲染的數據。
In the template, the special {{ }} tag indicates that this is some part of the template that's dynamic, and its content should be looked up in the Vue app data.
在模板中,特殊的{{ }}標簽表示這是動態模板的一部分,應在Vue應用程序數據中查找其內容。
You can see this example on CodePen.
您可以在CodePen上看到此示例。
CodePen is a little different from using a plain HTML file, and you need to configure it to point to the Vue library location in the Pen settings:
CodePen與使用純HTML文件略有不同,您需要對其進行配置以指向Pen設置中的Vue庫位置:
第二個示例:Vue CLI默認應用 (Second example: the Vue CLI default app)
Let’s level up the game a little bit. The next app we’re going to build is already done, and it’s the Vue CLI default application.
讓我們稍微升級一下游戲。 我們將要構建的下一個應用程序已經完成,它是Vue CLI的默認應用程序。
What is the Vue CLI? It’s a command line utility that helps to speed up development by scaffolding an application skeleton for you, with a sample app in place.
什么是Vue CLI? 它是一個命令行實用程序,可通過在適當位置安裝示例應用程序來為您架設一個應用程序框架來幫助加快開發速度。
There are two ways you can get this application:
有兩種方法可以獲取此應用程序:
Use the Vue CLI locally
在本地使用Vue CLI
The first is to install the Vue CLI on your computer and run the command:
首先是在計算機上安裝Vue CLI并運行以下命令:
vue create <enter the app name>Use CodeSandbox
使用CodeSandbox
A simpler way, without having to install anything, is to go to CodeSandbox. The link opens the Vue CLI default application.
一個簡單的方法(無需安裝任何程序)是轉到CodeSandbox 。 該鏈接將打開Vue CLI默認應用程序。
CodeSandbox is a cool code editor that allows you build apps in the cloud. You can use any npm package, and can easily integrate with Zeit Now for an easy deployment and with GitHub to manage versioning.
CodeSandbox是一個很棒的代碼編輯器,可讓您在云中構建應用程序。 您可以使用任何npm軟件包,并且可以輕松地與Zeit Now集成以實現輕松部署,并可以與GitHub集成以管理版本控制。
Whether you chose to use the Vue CLI locally, or go through CodeSandbox, let’s inspect that Vue app in detail.
無論您是選擇在本地使用Vue CLI,還是通過CodeSandbox,我們都將詳細檢查該Vue應用程序。
文件結構 (The files structure)
Beside package.json, which contains the configuration, these are the files contained in the initial project structure:
在package.json (其中包含配置)旁邊,這些是初始項目結構中包含的文件:
index.html
index.html
src/App.vue
src/App.vue
src/main.js
src/main.js
src/assets/logo.png
src/assets/logo.png
src/components/HelloWorld.vue
src/components/HelloWorld.vue
index.html (index.html)
The index.html file is the main app file.
index.html文件是主應用程序文件。
In the body it includes just one simple element: <div id="app"></div>. This is the element the Vue application we’ll use to attach to the DOM.
在主體中,它僅包含一個簡單元素: <div id="app"> </ div>。 這是我們將用于附加到DOM的Vue應用程序的元素。
<!DOCTYPE html> <html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1.0"><title>CodeSandbox Vue</title> </head><body><div id="app"></div><!-- built files will be auto injected --> </body></html>src/main.js (src/main.js)
This is the main JavaScript file that drives our app.
這是驅動我們的應用程序的主要JavaScript文件。
We first import the Vue library and the App component from App.vue.
我們首先從App.vue導入Vue庫和App組件。
We set productionTip to false, to avoid Vue outputting a “you’re in development mode” tip in the console.
我們將productionTip設置為false ,以避免Vue在控制臺中輸出“您處于開發模式”提示。
Next, we create the Vue instance, by assigning it to the DOM element identified by #app, which we defined in index.html, and we tell it to use the App component.
接下來,我們通過將Vue實例分配給我們在index.html定義的#app標識的DOM元素來創建Vue實例,并告訴它使用App組件。
// The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. import Vue from 'vue' import App from './App'Vue.config.productionTip = false/* eslint-disable no-new */ new Vue({el: '#app',components: { App },template: '<App/>' })src/App.vue (src/App.vue)
App.vue is a Single File Component. It contains three chunks of code: HTML, CSS, and JavaScript.
App.vue是單個文件組件。 它包含三個代碼塊:HTML,CSS和JavaScript。
This might seem weird at first, but Single File Components are a great way to create self-contained components that have all they need in a single file.
乍一看這很奇怪,但是“單個文件組件”是創建自包含組件的好方法,這些組件可以在單個文件中包含所有需要的組件。
We have the markup, the JavaScript that is going to interact with it, and style that’s applied to it, which can be scoped or not. In this case, it’s not scoped, and it’s just outputting that CSS which is applied like regular CSS to the page.
我們具有標記,將要與之交互JavaScript以及應用于其的樣式,可以對其范圍進行限制。 在這種情況下,它沒有作用域,只是輸出了像常規CSS一樣應用到頁面CSS。
The interesting part lies in the script tag.
有趣的部分在于script標簽。
We import a component from the components/HelloWorld.vue file, which we'll describe later.
我們從components/HelloWorld.vue文件導入一個組件,稍后將對其進行描述。
This component is going to be referenced in our component. It’s a dependency. We are going to output this code
該組件將在我們的組件中引用。 這是一個依賴關系。 我們將輸出此代碼
<div id="app"><img width="25%" src="./assets/logo.png"><HelloWorld/> </div>from this component, which you see references the HelloWorld component. Vue will automatically insert that component inside this placeholder.
在該組件中,您會看到它引用了HelloWorld組件。 Vue會自動將該組件插入此占位符。
<template><div id="app"><img width="25%" src="./assets/logo.png"><HelloWorld/></div> </template><script> import HelloWorld from './components/HelloWorld'export default {name: 'App',components: {HelloWorld} } </script><style> #app {font-family: 'Avenir', Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;margin-top: 60px; } </style>src/components/HelloWorld.vue (src/components/HelloWorld.vue)
Here’s the HelloWorld component, which is included by the App component.
這是HelloWorld組件,它包含在App組件中。
This component outputs a set of links, along with a message.
該組件輸出一組鏈接以及一條消息。
Remember above we talked about CSS in App.vue, which was not scoped? The HelloWorld component has scoped CSS.
還記得上面我們討論過App.vue中CSS,但沒有限定范圍嗎? HelloWorld組件的作用域為CSS。
You can easily determine it by looking at the style tag. If it has the scoped attribute, then it's scoped: <style scoped>
您可以通過查看style標簽輕松確定它。 如果它具有scoped屬性,則它的范圍是: <style scop ed>
This means that the generated CSS will be targeting the component uniquely, via a class that’s applied by Vue transparently. You don’t need to worry about this, and you know the CSS won’t leak to other parts of the page.
這意味著生成CSS將通過Vue透明應用的類來唯一地定位組件。 您無需為此擔心,并且知道CSS不會泄漏到頁面的其他部分。
The message the component outputs is stored in the data property of the Vue instance, and outputted in the template as {{ msg }}.
組件輸出的消息存儲在Vue實例的data屬性中,并在模板中以{{ msg }} 。
Anything that’s stored in data is reachable directly in the template via its own name. We didn't need to say data.msg, just msg.
data存儲的任何內容都可以通過自己的名稱直接在模板中訪問。 我們不需要說data.msg ,只需要說msg 。
<template><div class="hello"><h1>{{ msg }}</h1><h2>Essential Links</h2><ul><li><ahref="https://vuejs.org"target="_blank">Core Docs</a></li><li><ahref="https://forum.vuejs.org"target="_blank">Forum</a></li><li><ahref="https://chat.vuejs.org"target="_blank">Community Chat</a></li><li><ahref="https://twitter.com/vuejs"target="_blank">Twitter</a></li><br><li><ahref="http://vuejs-templates.github.io/webpack/"target="_blank">Docs for This Template</a></li></ul><h2>Ecosystem</h2><ul><li><ahref="http://router.vuejs.org/"target="_blank">vue-router</a></li><li><ahref="http://vuex.vuejs.org/"target="_blank">vuex</a></li><li><ahref="http://vue-loader.vuejs.org/"target="_blank">vue-loader</a></li><li><ahref="https://github.com/vuejs/awesome-vue"target="_blank">awesome-vue</a></li></ul></div> </template><script> export default {name: 'HelloWorld',data() {return {msg: 'Welcome to Your Vue.js App'}} } </script><!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> h1, h2 {font-weight: normal; } ul {list-style-type: none;padding: 0; } li {display: inline-block;margin: 0 10px; } a {color: #42b983; } </style>運行應用 (Run the app)
CodeSandbox has a cool preview functionality. You can run the app and edit anything in the source to have it immediately reflected in the preview.
CodeSandbox具有很酷的預覽功能。 您可以運行該應用程序并編輯源代碼中的任何內容,以使其立即反映在預覽中。
Vue CLI (The Vue CLI)
CodeSandbox is very cool for online coding and working without having to setup Vue locally. A great way to work locally is by setting up the Vue CLI (command line interface). Let’s find out more about it.
CodeSandbox非常適合在線編碼和工作,而無需在本地設置Vue。 在本地工作的好方法是設置Vue CLI(命令行界面)。 讓我們進一步了解它。
In the previous example, I introduced an example project based on the Vue CLI. What’s the Vue CLI exactly, and how does it fit in the Vue ecosystem? Also, how do we setup a Vue CLI-based project locally? Let’s find out!
在上一個示例中,我介紹了一個基于Vue CLI的示例項目。 Vue CLI到底是什么,它如何適合Vue生態系統? 另外,我們如何在本地設置基于Vue CLI的項目? 讓我們找出答案!
Note: There is a huge rework of the CLI going on right now, going from version 2 to 3. While not yet stable, I will describe version 3, because it’s a huge improvement over version 2, and quite different.
注意:從版本2到版本3,現在正在對CLI進行大量修改。雖然尚不穩定,但我將介紹版本3,因為它是對版本2的巨大改進,并且有很大的不同。
安裝 (Installation)
The Vue CLI is a command line utility, and you install it globally using npm:
Vue CLI是一個命令行實用程序,您可以使用npm在全局安裝它:
npm install -g @vue/clior using Yarn:
或使用紗線:
yarn global add @vue/cliOnce you do so, you can invoke the vue command.
完成后,您可以調用vue命令。
Vue CLI提供了什么? (What does the Vue CLI provide?)
The CLI is essential for rapid Vue.js development.
CLI對于快速Vue.js開發至關重要。
Its main goal is to make sure all the tools you need are working along, to perform what you need, and abstracts away all the nitty-gritty configuration details that using each tool in isolation would require.
它的主要目標是確保所需的所有工具都可以正常工作,執行所需的工作,并抽象出單獨使用每種工具所需的所有細節。
It can perform an initial project setup and scaffolding.
它可以執行初始項目設置和腳手架。
It’s a flexible tool. Once you create a project with the CLI, you can go and tweak the configuration, without having to eject your application (like you’d do with create-react-app).
這是一個靈活的工具。 使用CLI創建項目后,就可以進行配置調整,而不必退出應用程序(就像對create-react-app )。
When you eject from create-react-app you can update and tweak what you want, but you can’t rely on the cool features that create-react-app provides.
從create-react-app彈出時,可以更新和調整所需內容,但不能依賴create-react-app提供的出色功能。
You can configure anything and still be able to upgrade with ease.
您可以進行任何配置,仍然可以輕松升級。
After you create and configure the app, it acts as a runtime dependency tool, built on top of Webpack.
創建和配置應用程序后,它充當基于Webpack的運行時依賴工具。
The first encounter with the CLI is when creating a new Vue project.
與CLI的第一次接觸是在創建新的Vue項目時。
如何使用CLI創建新的Vue項目 (How to use the CLI to create a new Vue project)
The first thing you’re going to do with the CLI is to create a Vue app:
使用CLI要做的第一件事是創建一個Vue應用程序:
vue create exampleThe cool thing is that it’s an interactive process. You need to pick a preset. By default, there is one preset that provides Babel and ESLint integration:
最酷的是,這是一個交互式過程。 您需要選擇一個預設。 默認情況下,有一個預設可提供Babel和ESLint集成:
I’m going to press the down arrow ?? and manually choose the features I want:
我將按向下箭頭??并手動選擇所需的功能:
Press space to enable one of the things you need, and then press enter to go on. Since I chose Linter / Formatter, Vue CLI prompts me for the configuration. I chose ESLint + Prettier since that's my favorite setup:
按space鍵啟用所需的功能之一,然后按enter鍵繼續。 由于我選擇了Linter / Formatter ,因此Vue CLI會提示我進行配置。 我選擇了ESLint + Prettier因為這是我最喜歡的設置:
Next thing is choosing how to apply linting. I choose Lint on save.
下一步是選擇如何應用棉絨。 我選擇Lint on save 。
Next up: testing. Vue CLI lets me choose between the two most popular unit testing solutions: Mocha + Chai and Jest.
接下來:測試。 Vue CLI讓我在兩種最受歡迎??的單元測試解決方案之間進行選擇: Mocha + Chai和Jest 。
Vue CLI asks me where to put all the configuration: in the package.json file, or in dedicated configuration files, one for each tool. I chose the latter.
Vue CLI詢問我將所有配置放在哪里:在package.json文件或專用配置文件中,每個工具一個。 我選擇了后者。
Next, Vue CLI asks me if I want to save these presets, and allows me to pick them as a choice the next time I use Vue CLI to create a new app. It’s a very convenient feature, as having a quick setup with all my preferences is a complexity reliever:
接下來,Vue CLI詢問我是否要保存這些預設,并允許我下次使用Vue CLI創建新應用時選擇它們。 這是一個非常方便的功能,因為根據我的喜好進行快速設置可以緩解復雜性:
Vue CLI then asks me if I prefer using Yarn or NPM:
然后,Vue CLI詢問我是否更喜歡使用Yarn或NPM:
This is the last thing it asks me, and then it goes on to download the dependencies and create the Vue app:
這是它問我的最后一件事,然后繼續下載依賴項并創建Vue應用程序:
如何啟動新創建的Vue CLI應用程序 (How to start the newly created Vue CLI application)
Vue CLI has created the app for us, and we can go in the example folder and run yarn serve to start up our first app in development mode:
Vue CLI已經為我們創建了應用程序,我們可以進入example文件夾并運行yarn serve以在開發模式下啟動我們的第一個應用程序:
The starter example application source contains a few files, including package.json:
入門示例應用程序源代碼包含一些文件,包括package.json :
This is where all the CLI commands are defined, including yarn serve, which we used a minute ago. The other commands are
這是定義所有CLI命令的地方,包括我們在一分鐘前使用的yarn serve 。 其他命令是
yarn build, to start a production build
yarn build ,開始生產
yarn lint, to run the linter
yarn lint
yarn test:unit, to run the unit tests
yarn test:unit ,運行單元測試
I will describe the sample application generated by Vue CLI in a separate tutorial.
我將在單獨的教程中描述由Vue CLI生成的示例應用程序。
Git倉庫 (Git repository)
Notice the master word in the lower-left corner of VS Code? That's because Vue CLI automatically creates a repository, and makes the first commit. So we can jump right in, change things, and we know what we changed:
注意VS Code左下角的master詞嗎? 這是因為Vue CLI自動創建存儲庫并進行第一次提交。 這樣我們就可以跳進去,進行更改,然后我們知道更改了什么:
This is pretty cool. How many times do you dive in and change things, only to realize, when you want to commit the result, that you didn’t commit the initial state?
這很酷。 您投入了多少次并進行了更改,才意識到,當您要提交結果時,您沒有提交初始狀態?
從命令行使用預設 (Use a preset from the command line)
You can skip the interactive panel and instruct Vue CLI to use a particular preset:
您可以跳過交互式面板,并指示Vue CLI使用特定的預設:
vue create -p favourite example-2預設存儲在哪里 (Where presets are stored)
Presets are stored in the .vuejs file in your home directory. Here's mine after creating the first "favorite" preset:
預設存儲在主目錄中的.vuejs文件中。 創建第一個“收藏夾”預設后,這是我的:
{"useTaobaoRegistry": false,"packageManager": "yarn","presets": {"favourite": {"useConfigFiles": true,"plugins": {"@vue/cli-plugin-babel": {},"@vue/cli-plugin-eslint": {"config": "prettier","lintOn": ["save"]},"@vue/cli-plugin-unit-jest": {}},"router": true,"vuex": true}} }外掛程式 (Plugins)
As you can see from reading the configuration, a preset is basically a collection of plugins, with some optional configuration.
從閱讀配置可以看到,預設基本上是插件的集合,帶有一些可選配置。
Once a project is created, you can add more plugins by using vue add:
創建項目后,您可以使用vue add添加更多插件:
vue add @vue/cli-plugin-babelAll those plugins are used in the latest version available. You can force Vue CLI to use a specific version by passing the version property:
所有這些插件均以可用的最新版本使用。 您可以通過傳遞version屬性來強制Vue CLI使用特定版本:
"@vue/cli-plugin-eslint": {"version": "^3.0.0" }This is useful if a new version has a breaking change or a bug, and you need to wait a little bit before using it.
如果新版本具有重大更改或錯誤,并且您需要稍等片刻才能使用它,這將很有用。
遠程存儲預設 (Remotely store presets)
A preset can be stored in GitHub (or on other services) by creating a repository that contains a preset.json file, which contains a single preset configuration.
通過創建一個包含一個preset.json文件的存儲庫,可以將一個預置存儲在GitHub(或其他服務)中,該文件包含一個預置配置。
Extracted from the above, I made a sample preset which contains this configuration:
從以上摘錄中,我制作了一個包含以下配置的示例預設 :
{ "useConfigFiles": true, "plugins": { "@vue/cli-plugin-babel": {}, "@vue/cli-plugin-eslint": { "config": "prettier", "lintOn": [ "save" ] }, "@vue/cli-plugin-unit-jest": {} }, "router": true, "vuex": true}It can be used to bootstrap a new application using:
可以使用以下命令來引導新應用程序:
vue create --preset flaviocopes/vue-cli-preset example3Vue CLI的另一種用法:快速原型制作 (Another use of the Vue CLI: rapid prototyping)
Up until now, I’ve explained how to use the Vue CLI to create a new project from scratch, with all the bells and whistles. But for really quick prototyping, you can create a really simple Vue application (even one that’s self-contained in a single .vue file) and serve that, without having to download all the dependencies in the node_modules folder.
到目前為止,我已經解釋了如何使用Vue CLI從頭開始創建所有項目。 但是對于真正快速的原型制作,您可以創建一個非常簡單的Vue應用程序(甚至是一個包含在單個.vue文件中的應用程序)并提供該服務,而不必下載node_modules文件夾中的所有依賴node_modules 。
How? First install the cli-service-global global package:
怎么樣? 首先安裝cli-service-global全局軟件包:
npm install -g @vue/cli-service-global//oryarn global add @vue/cli-service-globalCreate an app.vue file:
創建一個app.vue文件:
<template> <div> <h2>Hello world!</h2> <marquee>Heyyy</marquee> </div></template>and then run
然后運行
vue serve app.vueYou can serve more organized projects, composed by JavaScript and HTML files as well. Vue CLI by default uses main.js / index.js as its entry point, and you can have a package.json and any tool configuration set up. vue serve will pick it up.
您還可以提供由JavaScript和HTML文件組成的更有條理的項目。 默認情況下,Vue CLI使用main.js / index.js作為其入口點,并且您可以設置package.json和任何工具配置。 vue serve會撿起來。
Since this uses global dependencies, it’s not an optimal approach for anything more than a demonstration or quick testing.
由于這使用了全局依賴性,因此除了演示或快速測試之外,它不是最佳方法。
Running vue build will prepare the project for deployment in dist/, and will generate all the corresponding code (also for vendor dependencies).
運行vue build將為要在dist/部署的項目做好準備,并將生成所有相應的代碼(也用于供應商依賴性)。
Webpack (Webpack)
Internally, Vue CLI uses Webpack, but the configuration is abstracted and we don’t even see the config file in our folder. You can still have access to it by calling vue inspect:
在內部,Vue CLI使用Webpack,但是配置是抽象的,我們甚至在文件夾中都看不到配置文件。 您仍然可以通過調用vue inspect來訪問它:
Vue開發工具 (The Vue DevTools)
When you’re first experimenting with Vue, if you open the Browser Developer Tools, you will find this message: “Download the Vue Devtools extension for a better development experience: https://github.com/vuejs/vue-devtools"
首次嘗試使用Vue時,如果打開瀏覽器開發人員工具,則會發現以下消息:“下載Vue Devtools擴展以獲得更好的開發體驗: https : //github.com/vuejs/vue-devtools ”
This is a friendly reminder to install the Vue Devtools Extension. What’s that? Any popular framework has its own devtools extension, which generally adds a new panel to the browser developer tools that is much more specialized than the ones that the browser ships by default. In this case, the panel will let us inspect our Vue application and interact with it.
這是一個友好的提醒,請安裝Vue Devtools Extension。 那是什么? 任何流行的框架都有其自己的devtools擴展,通常會向瀏覽器開發人員工具添加一個新面板,該面板比瀏覽器默認提供的工具更加專業。 在這種情況下,面板將使我們檢查Vue應用程序并與其進行交互。
This tool will be an amazing help when building Vue apps. The developer tools can only inspect a Vue application when it’s in development mode. This makes sure no one can use them to interact with your production app — and will make Vue more performant, because it does not have to care about the Dev Tools.
構建Vue應用程序時,此工具將為您提供驚人的幫助。 開發人員工具只能在處于開發模式時檢查Vue應用程序。 這樣可以確保沒有人可以使用它們與您的生產應用程序進行交互,并且可以使Vue的性能更高,因為它不必關心開發工具。
Let’s install it!
讓我們安裝它!
There are 3 ways to install the Vue Dev Tools:
有3種安裝Vue Dev Tools的方法:
- on Chrome 在Chrome上
- on Firefox 在Firefox上
- as a standalone application 作為獨立的應用程序
Safari, Edge and other browsers are not supported with a custom extension, but using the standalone application you can debug a Vue.js app running in any browser.
自定義擴展不支持Safari,Edge和其他瀏覽器,但是使用獨立應用程序,您可以調試在任何瀏覽器中運行的Vue.js應用程序。
在Chrome上安裝 (Install on Chrome)
Go to this page on the Google Chrome Store and click Add to Chrome.
轉到Google Chrome 商店上的此頁面,然后點擊Add to Chrome 。
Go through the installation process:
完成安裝過程:
The Vue.js devtools icon shows up in the toolbar. If the page does not have a Vue.js instance running, it’s grayed out.
Vue.js devtools圖標顯示在工具欄中。 如果頁面沒有正在運行的Vue.js實例,則該頁面顯示為灰色。
If Vue.js is detected, the icon has the Vue logo’s colors.
如果檢測到Vue.js,則該圖標具有Vue徽標的顏色。
The icon does nothing except show us that there is a Vue.js instance. To use the devtools, we must open the Developer Tools panel, using “View → Developer → Developer Tools”, or Cmd-Alt-i
圖標什么也不做只是告訴我們, 有一個Vue.js實例。 要使用devtools,我們必須使用“視圖→開發人員→開發人員工具”或Cmd-Alt-i打開“開發人員工具”面板
在Firefox上安裝 (Install on Firefox)
You can find the Firefox dev tools extension in the Mozilla Add-ons store.
您可以在Mozilla附加組件商店中找到Firefox開發工具擴展。
Click “Add to Firefox” and the extension will be installed. As with Chrome, a grayed icon shows up in the toolbar
單擊“添加到Firefox”,將安裝擴展名。 與Chrome一樣,工具欄中會顯示灰色圖標
And when you visit a site that has a Vue instance running, it will become green, and when we open the Dev Tools we will see a “Vue” panel:
當您訪問正在運行Vue實例的站點時,該站點將變為綠色,并且當我們打開開發工具時,我們將看到一個“ Vue”面板:
安裝獨立應用 (Install the standalone app)
Alternatively, you can use the DevTools standalone app.
或者,您可以使用DevTools獨立應用程序。
Simply install it using:
只需使用以下命令安裝它:
npm install -g @vue/devtools//oryarn global add @vue/devtoolsand run it by calling:
并通過調用來運行它:
vue-devtoolsThis will open the standalone Electron-based application.
這將打開獨立的基于電子的應用程序。
Now, paste the script tag it shows you
現在,粘貼顯示給您的腳本標簽
<script src="http://localhost:8098"></script>inside the project index.html file, and wait for the app to be reloaded. It will automatically connect to the app.
在項目index.html文件中,然后等待應用程序重新加載。 它將自動連接到應用程序。
如何使用開發人員工具 (How to use the Developer Tools)
As mentioned, the Vue DevTools can be activated by opening the Developer Tools in the browser and moving to the Vue panel.
如前所述,可以通過在瀏覽器中打開開發人員工具并移至Vue面板來激活Vue DevTools。
Another option is to right-click on any element in the page, and choose “Inspect Vue component”:
另一個選項是右鍵單擊頁面中的任何元素,然后選擇“檢查Vue組件”:
When the Vue DevTools panel is open, we can navigate the components tree. When we choose a component from the list on the left, the right panel shows the props and data it holds:
打開Vue DevTools面板后,我們可以導航組件樹。 當我們從左側的列表中選擇一個組件時,右側面板將顯示其擁有的道具和數據:
On the top there are fourbuttons:
在頂部有四個按鈕:
Components (the current panel), which lists all the component instances running in the current page. Vue can have multiple instances running at the same time. For example, it might manage your shopping cart widget and the slideshow, with separate, lightweight apps.
組件 (當前面板),其中列出了當前頁面中運行的所有組件實例。 Vue可以同時運行多個實例。 例如,它可以使用單獨的輕型應用程序管理購物車小部件和幻燈片。
Vuex is where you can inspect the state managed through Vuex.
在Vuex中,您可以檢查通過Vuex管理的狀態。
Events shows all the events emitted.
事件顯示所有發出的事件。
Refresh reloads the devtools panel.
刷新將重新加載devtools面板。
Notice the small = $vm0 text beside a component? It's a handy way to inspect a component using the Console. Pressing the "esc" key shows up the console in the bottom of the devtools, and you can type $vm0 to access the Vue component:
注意組件旁邊的小= $vm0文本嗎? 這是使用控制臺檢查組件的便捷方法。 按下“ esc”鍵將在devtools底部顯示控制臺,您可以鍵入$vm0來訪問Vue組件:
It’s very cool to inspect and interact with components without having to assign them to a global variable in the code.
檢查組件并與之交互非常酷,而不必在代碼中將它們分配給全局變量。
過濾組件 (Filter components)
Start typing a component name, and the components tree will filter out the ones that don’t match.
開始輸入組件名稱,組件樹將過濾出不匹配的組件。
在頁面中選擇一個組件 (Select a component in the page)
Click the Select component in the page button.
單擊Select component in the page按鈕中的Select component in the page 。
You can hover over any component in the page with the mouse, click it, and it will be opened in the devtools.
您可以用鼠標懸停在頁面上的任何組件上,單擊它,然后它將在devtools中打開。
格式化組件名稱 (Format components names)
You can choose to show components in camelCase or use dashes.
您可以選擇在camelCase中顯示組件或使用破折號。
篩選檢查的數據 (Filter inspected data)
On the right panel, you can type any word to filter the properties that don’t match it.
在右側面板上,您可以輸入任何單詞以過濾不匹配的屬性。
檢查DOM (Inspect DOM)
Click the Inspect DOM button to be brought to the DevTools Elements inspector, with the DOM element generated by the component:
單擊“檢查DOM”按鈕,將其帶到DevTools Elements檢查器中,該DOM元素由組件生成:
在編輯器中打開 (Open in editor)
Any user component (not framework-level components) has a button that opens it in your default editor. Very handy.
任何用戶組件(不是框架級組件)都有一個按鈕,可以在默認編輯器中將其打開。 非常便利。
設置VS Code以與Vue一起使用 (Setup VS Code to work with Vue)
Visual Studio Code is one of the most used code editors in the world right now. Editors have, like many software products, a cycle. Once TextMate was the favorite among developers, then it was Sublime Text, now it’s VS Code.
Visual Studio Code是目前世界上最常用的代碼編輯器之一。 像許多軟件產品一樣,編輯器有一個循環。 一旦TextMate成為開發人員的最愛,那么它就是Sublime Text ,現在是VS Code。
The cool thing about being popular is that people dedicate a lot of time to building plugins for everything they can imagine.
受歡迎的有趣之處在于,人們花了很多時間來為他們可以想象的一切構建插件。
One such plugin is an awesome tool that can help us Vue.js developers.
一個這樣的插件是一個很棒的工具,可以幫助我們Vue.js開發人員。
威圖 (Vetur)
It’s called Vetur, it’s hugely popular (more than 3 million downloads), and you can find it on the Visual Studio Marketplace.
它被稱為Vetur,非常受歡迎(下載量超過300萬),您可以在Visual Studio Marketplace上找到它。
安裝Vetur (Installing Vetur)
Clicking the Install button will trigger the installation panel in VS Code:
單擊“安裝”按鈕將在VS Code中觸發安裝面板:
You can also simply open the Extensions in VS Code and search for “vetur”:
您也可以簡單地在VS Code中打開擴展,然后搜索“ vetur”:
What does this extension provide?
此擴展程序提供什么?
語法高亮 (Syntax highlighting)
Vetur provides syntax highlighting for all your Vue source code files.
Vetur為所有Vue源代碼文件提供語法高亮顯示。
Without Vetur, a .vue file will be displayed in this way by VS Code:
如果沒有Vetur,VS代碼將以這種方式顯示.vue文件:
with Vetur installed:
安裝了Vetur時:
VS Code is able to recognize the type of code contained in a file from its extension.
VS Code能夠從其擴展名識別文件中包含的代碼類型。
Using Single File Components, you can mix different types of code inside the same file, from CSS to JavaScript to HTML.
使用單個文件組件,您可以在同一文件中混合使用不同類型的代碼,從CSS到JavaScript到HTML。
VS Code by default cannot recognize this kind of situation, and Vetur provides syntax highlighting for each kind of code you use.
默認情況下,VS Code無法識別這種情況,而Vetur為您使用的每種代碼提供語法高亮顯示。
Vetur enables support, among other things, for:
Vetur支持以下方面的支持:
- HTML HTML
- CSS CSS
- JavaScript JavaScript
- Pug 哈巴狗
- Haml 哈姆
- SCSS SCSS
- PostCSS PostCSS
- Sass 薩斯
- Stylus 觸控筆
- TypeScript 打字稿
片段 (Snippets)
As with syntax highlighting, since VS Code cannot determine the kind of code contained in a part of a .vue file, it cannot provide the snippets we all love. Snippets are pieces of code we can add to the file, provided by specialized plugins.
與語法突出顯示一樣,由于VS Code無法確定.vue文件的一部分中包含的代碼類型,因此它無法提供我們都喜歡的代碼段。 代碼片段是我們可以添加到文件中的代碼片段,由專用插件提供。
Vetur gives VS Code the ability to use your favorite snippets in Single File Components.
Vetur使VS Code能夠在單個文件組件中使用您喜歡的代碼段。
智能感知 (IntelliSense)
IntelliSense is also enabled by Vetur, for each different language, with autocomplete:
Vetur還為每種不同的語言啟用了IntelliSense ,并具有自動完成功能:
腳手架 (Scaffolding)
In addition to enabling custom snippets, Vetur provides its own set of snippets. Each one creates a specific tag (template, script, or style) with its own language:
除了啟用自定義片段外,Vetur還提供了自己的片段集。 每個人都使用自己的語言創建一個特定的標簽(模板,腳本或樣式):
scaffold
scaffold
template with html
template with html
template with pug
template with pug
script with JavaScript
script with JavaScript
script with TypeScript
script with TypeScript
style with CSS
style with CSS
style with CSS (scoped)
style with CSS (scoped)
style with scss
style with scss
style with scss (scoped)
style with scss (scoped)
style with less
style with less
style with less (scoped)
style with less (scoped)
style with sass
style with sass
style with sass (scoped)
style with sass (scoped)
style with postcss
style with postcss
style with postcss (scoped)
style with postcss (scoped)
style with stylus
style with stylus
style with stylus (scoped)
style with stylus (scoped)
If you type scaffold, you'll get a starter pack for a single-file component:
如果輸入scaffold ,您將獲得一個單文件組件的入門包:
<template></template><script>export default {}</script><style></style>The others are specific and create a single block of code.
其他的則是特定的,并創建單個代碼塊。
Note: (scoped) in the above list means that it applies to the current component only.
注意:以上列表中的(作用域)意味著它僅適用于當前組件。
Emmet (Emmet)
Emmet, the popular HTML/CSS abbreviations engine, is supported by default. You can type one of the Emmet abbreviations, and by pressing tab VS Code will automatically expand it to the HTML equivalent:
默認情況下, Emmet是流行HTML / CSS縮寫引擎。 您可以輸入Emmet縮寫之一,然后按VS Code tab將其自動擴展為等效HTML:
整理和錯誤檢查 (Linting and error checking)
Vetur integrates with ESLint through the VS Code ESLint plugin.
Vetur通過VS Code ESLint插件與ESLint集成。
代碼格式化 (Code Formatting)
Vetur provides automatic support for code formatting to format the whole file upon save — in combination with the "editor.formatOnSave" VS Code setting.
Vetur為代碼格式化提供自動支持,以在保存時對整個文件進行格式化-結合"editor.formatOnSave" VS Code設置。
You can choose to disable automatic formatting for some specific languages by setting the vetur.format.defaultFormatter.XXXXX to none in the VS Code settings. To change one of those settings, just start searching for the string, and override what you want in the user settings on the right panel.
您可以通過在VS Code設置vetur.format.defaultFormatter.XXXXX設置為none來選擇禁用某些特定語言的自動格式設置。 要更改這些設置之一,只需開始搜索字符串,然后在右側面板的用戶設置中覆蓋所需的內容即可。
Most of the languages supported use Prettier for automatic formatting, a tool that’s becoming an industry standard. It uses your Prettier configuration to determine your preferences.
支持的大多數語言都使用Prettier進行自動格式化,該工具已成為行業標準。 它使用您的Prettier配置來確定您的首選項。
介紹Vue組件 (Introducing Vue Components)
Components are single, independent units of an interface. They can have their own state, markup, and style.
組件是接口的單個??獨立單元。 他們可以具有自己的狀態,標記和樣式。
如何使用組件 (How to use components)
Vue components can be defined in four main ways. Let’s talk in code.
Vue組件可以通過四種主要方式進行定義。 讓我們談談代碼。
The first is:
第一個是:
new Vue({ /* options */})The second is:
第二個是:
Vue.component('component-name', { /* options */})The third is by using local components. These are components that are only accessible by a specific component, and not available elsewhere (great for encapsulation).
第三是通過使用本地組件。 這些是只能由特定組件訪問的組件,而在其他地方則不可用(非常適合封裝)。
The fourth is in .vue files, also called Single File Components.
第四個位于.vue文件中,也稱為“單個文件組件”。
Let’s dive into the first 3 ways in detail.
讓我們詳細介紹前三種方式。
Using new Vue() or Vue.component() is the standard way to use Vue when you're building an application that is not a Single Page Application (SPA). You use this method, rather, when you’re just using Vue.js in some pages, like in a contact form or in the shopping cart. Or maybe Vue is used in all pages, but the server is rendering the layout, and you serve the HTML to the client, which then loads the Vue application you build.
在構建不是單頁應用程序(SPA)的應用程序時,使用new Vue()或Vue.component()是使用Vue的標準方法。 相反,當您僅在某些頁面中使用Vue.js(例如在聯系表單或購物車中)時,就使用此方法。 也許在所有頁面中都使用了Vue,但是服務器正在渲染布局,然后您將HTML提供給客戶端,然后客戶端將加載您構建的Vue應用程序。
In an SPA, where it’s Vue that builds the HTML, it’s more common to use Single File Components as they are more convenient.
在SPA中,是由Vue構建HTML的,使用單文件組件更為方便,因此更為常見。
You instantiate Vue by mounting it on a DOM element. If you have a <div id="app"></div> tag, you will use:
您可以通過將Vue安裝在DOM元素上來實例化Vue。 如果您有<div id="app"> </ div>標記,則將使用:
new Vue({ el: '#app' })A component initialized with new Vue has no corresponding tag name, so it's usually the main container component.
用new Vue初始化的組件沒有相應的標簽名稱,因此通常是主要的容器組件。
Other components used in the application are initialized using Vue.component(). Such a component allows you to define a tag — with which you can embed the component multiple times in the application — and specify the output of the component in the template property:
使用Vue.component()初始化應用程序中使用的其他組件。 這樣的組件允許您定義一個標記(您可以使用該標記在應用程序中多次嵌入該組件),并在template屬性中指定該組件的輸出:
<div id="app"> <user-name name="Flavio"></user-name></div>Vue.component('user-name', { props: ['name'], template: '<p>Hi {{ name }}</p>'})new Vue({ el: '#app'})See on JSFiddle
在JSFiddle上查看
What are we doing? We are initializing a Vue root component on #app, and inside that, we use the Vue component user-name, which abstracts our greeting to the user.
我們在做什么? 我們正在#app上初始化Vue根組件,在其中,我們使用Vue組件user-name ,它抽象了向用戶的問候。
The component accepts a prop, which is an attribute we use to pass data down to child components.
組件接受道具,這是我們用來將數據向下傳遞給子組件的屬性。
In the Vue.component() call we passed user-name as the first parameter. This gives the component a name. You can write the name in 2 ways here. The first is the one we used, called kebab-case. The second is called PascalCase, which is like camelCase, but with the first letter capitalized:
在Vue.component()調用中,我們傳遞了user-name作為第一個參數。 這為組件命名。 您可以在此處以兩種方式輸入名稱。 第一個是我們使用的那個,叫做kebab-case。 第二個稱為PascalCase,類似于camelCase,但是第一個字母大寫:
Vue.component('UserName', { /* ... */})Vue automatically creates an alias internally from user-name to UserName, and vice versa, so you can use whatever you like. It's generally best to use UserName in the JavaScript, and user-name in the template.
Vue會在內部從user-name到UserName自動創建別名,反之亦然,因此您可以隨意使用。 通常最好在JavaScript中使用UserName ,在模板中使用user-name 。
本地組件 (Local components)
Any component created using Vue.component() is globally registered. You don't need to assign it to a variable or pass it around to reuse it in your templates.
使用Vue.component()創建的任何組件都是全局注冊的。 您無需將其分配給變量或將其傳遞以在模板中重復使用。
You can encapsulate components locally by assigning an object that defines the component object to a variable:
您可以通過將定義組件對象的對象分配給變量來在本地封裝組件:
const Sidebar = { template: '<aside>Sidebar</aside>'}and then make it available inside another component by using the components property:
然后使用components屬性使其在另一個組件內部可用:
new Vue({ el: '#app', components: { Sidebar }})You can write the component in the same file, but a great way to do this is to use JavaScript modules:
您可以在同一文件中編寫組件,但是一種很好的方法是使用JavaScript模塊:
import Sidebar from './Sidebar'export default { el: '#app', components: { Sidebar }}重用組件 (Reusing a component)
A child component can be added multiple times. Each separate instance is independent of the others:
子組件可以添加多次。 每個單獨的實例都獨立于其他實例:
<div id="app"> <user-name name="Flavio"></user-name> <user-name name="Roger"></user-name> <user-name name="Syd"></user-name></div>Vue.component('user-name', { props: ['name'], template: '<p>Hi {{ name }}</p>'})new Vue({ el: '#app'})See on JSFiddle
在JSFiddle上查看
組件的組成部分 (The building blocks of a component)
So far we’ve seen how a component can accept the el, props and template properties.
到目前為止,我們已經看到了組件如何接受el , props和template屬性。
el is only used in root components initialized using new Vue({}), and identifies the DOM element the component will mount on.
el僅在使用new Vue({})初始化的根組件中使用,并標識組件將安裝在其上的DOM元素。
props lists all the properties that we can pass down to a child component
props列出了我們可以傳遞給子組件的所有屬性
template is where we can set up the component template, which will be responsible for defining the output the component generates.
template是我們可以在其中設置組件模板的地方,它將負責定義組件生成的輸出。
A component accepts other properties:
組件接受其他屬性:
data the component local state
data組件本地狀態
methods: the component methods
methods :組件方法
computed: the computed properties associated with the component
computed :與組件關聯的計算屬性
watch: the component watchers
watch :組件觀察者
單個文件組件 (Single File Components)
A Vue component can be declared in a JavaScript file (.js) like this:
可以在JavaScript文件( .js )中聲明Vue組件,如下所示:
Vue.component('component-name', { /* options */})or also:
或者:
new Vue({ /* options */})or it can be specified in a .vue file.
或者可以在.vue文件中指定。
The .vue file is pretty cool because it allows you to define:
.vue文件非常酷,因為它允許您定義:
- JavaScript logic JavaScript邏輯
- HTML code template HTML代碼模板
- CSS styling CSS樣式
all in just a single file. As such it got the name of Single File Component.
全部都在一個文件中。 因此,它的名稱為“單個文件組件”。
Here’s an example:
這是一個例子:
<template> <p>{{ hello }}</p></template><script>export default { data() { return { hello: 'Hello World!' } }}</script><style scoped> p { color: blue; }</style>All of this is possible thanks to the use of Webpack. The Vue CLI makes this very easy and supported out of the box. .vuefiles cannot be used without a Webpack setup, and as such, they are not very suited to apps that just use Vue on a page without being a full-blown single-page app (SPA).
由于使用了Webpack,所有這些都是可能的。 Vue CLI使得此操作非常容易,并且開箱即用。 .vue文件必須在沒有Webpack設置的情況下才能使用,因此,它們非常不適合僅在頁面上使用Vue而又不是完整的單頁應用程序(SPA)的應用程序。
Since Single File Components rely on Webpack, we get for free the ability to use modern Web features.
由于單個文件組件依賴Webpack,因此我們免費獲得了使用現代Web功能的功能。
Your CSS can be defined using SCSS or Stylus, the template can be built using Pug, and all you need to do to make this happen is to declare to Vue which language preprocessor you are going to use.
可以使用SCSS或Stylus定義CSS,可以使用Pug構建模板,而要做的就是向Vue聲明要使用哪種語言預處理器。
The list of supported preprocessors include
支持的預處理器列表包括
- TypeScript 打字稿
- SCSS SCSS
- Sass 薩斯
- Less 減
- PostCSS PostCSS
- Pug 哈巴狗
We can use modern JavaScript (ES6–7–8) regardless of the target browser using the Babel integration, and ES Modules too, so we can use import/export statements.
We can use modern JavaScript (ES6–7–8) regardless of the target browser using the Babel integration, and ES Modules too, so we can use import/export statements.
We can use CSS Modules to scope our CSS.
We can use CSS Modules to scope our CSS.
Speaking of scoping CSS, Single File Components make it absolutely easy to write CSS that won’t leak to other components, by using <style scoped> tags.
Speaking of scoping CSS, Single File Components make it absolutely easy to write CSS that won't leak to other components, by using <style scop ed> tags.
If you omit scoped, the CSS you define will be global. But adding the scoped tag, Vue automatically adds a specific class to the component, unique to your app, so the CSS is guaranteed to not leak out to other components.
If you omit scoped , the CSS you define will be global. But adding the scoped tag, Vue automatically adds a specific class to the component, unique to your app, so the CSS is guaranteed to not leak out to other components.
Maybe your JavaScript is huge because of some logic you need to take care of. What if you want to use a separate file for your JavaScript?
Maybe your JavaScript is huge because of some logic you need to take care of. What if you want to use a separate file for your JavaScript?
You can use the src attribute to externalize it:
You can use the src attribute to externalize it:
<template> <p>{{ hello }}</p></template><script src="./hello.js"></script>This also works for your CSS:
This also works for your CSS:
<template> <p>{{ hello }}</p></template><script src="./hello.js"></script><style src="./hello.css"></style>Notice how I used
Notice how I used
export default { data() { return { hello: 'Hello World!' } }}in the component’s JavaScript to set up the data.
in the component's JavaScript to set up the data.
Other common ways you will see are:
Other common ways you will see are:
export default { data: function() { return { name: 'Flavio' } }}The above is equivalent to what we did before.
The above is equivalent to what we did before.
Or:
要么:
export default { data: () => { return { name: 'Flavio' } }}This is different, because it uses an arrow function. Arrow functions are fine until we need to access a component method. This is an issue if we need to make use of this, and such property is not bound to the component using arrow functions. So it's mandatory to use regular functions rather than arrow functions.
This is different, because it uses an arrow function. Arrow functions are fine until we need to access a component method. This is an issue if we need to make use of this , and such property is not bound to the component using arrow functions. So it's mandatory to use regular functions rather than arrow functions.
You might also see:
You might also see:
module.exports = { data: () => { return { name: 'Flavio' } }}This is using the CommonJS syntax and it works as well. But I recommend using the ES Modules syntax, as that is a JavaScript standard.
This is using the CommonJS syntax and it works as well. But I recommend using the ES Modules syntax, as that is a JavaScript standard.
Vue Templates (Vue Templates)
Vue.js uses a templating language that’s a superset of HTML.
Vue.js uses a templating language that's a superset of HTML.
Any HTML is a valid Vue.js template. In addition to that, Vue.js provides two powerful things: interpolation and directives.
Any HTML is a valid Vue.js template. In addition to that, Vue.js provides two powerful things: interpolation and directives.
This is a valid Vue.js template:
This is a valid Vue.js template:
<span>Hello!</span>This template can be put inside a Vue component declared explicitly:
This template can be put inside a Vue component declared explicitly:
new Vue({ template: '<span>Hello!</span>'})or it can be put into a Single File Component:
or it can be put into a Single File Component:
<template> <span>Hello!</span></template>This first example is very basic. The next step is making it output a piece of the component state, for example, a name.
This first example is very basic. The next step is making it output a piece of the component state, for example, a name.
This can be done using interpolation. First, we add some data to our component:
This can be done using interpolation. First, we add some data to our component:
new Vue({ data: { name: 'Flavio' }, template: '<span>Hello!</span>' })and then we can add it to our template using the double brackets syntax:
and then we can add it to our template using the double brackets syntax:
new Vue({ data: { name: 'Flavio' }, template: '<span>Hello {{name}}!</span>'})One interesting thing here. See how we just used name instead of this.data.name?
One interesting thing here. See how we just used name instead of this.data.name ?
This is because Vue.js does some internal binding and lets the template use the property as if it was local. Pretty handy.
This is because Vue.js does some internal binding and lets the template use the property as if it was local. 很方便。
In a single file component, that would be:
In a single file component, that would be:
<template> <span>Hello {{name}}!</span></template><script>export default { data() { return { name: 'Flavio' } }}</script>I used a regular function in my export. Why not an arrow function?
I used a regular function in my export. Why not an arrow function?
This is because in data we might need to access a method in our component instance, and we can't do that if this is not bound to the component, so we can’t use an arrow function.
This is because in data we might need to access a method in our component instance, and we can't do that if this is not bound to the component, so we can't use an arrow function.
Do note that we could use an arrow function, but then I would need to remember to switch to a regular function in case I use this. Better play it safe, I think.
Do note that we could use an arrow function, but then I would need to remember to switch to a regular function in case I use this . Better play it safe, I think.
Now, back to the interpolation.
Now, back to the interpolation.
{{ name }} should remind you of Mustache / Handlebars template interpolation, but it's just a visual reminder.
{{ name }} should remind you of Mustache / Handlebars template interpolation, but it's just a visual reminder.
While in those templating engines they are “dumb”, in Vue, you can do much more, and it’s more flexible.
While in those templating engines they are “dumb”, in Vue, you can do much more, and it's more flexible.
You can use any JavaScript expression inside your interpolations, but you’re limited to just one expression:
You can use any JavaScript expression inside your interpolations, but you're limited to just one expression:
{{ name.reverse() }}{{ name === 'Flavio' ? 'Flavio' : 'stranger' }}Vue provides access to some global objects inside templates, including Math and Date, so you can use them:
Vue provides access to some global objects inside templates, including Math and Date, so you can use them:
{{ Math.sqrt(16) * Math.random() }}It’s best to avoid adding complex logic to templates, but the fact that Vue allows it gives us more flexibility, especially when trying things out.
It's best to avoid adding complex logic to templates, but the fact that Vue allows it gives us more flexibility, especially when trying things out.
We can first try to put an expression in the template, and then move it to a computed property or method later on.
We can first try to put an expression in the template, and then move it to a computed property or method later on.
The value included in any interpolation will be updated upon a change of any of the data properties it relies on.
The value included in any interpolation will be updated upon a change of any of the data properties it relies on.
You can avoid this reactivity by using the v-once directive.
You can avoid this reactivity by using the v-once directive.
The result is always escaped, so you can’t have HTML in the output.
The result is always escaped, so you can't have HTML in the output.
If you need to have an HTML snippet, you need to use the v-html directive instead.
If you need to have an HTML snippet, you need to use the v-html directive instead.
Styling components using CSS (Styling components using CSS)
The simplest option to add CSS to a Vue.js component is to use the style tag, just like in HTML:
The simplest option to add CSS to a Vue.js component is to use the style tag, just like in HTML:
<template> <p style="text-decoration: underline">Hi!</p></template><script>export default { data() { return { decoration: 'underline' } }}</script>This is as static as you can get. What if you want underline to be defined in the component data? Here's how you can do it:
This is as static as you can get. What if you want underline to be defined in the component data? 方法如下:
<template> <p :style="{'text-decoration': decoration}">Hi!</p></template><script>export default { data() { return { decoration: 'underline' } }}</script>:style is a shorthand for v-bind:style. I'll use this shorthand throughout this tutorial.
:style is a shorthand for v-bind:style . I'll use this shorthand throughout this tutorial.
Notice how we had to wrap text-decoration in quotes. This is because of the dash, which is not part of a valid JavaScript identifier.
Notice how we had to wrap text-decoration in quotes. This is because of the dash, which is not part of a valid JavaScript identifier.
You can avoid the quotes by using a special camelCase syntax that Vue.js enables, and rewriting it to textDecoration:
You can avoid the quotes by using a special camelCase syntax that Vue.js enables, and rewriting it to textDecoration :
<template> <p :style="{textDecoration: decoration}">Hi!</p></template>Instead of binding an object to style, you can reference a computed property:
Instead of binding an object to style , you can reference a computed property:
<template> <p :style="styling">Hi!</p></template><script>export default { data() { return { textDecoration: 'underline', textWeight: 'bold' } }, computed: { styling: function() { return { textDecoration: this.textDecoration, textWeight: this.textWeight } } }}</script>Vue components generate plain HTML, so you can choose to add a class to each element, and add a corresponding CSS selector with properties that style it:
Vue components generate plain HTML, so you can choose to add a class to each element, and add a corresponding CSS selector with properties that style it:
<template> <p class="underline">Hi!</p></template><style>.underline { text-decoration: underline; }</style>You can use SCSS like this:
You can use SCSS like this:
<template> <p class="underline">Hi!</p></template><style lang="scss">body { .underline { text-decoration: underline; }}</style>You can hard code the class like in the above example. Or you can bind the class to a component property, to make it dynamic, and only apply to that class if the data property is true:
You can hard code the class like in the above example. Or you can bind the class to a component property, to make it dynamic, and only apply to that class if the data property is true:
<template> <p :class="{underline: isUnderlined}">Hi!</p></template><script>export default { data() { return { isUnderlined: true } }}</script><style>.underline { text-decoration: underline; }</style>Instead of binding an object to class, like we did with <p :class="{text: isText}">Hi!</p>, you can directly bind a string, and that will reference a data property:
Instead of binding an object to class, like we did with <p :class="{text: isText}">H i!</p>, you can directly bind a string, and that will reference a data property:
<template> <p :class="paragraphClass">Hi!</p></template><script>export default { data() { return { paragraphClass: 'underline' } }}</script><style>.underline { text-decoration: underline; }</style>You can assign multiple classes, either by adding two classes to paragraphClass in this case or by using an array:
You can assign multiple classes, either by adding two classes to paragraphClass in this case or by using an array:
<template> <p :class="[decoration, weight]">Hi!</p></template><script>export default { data() { return { decoration: 'underline', weight: 'weight', } }}</script><style>.underline { text-decoration: underline; }.weight { font-weight: bold; }</style>The same can be done using an object inlined in the class binding:
The same can be done using an object inlined in the class binding:
<template> <p :class="{underline: isUnderlined, weight: isBold}">Hi!</p></template><script>export default { data() { return { isUnderlined: true, isBold: true } }}</script><style>.underline { text-decoration: underline; }.weight { font-weight: bold; }</style>And you can combine the two statements:
And you can combine the two statements:
<template> <p :class="[decoration, {weight: isBold}]">Hi!</p></template><script>export default { data() { return { decoration: 'underline', isBold: true } }}</script><style>.underline { text-decoration: underline; }.weight { font-weight: bold; }</style>You can also use a computed property that returns an object, which works best when you have many CSS classes to add to the same element:
You can also use a computed property that returns an object, which works best when you have many CSS classes to add to the same element:
<template> <p :class="paragraphClasses">Hi!</p></template><script>export default { data() { return { isUnderlined: true, isBold: true } }, computed: { paragraphClasses: function() { return { underlined: this.isUnderlined, bold: this.isBold } } }}</script><style>.underlined { text-decoration: underline; }.bold { font-weight: bold; }</style>Notice that in the computed property you need to reference the component data using this.[propertyName], while in the template data, properties are conveniently put as first-level properties.
Notice that in the computed property you need to reference the component data using this.[propertyName] , while in the template data, properties are conveniently put as first-level properties.
Any CSS that’s not hard coded like in the first example is going to be processed by Vue, and Vue does the nice job of automatically prefixing the CSS for us. This allows us to write clean CSS while still targeting older browsers (which still means browsers that Vue supports, so IE9+).
Any CSS that's not hard coded like in the first example is going to be processed by Vue, and Vue does the nice job of automatically prefixing the CSS for us. This allows us to write clean CSS while still targeting older browsers (which still means browsers that Vue supports, so IE9+).
指令 (Directives)
We saw in Vue.js templates and interpolations how you can embed data in Vue templates.
We saw in Vue.js templates and interpolations how you can embed data in Vue templates.
This section explains the other technique offered by Vue.js in templates: directives.
This section explains the other technique offered by Vue.js in templates: directives.
Directives are basically like HTML attributes which are added inside templates. They all start with v-, to indicate that's a Vue special attribute.
Directives are basically like HTML attributes which are added inside templates. They all start with v- , to indicate that's a Vue special attribute.
Let’s see each of the Vue directives in detail.
Let's see each of the Vue directives in detail.
v-text (v-text)
Instead of using interpolation, you can use the v-text directive. It performs the same job:
Instead of using interpolation, you can use the v-text directive. It performs the same job:
<span v-text="name"></span>v-once (v-once)
You know how {{ name }} binds to the name property of the component data.
You know how {{ name }} binds to the name property of the component data.
Any time name changes in your component data, Vue is going to update the value represented in the browser.
Any time name changes in your component data, Vue is going to update the value represented in the browser.
Unless you use the v-once directive, which is basically like an HTML attribute:
Unless you use the v-once directive, which is basically like an HTML attribute:
<span v-once>{{ name }}</span>v-html (v-html)
When you use interpolation to print a data property, the HTML is escaped. This is a great way that Vue uses to automatically protect from XSS attacks.
When you use interpolation to print a data property, the HTML is escaped. This is a great way that Vue uses to automatically protect from XSS attacks.
There are cases, however, where you want to output HTML and make the browser interpret it. You can use the v-htmldirective:
There are cases, however, where you want to output HTML and make the browser interpret it. You can use the v-html directive:
<span v-html="someHtml"></span>v-bind (v-bind)
Interpolation only works in the tag content. You can’t use it on attributes.
Interpolation only works in the tag content. You can't use it on attributes.
Attributes must use v-bind:
Attributes must use v-bind :
<a v-bind:href="url">{{ linkText }}</a>v-bind is so common that there is a shorthand syntax for it:
v-bind is so common that there is a shorthand syntax for it:
<a v-bind:href="url">{{ linkText }}</a><a :href="url">{{ linkText }}</a>Two-way binding using v-model (Two-way binding using v-model)
v-model lets us bind a form input element for example, and makes it change the Vue data property when the user changes the content of the field:
v-model lets us bind a form input element for example, and makes it change the Vue data property when the user changes the content of the field:
<input v-model="message" placeholder="Enter a message"><p>Message is: {{ message }}</p><select v-model="selected"> <option disabled value="">Choose a fruit</option> <option>Apple</option> <option>Banana</option> <option>Strawberry</option></select><span>Fruit chosen: {{ selected }}</span>Using expressions (Using expressions)
You can use any JavaScript expression inside a directive:
You can use any JavaScript expression inside a directive:
<span v-text="'Hi, ' + name + '!'"></span><a v-bind:href="'https://' + domain + path">{{ linkText }}</a>Any variable used in a directive references the corresponding data property.
Any variable used in a directive references the corresponding data property.
有條件的 (Conditionals)
Inside a directive you can use the ternary operator to perform a conditional check, since that’s an expression:
Inside a directive you can use the ternary operator to perform a conditional check, since that's an expression:
<span v-text="name == Flavio ? 'Hi Flavio!' : 'Hi' + name + '!'"></span>There are dedicated directives that allow you to perform more organized conditionals: v-if, v-else and v-else-if.
There are dedicated directives that allow you to perform more organized conditionals: v-if , v-else and v-else-if .
<p v-if="shouldShowThis">Hey!</p>shouldShowThis is a boolean value contained in the component's data.
shouldShowThis is a boolean value contained in the component's data.
循環 (Loops)
v-for allows you to render a list of items. Use it in combination with v-bind to set the properties of each item in the list.
v-for allows you to render a list of items. Use it in combination with v-bind to set the properties of each item in the list.
You can iterate on a simple array of values:
You can iterate on a simple array of values:
<template> <ul> <li v-for="item in items">{{ item }}</li> </ul></template><script>export default { data() { return { items: ['car', 'bike', 'dog'] } }}</script>Or on an array of objects:
Or on an array of objects:
<template> <div> <!-- using interpolation --> <ul> <li v-for="todo in todos">{{ todo.title }}</li> </ul> <!-- using v-text --> <ul> <li v-for="todo in todos" v-text="todo.title"></li> </ul> </div></template><script>export default { data() { return { todos: [ { id: 1, title: 'Do something' }, { id: 2, title: 'Do something else' } ] } }}</script>v-for can give you the index using:
v-for can give you the index using:
<li v-for="(todo, index) in todos"></li>大事記 (Events)
v-on allows you to listen to DOM events, and trigger a method when the event happens. Here we listen for a click event:
v-on allows you to listen to DOM events, and trigger a method when the event happens. Here we listen for a click event:
<template> <a v-on:click="handleClick">Click me!</a></template><script>export default { methods: { handleClick: function() { alert('test') } }}</script>You can pass parameters to any event:
You can pass parameters to any event:
<template> <a v-on:click="handleClick('test')">Click me!</a></template><script>export default { methods: { handleClick: function(value) { alert(value) } }}</script>Small bits of JavaScript (a single expression) can be put directly into the template:
Small bits of JavaScript (a single expression) can be put directly into the template:
<template> <a v-on:click="counter = counter + 1">{{counter}}</a></template><script>export default { data: function() { return { counter: 0 } }}</script>click is just one kind of event. A common event is submit, which you can bind using v-on:submit.
click is just one kind of event. A common event is submit , which you can bind using v-on:submit .
v-on is so common that there is a shorthand syntax for it, @:
v-on is so common that there is a shorthand syntax for it, @ :
<a v-on:click="handleClick">Click me!</a><a @click="handleClick">Click me!</a>Show or hide (Show or hide)
You can choose to only show an element in the DOM if a particular property of the Vue instance evaluates to true, using v-show:
You can choose to only show an element in the DOM if a particular property of the Vue instance evaluates to true, using v-show :
<p v-show="isTrue">Something</p>The element is still inserted in the DOM, but set to display: none if the condition is not satisfied.
The element is still inserted in the DOM, but set to display: none if the condition is not satisfied.
Event directive modifiers (Event directive modifiers)
Vue offers some optional event modifiers you can use in association with v-on, which automatically make the event do something without you explicitly coding it in your event handler.
Vue offers some optional event modifiers you can use in association with v-on , which automatically make the event do something without you explicitly coding it in your event handler.
One good example is .prevent, which automatically calls preventDefault() on the event.
One good example is .prevent , which automatically calls preventDefault() on the event.
In this case, the form does not cause the page to be reloaded, which is the default behavior:
In this case, the form does not cause the page to be reloaded, which is the default behavior:
<form v-on:submit.prevent="formSubmitted"></form>Other modifiers include .stop, .capture, .self, .once, .passive and they are described in detail in the official docs.
Other modifiers include .stop , .capture , .self , .once , .passive and they are described in detail in the official docs .
Custom directives (Custom directives)
The Vue default directives already let you do a lot of work, but you can always add new, custom directives if you want.
The Vue default directives already let you do a lot of work, but you can always add new, custom directives if you want.
Read here if you’re interested in learning more.
Read here if you're interested in learning more.
方法 (Methods)
What are Vue.js methods? (What are Vue.js methods?)
A Vue method is a function associated with the Vue instance.
A Vue method is a function associated with the Vue instance.
Methods are defined inside the methods property:
Methods are defined inside the methods property:
new Vue({ methods: { handleClick: function() { alert('test') } }})or in the case of Single File Components:
or in the case of Single File Components:
<script>export default { methods: { handleClick: function() { alert('test') } }}</script>Methods are especially useful when you need to perform an action and you attach a v-on directive on an element to handle events. Like this one, which calls handleClick when the element is clicked:
Methods are especially useful when you need to perform an action and you attach a v-on directive on an element to handle events. Like this one, which calls handleClick when the element is clicked:
<template> <a @click="handleClick">Click me!</a></template>Pass parameters to Vue.js methods (Pass parameters to Vue.js methods)
Methods can accept parameters.
Methods can accept parameters.
In this case, you just pass the parameter in the template:
In this case, you just pass the parameter in the template:
<template> <a @click="handleClick('something')">Click me!</a></template>new Vue({ methods: { handleClick: function(text) { alert(text) } }})or in the case of Single File Components:
or in the case of Single File Components:
<script>export default { methods: { handleClick: function(text) { alert(text) } }}</script>How to access data from a method (How to access data from a method)
You can access any of the data properties of the Vue component by using this.propertyName:
You can access any of the data properties of the Vue component by using this.propertyName :
<template> <a @click="handleClick()">Click me!</a></template><script>export default { data() { return { name: 'Flavio' } }, methods: { handleClick: function() { console.log(this.name) } }}</script>We don’t have to use this.data.name, just this.name. Vue does provide a transparent binding for us. Using this.data.name will raise an error.
We don't have to use this.data.name , just this.name . Vue does provide a transparent binding for us. Using this.data.name will raise an error.
As you saw before in the events description, methods are closely interlinked to events, because they are used as event handlers. Every time an event occurs, that method is called.
As you saw before in the events description, methods are closely interlinked to events, because they are used as event handlers. Every time an event occurs, that method is called.
Watchers (Watchers)
A watcher is a special Vue.js feature that allows you to spy on one property of the component state, and run a function when that property value changes.
A watcher is a special Vue.js feature that allows you to spy on one property of the component state, and run a function when that property value changes.
Here’s an example. We have a component that shows a name, and allows you to change it by clicking a button:
這是一個例子。 We have a component that shows a name, and allows you to change it by clicking a button:
<template> <p>My name is {{name}}</p> <button @click="changeName()">Change my name!</button></template><script>export default { data() { return { name: 'Flavio' } }, methods: { changeName: function() { this.name = 'Flavius' } }}</script>When the name changes we want to do something, like print a console log.
When the name changes we want to do something, like print a console log.
We can do so by adding to the watch object a property named as the data property we want to watch over:
We can do so by adding to the watch object a property named as the data property we want to watch over:
<script>export default { data() { return { name: 'Flavio' } }, methods: { changeName: function() { this.name = 'Flavius' } }, watch: { name: function() { console.log(this.name) } }}</script>The function assigned to watch.name can optionally accept 2 parameters. The first is the new property value. The second is the old property value:
The function assigned to watch.name can optionally accept 2 parameters. The first is the new property value. The second is the old property value:
<script>export default { /* ... */ watch: { name: function(newValue, oldValue) { console.log(newValue, oldValue) } }}</script>Watchers cannot be looked up from a template as you can with computed properties.
Watchers cannot be looked up from a template as you can with computed properties.
Computed Properties (Computed Properties)
What is a Computed Property (What is a Computed Property)
In Vue.js you can output any data value using parentheses:
In Vue.js you can output any data value using parentheses:
<template> <p>{{ count }}</p></template><script>export default { data() { return { count: 1 } }}</script>This property can host some small computations. For example:
This property can host some small computations. 例如:
<template> {{ count * 10 }}</template>But you’re limited to a single JavaScript expression.
But you're limited to a single JavaScript expression .
In addition to this technical limitation, you also need to consider that templates should only be concerned with displaying data to the user, not perform logic computations.
In addition to this technical limitation, you also need to consider that templates should only be concerned with displaying data to the user, not perform logic computations.
To do something more than a single expression, and to have more declarative templates, you use a computed property.
To do something more than a single expression, and to have more declarative templates, you use a computed property.
Computed properties are defined in the computed property of the Vue component:
Computed properties are defined in the computed property of the Vue component:
<script>export default { computed: {}}</script>An example of a computed property (An example of a computed property)
Here’s an example that uses a computed property count to calculate the output.
Here's an example that uses a computed property count to calculate the output.
Notice:
注意:
I didn’t have to call {{ count() }}. Vue.js automatically invokes the function
I didn't have to call {{ count() }} . Vue.js automatically invokes the function
I used a regular function (not an arrow function) to define the count computed property, because I need to be able to access the component instance through this.
I used a regular function (not an arrow function) to define the count computed property, because I need to be able to access the component instance through this .
Computed properties vs. methods (Computed properties vs. methods)
If you already know about Vue methods, you may wonder what’s the difference.
If you already know about Vue methods, you may wonder what's the difference.
First, methods must be called, not just referenced, so you’d need to do:
First, methods must be called, not just referenced, so you'd need to do:
<template> <p>{{ count() }}</p></template><script>export default { data() { return { items: [1, 2, 3] } }, methods: { count: function() { return 'The count is ' + this.items.length * 10 } }}</script>But the main difference is that computed properties are cached.
But the main difference is that computed properties are cached.
The result of the count computed property is internally cached until the items data property changes.
The result of the count computed property is internally cached until the items data property changes.
Important: Computed properties are only updated when a reactive source updates. Regular JavaScript methods are not reactive, so a common example is to use Date.now():
Important: Computed properties are only updated when a reactive source updates. Regular JavaScript methods are not reactive, so a common example is to use Date.now() :
<template> <p>{{ now }}</p></template><script>export default { computed: { now: function () { return Date.now() } }}</script>It will render once, and then it will not be updated even when the component re-renders. It’s just updated on a page refresh, when the Vue component is quit and reinitialized.
It will render once, and then it will not be updated even when the component re-renders. It's just updated on a page refresh, when the Vue component is quit and reinitialized.
In this case, a method is better suited for your needs.
In this case, a method is better suited for your needs.
Methods vs. Watchers vs. Computed Properties (Methods vs. Watchers vs. Computed Properties)
Now that you know about methods, watchers and computed properties, you might be wondering when should you use one vs the others.
Now that you know about methods, watchers and computed properties, you might be wondering when should you use one vs the others.
Here’s a breakdown of this question.
Here's a breakdown of this question.
When to use methods (When to use methods)
- To react to some event happening in the DOM To react to some event happening in the DOM
To call a function when something happens in your component.
To call a function when something happens in your component.
You can call a method from computed properties or watchers.
You can call a method from computed properties or watchers.
When to use computed properties (When to use computed properties)
- You need to compose new data from existing data sources You need to compose new data from existing data sources
- You have a variable you use in your template that’s built from one or more data properties You have a variable you use in your template that's built from one or more data properties
- You want to reduce a complicated, nested property name to a more readable and easy to use one (but update it when the original property changes) You want to reduce a complicated, nested property name to a more readable and easy to use one (but update it when the original property changes)
- You need to reference a value from the template. In this case, creating a computed property is the best thing, because it’s cached. You need to reference a value from the template. In this case, creating a computed property is the best thing, because it's cached.
- You need to listen to changes of more than one data property You need to listen to changes of more than one data property
When to use watchers (When to use watchers)
- You want to listen when a data property changes, and perform some action You want to listen when a data property changes, and perform some action
- You want to listen to a prop value change You want to listen to a prop value change
- You only need to listen to one specific property (you can’t watch multiple properties at the same time) You only need to listen to one specific property (you can't watch multiple properties at the same time)
- You want to watch a data property until it reaches some specific value and then do something You want to watch a data property until it reaches some specific value and then do something
Props: pass data to child components (Props: pass data to child components)
Props are the way components can accept data from components that include them (parent components).
Props are the way components can accept data from components that include them (parent components).
When a component expects one or more prop, it must define them in its props property:
When a component expects one or more prop, it must define them in its props property:
Vue.component('user-name', { props: ['name'], template: '<p>Hi {{ name }}</p>'})or, in a Vue Single File Component:
or, in a Vue Single File Component:
<template> <p>{{ name }}</p></template><script>export default { props: ['name']}</script>Accept multiple props (Accept multiple props)
You can have multiple props by simply appending them to the array:
You can have multiple props by simply appending them to the array:
Vue.component('user-name', { props: ['firstName', 'lastName'], template: '<p>Hi {{ firstName }} {{ lastName }}</p>'})Set the prop type (Set the prop type)
You can specify the type of a prop very simply by using an object instead of an array, using the name of the property as the key of each property, and the type as the value:
You can specify the type of a prop very simply by using an object instead of an array, using the name of the property as the key of each property, and the type as the value:
Vue.component('user-name', { props: { firstName: String, lastName: String }, template: '<p>Hi {{ firstName }} {{ lastName }}</p>'})The valid types you can use are:
The valid types you can use are:
- String 串
- Number 數
- Boolean 布爾型
- Array 數組
- Object 目的
- Date 日期
- Function Function
- Symbol Symbol
When a type mismatches, Vue alerts you (in development mode) in the console with a warning.
When a type mismatches, Vue alerts you (in development mode) in the console with a warning.
Prop types can be more articulated.
Prop types can be more articulated.
You can allow multiple different value types:
You can allow multiple different value types:
props: { firstName: [String, Number]}Set a prop to be mandatory (Set a prop to be mandatory)
You can require a prop to be mandatory:
You can require a prop to be mandatory:
props: { firstName: { type: String, required: true }}Set the default value of a prop (Set the default value of a prop)
You can specify a default value:
You can specify a default value:
props: { firstName: { type: String, default: 'Unknown person' }}For objects:
For objects:
props: { name: { type: Object, default: { firstName: 'Unknown', lastName: '' } }}default can also be a function that returns an appropriate value, rather than being the actual value.
default can also be a function that returns an appropriate value, rather than being the actual value.
You can even build a custom validator, which is cool for complex data:
You can even build a custom validator, which is cool for complex data:
props: { name: { validator: name => { return name === 'Flavio' //only allow "Flavios" } }}Passing props to the component (Passing props to the component)
You pass a prop to a component using the syntax
You pass a prop to a component using the syntax
<ComponentName color="white" />if what you pass is a static value.
if what you pass is a static value.
If it’s a data property, you use
If it's a data property, you use
<template> <ComponentName :color=color /></template><script>...export default { //... data: function() { return { color: 'white' } }, //...}</script>You can use a ternary operator inside the prop value to check a truthy condition and pass a value that depends on it:
You can use a ternary operator inside the prop value to check a truthy condition and pass a value that depends on it:
<template> <ComponentName :colored="color == 'white' ? true : false" /></template><script>...export default { //... data: function() { return { color: 'white' } }, //...}</script>Handling Events in Vue (Handling Events in Vue)
What are Vue.js events? (What are Vue.js events?)
Vue.js allows us to intercept any DOM event by using the v-on directive on an element.
Vue.js allows us to intercept any DOM event by using the v-on directive on an element.
If we want to do something when a click event happens in this element:
If we want to do something when a click event happens in this element:
<template> <a>Click me!</a></template>we add a v-on directive:
we add a v-on directive:
<template> <a v-on:click="handleClick">Click me!</a></template>Vue also offers a very convenient alternative syntax for this:
Vue also offers a very convenient alternative syntax for this:
<template> <a @click="handleClick">Click me!</a></template>You can choose to use the parentheses or not. @click="handleClick" is equivalent to @click="handleClick()".
You can choose to use the parentheses or not. @click="handleClick" is equivalent to @click="handleClick()" .
handleClick is a method attached to the component:
handleClick is a method attached to the component:
<script>export default { methods: { handleClick: function(event) { console.log(event) } }}</script>What you need to know here is that you can pass parameters from events: @click="handleClick(param)" and they will be received inside the method.
What you need to know here is that you can pass parameters from events: @click="handleClick(param)" and they will be received inside the method.
Access the original event object (Access the original event object)
In many cases, you will want to perform an action on the event object or look up some property in it. How can you access it?
In many cases, you will want to perform an action on the event object or look up some property in it. How can you access it?
Use the special $event directive:
Use the special $event directive:
<template> <a @click="handleClick($event)">Click me!</a></template><script>export default { methods: { handleClick: function(event) { console.log(event) } }}</script>and if you already pass a variable:
and if you already pass a variable:
<template> <a @click="handleClick('something', $event)">Click me!</a></template><script>export default { methods: { handleClick: function(text, event) { console.log(text) console.log(event) } }}</script>From there you could call event.preventDefault(), but there's a better way: event modifiers.
From there you could call event.preventDefault() , but there's a better way: event modifiers.
Event modifiers (Event modifiers)
Instead of messing with DOM “things” in your methods, tell Vue to handle things for you:
Instead of messing with DOM “things” in your methods, tell Vue to handle things for you:
@click.prevent call event.preventDefault()
@click.prevent call event.preventDefault()
@click.stop call event.stopPropagation()
@click.stop call event.stopPropagation()
@click.passive makes use of the passive option of addEventListener
@click.passive makes use of the passive option of addEventListener
@click.capture uses event capturing instead of event bubbling
@click.capture uses event capturing instead of event bubbling
@click.self make sure the click event was not bubbled from a child event, but directly happened on that element
@click.self make sure the click event was not bubbled from a child event, but directly happened on that element
@click.once the event will only be triggered exactly once
@click.once the event will only be triggered exactly once
All those options can be combined by appending one modifier after the other.
All those options can be combined by appending one modifier after the other.
For more on propagation, bubbling and capturing, see my JavaScript events guide.
For more on propagation, bubbling and capturing, see my JavaScript events guide .
Inject content using slots (Inject content using slots)
A component can choose to define its content entirely, like in this case:
A component can choose to define its content entirely, like in this case:
Vue.component('user-name', { props: ['name'], template: '<p>Hi {{ name }}</p>'})Or it can also let the parent component inject any kind of content into it, by using slots.
Or it can also let the parent component inject any kind of content into it, by using slots.
What’s a slot?
What's a slot?
You define it by putting <slot></slot> in a component template:
You define it by putting <slot>& lt;/slot> in a component template:
Vue.component('user-information', { template: '<div class="user-information"><slot></slot></div>'})When using this component, any content added between the opening and closing tag will be added inside the slot placeholder:
When using this component, any content added between the opening and closing tag will be added inside the slot placeholder:
<user-information> <h2>Hi!</h2> <user-name name="Flavio"></user-information>If you put any content side the <slot></slot> tags, that serves as the default content in case nothing is passed in.
If you put any content side the <slot>& lt;/slot> tags, that serves as the default content in case nothing is passed in.
A complicated component layout might require a better way to organize content.
A complicated component layout might require a better way to organize content.
Enter named slots.
Enter named slots .
With a named slot, you can assign parts of a slot to a specific position in your component template layout, and you use a slot attribute to any tag, to assign content to that slot.
With a named slot, you can assign parts of a slot to a specific position in your component template layout, and you use a slot attribute to any tag, to assign content to that slot.
Anything outside any template tag is added to the main slot.
Anything outside any template tag is added to the main slot .
For convenience, I use a page single file component in this example:
For convenience, I use a page single file component in this example:
<template> <div> <main> <slot></slot> </main> <sidebar> <slot name="sidebar"></slot> </sidebar> </div></template><page> <ul slot="sidebar"> <li>Home</li> <li>Contact</li> </ul><h2>Page title</h2> <p>Page content</p></page>Filters, helpers for templates (Filters, helpers for templates)
Filters are a functionality provided by Vue components that let you apply formatting and transformations to any part of your template dynamic data.
Filters are a functionality provided by Vue components that let you apply formatting and transformations to any part of your template dynamic data.
They don’t change a component’s data or anything, but they only affect the output.
They don't change a component's data or anything, but they only affect the output.
Say you are printing a name:
Say you are printing a name:
<template> <p>Hi {{ name }}!</p></template><script>export default { data() { return { name: 'Flavio' } }}</script>What if you want to check that name is actually containing a value, and if not print 'there', so that our template will print "Hi there!"?
What if you want to check that name is actually containing a value, and if not print 'there', so that our template will print "Hi there!"?
Enter filters:
Enter filters:
<template> <p>Hi {{ name | fallback }}!</p></template><script>export default { data() { return { name: 'Flavio' } }, filters: { fallback: function(name) { return name ? name : 'there' } }}</script>Notice the syntax to apply a filter, which is | filterName. If you're familiar with Unix, that's the Unix pipe operator, which is used to pass the output of an operation as an input to the next one.
Notice the syntax to apply a filter, which is | filterName . If you're familiar with Unix, that's the Unix pipe operator, which is used to pass the output of an operation as an input to the next one.
The filters property of the component is an object. A single filter is a function that accepts a value and returns another value.
The filters property of the component is an object. A single filter is a function that accepts a value and returns another value.
The returned value is the one that’s actually printed in the Vue.js template.
The returned value is the one that's actually printed in the Vue.js template.
The filter, of course, has access to the component data and methods.
The filter, of course, has access to the component data and methods.
What’s a good use case for filters?
What's a good use case for filters?
- transforming a string, for example, capitalizing or making it lowercase transforming a string, for example, capitalizing or making it lowercase
- formatting a price formatting a price
Above you saw a simple example of a filter: {{ name | fallback }}.
Above you saw a simple example of a filter: {{ name | fallback }} .
Filters can be chained, by repeating the pipe syntax:
Filters can be chained, by repeating the pipe syntax:
{{ name | fallback | capitalize }}This first applies the fallback filter, then the capitalize filter (which we didn't define, but try making one!).
This first applies the fallback filter, then the capitalize filter (which we didn't define, but try making one!).
Advanced filters can also accept parameters, using the normal function parameters syntax:
Advanced filters can also accept parameters, using the normal function parameters syntax:
<template> <p>Hello {{ name | prepend('Dr.') }}</p></template><script>export default { data() { return { name: 'House' } }, filters: { prepend: (name, prefix) => { return `${prefix} ${name}` } }}</script>If you pass parameters to a filter, the first one passed to the filter function is always the item in the template interpolation (name in this case), followed by the explicit parameters you passed.
If you pass parameters to a filter, the first one passed to the filter function is always the item in the template interpolation ( name in this case), followed by the explicit parameters you passed.
You can use multiple parameters by separating them using a comma.
You can use multiple parameters by separating them using a comma.
Notice I used an arrow function. We avoid arrow functions in methods and computed properties, generally, because they almost always reference this to access the component data. But in this case, the filter does not need to access this but receives all the data it needs through the parameters, and we can safely use the simpler arrow function syntax.
Notice I used an arrow function. We avoid arrow functions in methods and computed properties, generally, because they almost always reference this to access the component data. But in this case, the filter does not need to access this but receives all the data it needs through the parameters, and we can safely use the simpler arrow function syntax.
This package has a lot of pre-made filters for you to use directly in templates, which include capitalize, uppercase, lowercase, placeholder, truncate, currency, pluralize and more.
This package has a lot of pre-made filters for you to use directly in templates, which include capitalize , uppercase , lowercase , placeholder , truncate , currency , pluralize and more.
Communication among components (Communication among components)
Components in Vue can communicate in various ways.
Components in Vue can communicate in various ways.
Using Props (Using Props)
The first way is by using props.
The first way is by using props.
Parents “pass down” data by adding arguments to the component declaration:
Parents “pass down” data by adding arguments to the component declaration:
<template> <div> <Car color="green" /> </div></template><script>import Car from './components/Car'export default { name: 'App', components: { Car }}</script>Props are one-way: from parent to child. Any time the parent changes the prop, the new value is sent to the child and re-rendered.
Props are one-way: from parent to child. Any time the parent changes the prop, the new value is sent to the child and re-rendered.
The reverse is not true, and you should never mutate a prop inside the child component.
The reverse is not true, and you should never mutate a prop inside the child component.
Using Events to communicate from children to parent (Using Events to communicate from children to parent)
Events allow you to communicate from the children up to the parent:
Events allow you to communicate from the children up to the parent:
<script>export default { name: 'Car', methods: { handleClick: function() { this.$emit('clickedSomething') } }}</script>The parent can intercept this using the v-on directive when including the component in its template:
The parent can intercept this using the v-on directive when including the component in its template:
<template> <div> <Car v-on:clickedSomething="handleClickInParent" /> <!-- or --> <Car @clickedSomething="handleClickInParent" /> </div></template><script>export default { name: 'App', methods: { handleClickInParent: function() { //... } }}</script>You can pass parameters of course:
You can pass parameters of course:
<script>export default { name: 'Car', methods: { handleClick: function() { this.$emit('clickedSomething', param1, param2) } }}</script>and retrieve them from the parent:
and retrieve them from the parent:
<template> <div> <Car v-on:clickedSomething="handleClickInParent" /> <!-- or --> <Car @clickedSomething="handleClickInParent" /> </div></template><script>export default { name: 'App', methods: { handleClickInParent: function(param1, param2) { //... } }}</script>Using an Event Bus to communicate between any components (Using an Event Bus to communicate between any components)
Using events you’re not limited to child-parent relationships. You can use the so-called Event Bus.
Using events you're not limited to child-parent relationships. You can use the so-called Event Bus.
Above we used this.$emit to emit an event on the component instance.
Above we used this.$emit to emit an event on the component instance.
What we can do instead is to emit the event on a more generally accessible component.
What we can do instead is to emit the event on a more generally accessible component.
this.$root, the root component, is commonly used for this.
this.$root , the root component, is commonly used for this.
You can also create a Vue component dedicated to this job, and import it where you need.
You can also create a Vue component dedicated to this job, and import it where you need.
<script>export default { name: 'Car', methods: { handleClick: function() { this.$root.$emit('clickedSomething') } }}</script>Any other component can listen for this event. You can do so in the mounted callback:
Any other component can listen for this event. You can do so in the mounted callback:
<script>export default { name: 'App', mounted() { this.$root.$on('clickedSomething', () => { //... }) }}</script>This is what Vue provides out of the box.
This is what Vue provides out of the box.
When you outgrow this, you can look into Vuex or other 3rd part libraries.
When you outgrow this, you can look into Vuex or other 3rd part libraries.
Manage state using Vuex (Manage state using Vuex)
Vuex is the official state management library for Vue.js.
Vuex is the official state management library for Vue.js.
Its job is to share data across the components of your application.
Its job is to share data across the components of your application.
Components in Vue.js out of the box can communicate using
Components in Vue.js out of the box can communicate using
- props, to pass state down to child components from a parent props, to pass state down to child components from a parent
- events, to change the state of a parent component from a child, or using the root component as an event bus events, to change the state of a parent component from a child, or using the root component as an event bus
Sometimes things get more complex than what these simple options allow.
Sometimes things get more complex than what these simple options allow.
In this case, a good option is to centralize the state in a single store. This is what Vuex does.
In this case, a good option is to centralize the state in a single store. This is what Vuex does.
Why should you use Vuex? (Why should you use Vuex?)
Vuex is not the only state management option you can use in Vue (you can use Redux too), but its main advantage is that it’s official, and its integration with Vue.js is what makes it shine.
Vuex is not the only state management option you can use in Vue (you can use Redux too), but its main advantage is that it's official, and its integration with Vue.js is what makes it shine.
With React you have the trouble of having to choose one of the many libraries available, as the ecosystem is huge and has no actual standard. Lately Redux was the most popular choice, with MobX following up in terms of popularity. With Vue I’d go as far as to say that you won’t need to look around for anything other than Vuex, especially when starting out.
With React you have the trouble of having to choose one of the many libraries available, as the ecosystem is huge and has no actual standard. Lately Redux was the most popular choice, with MobX following up in terms of popularity. With Vue I'd go as far as to say that you won't need to look around for anything other than Vuex, especially when starting out.
Vuex borrowed many of its ideas from the React ecosystem, as this is the Flux pattern popularized by Redux.
Vuex borrowed many of its ideas from the React ecosystem, as this is the Flux pattern popularized by Redux.
If you know Flux or Redux already, Vuex will be very familiar. If you don’t, no problem — I’ll explain every concept from the ground up.
If you know Flux or Redux already, Vuex will be very familiar. If you don't, no problem — I'll explain every concept from the ground up.
Components in a Vue application can have their own state. For example, an input box will store the data entered into it locally. This is perfectly fine, and components can have local state even when using Vuex.
Components in a Vue application can have their own state. For example, an input box will store the data entered into it locally. This is perfectly fine, and components can have local state even when using Vuex.
You know that you need something like Vuex when you start doing a lot of work to pass a piece of state around.
You know that you need something like Vuex when you start doing a lot of work to pass a piece of state around.
In this case, Vuex provides a central repository store for the state, and you mutate the state by asking the store to do that.
In this case, Vuex provides a central repository store for the state, and you mutate the state by asking the store to do that.
Every component that depends on a particular piece of the state will access it using a getter on the store, which makes sure it’s updated as soon as that thing changes.
Every component that depends on a particular piece of the state will access it using a getter on the store, which makes sure it's updated as soon as that thing changes.
Using Vuex will introduce some complexity into the application, as things need to be set up in a certain way to work correctly. But if this helps solve the unorganized props passing and event system that might grow into a spaghetti mess if too complicated, then it’s a good choice.
Using Vuex will introduce some complexity into the application, as things need to be set up in a certain way to work correctly. But if this helps solve the unorganized props passing and event system that might grow into a spaghetti mess if too complicated, then it's a good choice.
開始吧 (Let’s start)
In this example, I’m starting from a Vue CLI application. Vuex can be used also by directly loading it into a script tag. But, since Vuex is more in tune with bigger applications, it’s much more likely you will use it on a more structured application, like the ones you can start up quickly with the Vue CLI.
In this example, I'm starting from a Vue CLI application. Vuex can be used also by directly loading it into a script tag. But, since Vuex is more in tune with bigger applications, it's much more likely you will use it on a more structured application, like the ones you can start up quickly with the Vue CLI.
The examples I use will be put CodeSandbox, which is a great service that has a Vue CLI sample ready to go. I recommend using it to play around.
The examples I use will be put CodeSandbox, which is a great service that has a Vue CLI sample ready to go. I recommend using it to play around.
Once you’re there, click the Add dependency button, enter “vuex” and click it.
Once you're there, click the Add dependency button, enter “vuex” and click it.
Now Vuex will be listed in the project dependencies.
Now Vuex will be listed in the project dependencies.
To install Vuex locally you can simply run npm install vuex or yarn add vuex inside the project folder.
To install Vuex locally you can simply run npm install vuex or yarn add vuex inside the project folder.
Create the Vuex store (Create the Vuex store)
Now we are ready to create our Vuex store.
Now we are ready to create our Vuex store.
This file can be put anywhere. It’s generally suggested to put it in the src/store/store.js file, so we'll do that.
This file can be put anywhere. It's generally suggested to put it in the src/store/store.js file, so we'll do that.
In this file we initialize Vuex and tell Vue to use it:
In this file we initialize Vuex and tell Vue to use it:
import Vue from 'vue'import Vuex from 'vuex'Vue.use(Vuex)export const store = new Vuex.Store({})We export a Vuex store object, which we create using the Vuex.Store() API.
We export a Vuex store object, which we create using the Vuex.Store() API.
A use case for the store (A use case for the store)
Now that we have a skeleton in place, let’s come up with an idea for a good use case for Vuex, so I can introduce its concepts.
Now that we have a skeleton in place, let's come up with an idea for a good use case for Vuex, so I can introduce its concepts.
For example, I have two sibling components, one with an input field, and one that prints that input field content.
For example, I have two sibling components, one with an input field, and one that prints that input field content.
When the input field is changed, I want to also change the content in that second component. Very simple, but this will do the job for us.
When the input field is changed, I want to also change the content in that second component. Very simple, but this will do the job for us.
Introducing the new components we need (Introducing the new components we need)
I delete the HelloWorld component and add a Form component, and a Display component.
I delete the HelloWorld component and add a Form component, and a Display component.
<template> <div> <label for="flavor">Favorite ice cream flavor?</label> <input name="flavor"> </div></template><template> <div> <p>You chose ???</p> </div></template>Adding those components to the app (Adding those components to the app)
We add them to the App.vue code instead of the HelloWorld component:
We add them to the App.vue code instead of the HelloWorld component:
<template> <div id="app"> <Form/> <Display/> </div></template><script>import Form from './components/Form'import Display from './components/Display'export default { name: 'App', components: { Form, Display }}</script>Add the state to the store (Add the state to the store)
So with this in place, we go back to the store.js file. We add a property to the store called state, which is an object, that contains the flavor property. That's an empty string initially.
So with this in place, we go back to the store.js file. We add a property to the store called state , which is an object, that contains the flavor property. That's an empty string initially.
import Vue from 'vue'import Vuex from 'vuex'Vue.use(Vuex)export const store = new Vuex.Store({ state: { flavor: '' }})We’ll update it when the user types into the input field.
We'll update it when the user types into the input field.
Add a mutation (Add a mutation)
The state cannot be manipulated except by using mutations. We set up one mutation which will be used inside the Form component to notify the store that the state should change.
The state cannot be manipulated except by using mutations. We set up one mutation which will be used inside the Form component to notify the store that the state should change.
import Vue from 'vue'import Vuex from 'vuex'Vue.use(Vuex)export const store = new Vuex.Store({ state: { flavor: '' }, mutations: { change(state, flavor) { state.flavor = flavor } }})Add a getter to reference a state property (Add a getter to reference a state property)
With that set, we need to add a way to look at the state. We do so using getters. We set up a getter for the flavorproperty:
With that set, we need to add a way to look at the state. We do so using getters. We set up a getter for the flavor property:
import Vue from 'vue'import Vuex from 'vuex'Vue.use(Vuex)export const store = new Vuex.Store({ state: { flavor: '' }, mutations: { change(state, flavor) { state.flavor = flavor } }, getters: { flavor: state => state.flavor }})Notice how getters is an object. flavor is a property of this object, which accepts the state as the parameter, and returns the flavor property of the state.
Notice how getters is an object. flavor is a property of this object, which accepts the state as the parameter, and returns the flavor property of the state.
Adding the Vuex store to the app (Adding the Vuex store to the app)
Now the store is ready to be used. We go back to our application code, and in the main.js file, we need to import the state and make it available in our Vue app.
Now the store is ready to be used. We go back to our application code, and in the main.js file, we need to import the state and make it available in our Vue app.
We add
We add
import { store } from './store/store'and we add it to the Vue application:
and we add it to the Vue application:
new Vue({ el: '#app', store, components: { App }, template: '<App/>'})Once we add this, since this is the main Vue component, the store variable inside every Vue component will point to the Vuex store.
Once we add this, since this is the main Vue component, the store variable inside every Vue component will point to the Vuex store.
Update the state on a user action using commit (Update the state on a user action using commit)
Let’s update the state when the user types something.
Let's update the state when the user types something.
We do so by using the store.commit() API.
We do so by using the store.commit() API.
But first, let’s create a method that is invoked when the input content changes. We use @input rather than @changebecause the latter is only triggered when the focus is moved away from the input box, while @input is called on every keypress.
But first, let's create a method that is invoked when the input content changes. We use @input rather than @change because the latter is only triggered when the focus is moved away from the input box, while @input is called on every keypress.
<template> <div> <label for="flavor">Favorite ice cream flavor?</label> <input @input="changed" name="flavor"> </div></template><script>export default { methods: { changed: function(event) { alert(event.target.value) } }}</script>Now that we have the value of the flavor, we use the Vuex API:
Now that we have the value of the flavor, we use the Vuex API:
<script>export default { methods: { changed: function(event) { this.$store.commit('change', event.target.value) } }}</script>See how we reference the store using this.$store? This is thanks to the inclusion of the store object in the main Vue component initialization.
See how we reference the store using this.$store ? This is thanks to the inclusion of the store object in the main Vue component initialization.
The commit() method accepts a mutation name (we used change in the Vuex store) and a payload, which will be passed to the mutation as the second parameter of its callback function.
The commit() method accepts a mutation name (we used change in the Vuex store) and a payload, which will be passed to the mutation as the second parameter of its callback function.
Use the getter to print the state value (Use the getter to print the state value)
Now we need to reference the getter of this value in the Display template, by using $store.getters.flavor. this can be removed because we're in the template, and this is implicit.
Now we need to reference the getter of this value in the Display template, by using $store.getters.flavor . this can be removed because we're in the template, and this is implicit.
<template> <div> <p>You chose {{ $store.getters.flavor }}</p> </div></template>The full, working source code is available here.
The full, working source code is available here .
There are still many concepts missing in this puzzle:
There are still many concepts missing in this puzzle:
- actions 行動
- modules 模組
- helpers helpers
- plugins plugins
But now you have the basics to go and read about them in the official docs.
But now you have the basics to go and read about them in the official docs.
Handle URLs using Vue Router (Handle URLs using Vue Router)
In a JavaScript web application, a router is the part that syncs the currently displayed view with the browser address bar content.
In a JavaScript web application, a router is the part that syncs the currently displayed view with the browser address bar content.
In other words, it’s the part that makes the URL change when you click something in the page, and helps to show the correct view when you hit a specific URL.
In other words, it's the part that makes the URL change when you click something in the page, and helps to show the correct view when you hit a specific URL.
Traditionally, the Web is built around URLs. When you hit a certain URL, a specific page is displayed.
Traditionally, the Web is built around URLs. When you hit a certain URL, a specific page is displayed.
With the introduction of applications that run inside the browser and change what the user sees, many applications broke this interaction, and you had to manually update the URL with the browser’s History API.
With the introduction of applications that run inside the browser and change what the user sees, many applications broke this interaction, and you had to manually update the URL with the browser's History API.
You need a router when you need to sync URLs to views in your app. It’s a very common need, and all the major modern frameworks now allow you to manage routing.
You need a router when you need to sync URLs to views in your app. It's a very common need, and all the major modern frameworks now allow you to manage routing.
The Vue Router library is the way to go for Vue.js applications. Vue does not enforce the use of this library. You can use whatever generic routing library you want, or also create your own History API integration, but the benefit of using Vue Router is that it’s official.
The Vue Router library is the way to go for Vue.js applications. Vue does not enforce the use of this library. You can use whatever generic routing library you want, or also create your own History API integration, but the benefit of using Vue Router is that it's official.
This means it’s maintained by the same people who maintain Vue, so you get a more consistent integration in the framework, and the guarantee that it’s always going to be compatible in the future, no matter what.
This means it's maintained by the same people who maintain Vue, so you get a more consistent integration in the framework, and the guarantee that it's always going to be compatible in the future, no matter what.
安裝 (Installation)
Vue Router is available via npm with the package named vue-router.
Vue Router is available via npm with the package named vue-router .
If you use Vue via a script tag, you can include Vue Router using
If you use Vue via a script tag, you can include Vue Router using
<script src="https://unpkg.com/vue-router"></script>UNPKG is a very handy tool that makes every npm package available in the browser with a simple link.
UNPKG is a very handy tool that makes every npm package available in the browser with a simple link.
If you use the Vue CLI, install it using:
If you use the Vue CLI, install it using:
npm install vue-routerOnce you install vue-router and make it available either using a script tag or via Vue CLI, you can now import it in your app.
Once you install vue-router and make it available either using a script tag or via Vue CLI, you can now import it in your app.
You import it after vue, and you call Vue.use(VueRouter) to install it inside the app:
You import it after vue , and you call Vue.use(VueRouter) to install it inside the app:
import Vue from 'vue'import VueRouter from 'vue-router'Vue.use(VueRouter)After you call Vue.use() passing the router object, in any component of the app you have access to these objects:
After you call Vue.use() passing the router object, in any component of the app you have access to these objects:
this.$router is the router object
this.$router is the router object
this.$route is the current route object
this.$route is the current route object
The router object (The router object)
The router object, accessed using this.$router from any component when the Vue Router is installed in the root Vue component, offers many nice features.
The router object, accessed using this.$router from any component when the Vue Router is installed in the root Vue component, offers many nice features.
We can make the app navigate to a new route using
We can make the app navigate to a new route using
this.$router.push()
this.$router.push()
this.$router.replace()
this.$router.replace()
this.$router.go()
this.$router.go()
which resemble the pushState, replaceState and go methods of the History API.
which resemble the pushState , replaceState and go methods of the History API.
push() is used to go to a new route, adding a new item to the browser history
push() is used to go to a new route, adding a new item to the browser history
replace() is the same, except it does not push a new state to the history
replace() is the same, except it does not push a new state to the history
Usage samples:
Usage samples:
this.$router.push('about') //named route, see laterthis.$router.push({ path: 'about' })this.$router.push({ path: 'post', query: { post_slug: 'hello-world' } }) //using query parameters (post?post_slug=hello-world)this.$router.replace({ path: 'about' })go() goes back and forth, accepting a number that can be positive or negative to go back in the history:
go() goes back and forth, accepting a number that can be positive or negative to go back in the history:
this.$router.go(-1) //go back 1 stepthis.$router.go(1) //go forward 1 stepDefining the routes (Defining the routes)
I’m using a Vue Single File Component in this example.
I'm using a Vue Single File Component in this example.
In the template I use a nav tag that has three router-link components, which have the labels Home, Login, and About. A URL is assigned through the to attribute.
In the template I use a nav tag that has three router-link components, which have the labels Home, Login, and About. A URL is assigned through the to attribute.
The router-view component is where the Vue Router will put the content that matches the current URL.
The router-view component is where the Vue Router will put the content that matches the current URL.
<template> <div id="app"> <nav> <router-link to="/">Home</router-link> <router-link to="/login">Login</router-link> <router-link to="/about">About</router-link> </nav> <router-view></router-view> </div></template>A router-link component renders an a tag by default (you can change that). Every time the route changes, either by clicking a link or by changing the URL, a router-link-active class is added to the element that refers to the active route, allowing you to style it.
A router-link component renders an a tag by default (you can change that). Every time the route changes, either by clicking a link or by changing the URL, a router-link-active class is added to the element that refers to the active route, allowing you to style it.
In the JavaScript part, we first include and install the router, then we define three route components.
In the JavaScript part, we first include and install the router, then we define three route components.
We pass them to the initialization of the router object, and we pass this object to the Vue root instance.
We pass them to the initialization of the router object, and we pass this object to the Vue root instance.
Here’s the code:
這是代碼:
<script>import Vue from 'vue'import VueRouter from 'vue-router'Vue.use(Router)const Home = { template: '<div>Home</div>'}const Login = { template: '<div>Login</div>'}const About = { template: '<div>About</div>'}const router = new VueRouter({ routes: [ { path: '/', component: Home }, { path: '/login', component: Login }, { path: '/about', component: About } ]})new Vue({ router}).$mount('#app')</script>Usually, in a Vue app, you instantiate and mount the root app using:
Usually, in a Vue app, you instantiate and mount the root app using:
new Vue({ render: h => h(App)}).$mount('#app')When using the Vue Router, you don’t pass a render property but instead, you use router.
When using the Vue Router, you don't pass a render property but instead, you use router .
The syntax used in the above example:
The syntax used in the above example:
new Vue({ router}).$mount('#app')is shorthand for:
is shorthand for:
new Vue({ router: router}).$mount('#app')See in the example, we pass a routes array to the VueRouter constructor. Each route in this array has a path and component params.
See in the example, we pass a routes array to the VueRouter constructor. Each route in this array has a path and component params.
If you pass a name param too, you have a named route.
If you pass a name param too, you have a named route.
Using named routes to pass parameters to the router push and replace methods (Using named routes to pass parameters to the router push and replace methods)
Remember how we used the Router object to push a new state before?
Remember how we used the Router object to push a new state before?
this.$router.push({ path: 'about' })With a named route we can pass parameters to the new route:
With a named route we can pass parameters to the new route:
this.$router.push({ name: 'post', params: { post_slug: 'hello-world' } })The same goes for replace():
The same goes for replace() :
this.$router.replace({ name: 'post', params: { post_slug: 'hello-world' } })What happens when a user clicks a router-link? (What happens when a user clicks a router-link?)
The application will render the route component that matches the URL passed to the link.
The application will render the route component that matches the URL passed to the link.
The new route component that handles the URL is instantiated and its guards called, and the old route component will be destroyed.
The new route component that handles the URL is instantiated and its guards called, and the old route component will be destroyed.
Route guards (Route guards)
Since we mentioned guards, let’s introduce them.
Since we mentioned guards, let's introduce them.
You can think of them as life cycle hooks or middleware. Those are functions called at specific times during the execution of the application. You can jump in and alter the execution of a route, redirecting or simply canceling the request.
You can think of them as life cycle hooks or middleware. Those are functions called at specific times during the execution of the application. You can jump in and alter the execution of a route, redirecting or simply canceling the request.
You can have global guards by adding a callback to the beforeEach() and afterEach() property of the router.
You can have global guards by adding a callback to the beforeEach() and afterEach() property of the router.
beforeEach() is called before the navigation is confirmed
beforeEach() is called before the navigation is confirmed
beforeResolve() is called when beforeEach() is executed and all the components beforeRouterEnter and beforeRouteUpdate guards are called, but before the navigation is confirmed. The final check.
beforeResolve() is called when beforeEach() is executed and all the components beforeRouterEnter and beforeRouteUpdate guards are called, but before the navigation is confirmed. The final check.
afterEach() is called after the navigation is confirmed
afterEach() is called after the navigation is confirmed
What does “the navigation is confirmed” mean? We’ll see it in a second. In the meantime think of it as “the app can go to that route”.
What does “the navigation is confirmed” mean? We'll see it in a second. In the meantime think of it as “the app can go to that route”.
The usage is:
The usage is:
this.$router.beforeEach((to, from, next) => { // ...})this.$router.afterEach((to, from) => { // ...})to and from represent the route objects that we go to and from.
to and from represent the route objects that we go to and from.
beforeEach has an additional parameter next which if we call with false as the parameter, will block the navigation and cause it to be unconfirmed.
beforeEach has an additional parameter next which if we call with false as the parameter, will block the navigation and cause it to be unconfirmed.
Like in Node middleware, if you're familiar, next() should always be called, otherwise execution will get stuck.
Like in Node middleware, if you're familiar, next() should always be called, otherwise execution will get stuck.
Single route components also have guards:
Single route components also have guards:
beforeRouteEnter(from, to, next) is called before the current route is confirmed
beforeRouteEnter(from, to, next) is called before the current route is confirmed
beforeRouteUpdate(from, to, next) is called when the route changes but the component that manages it is still the same (with dynamic routing, see next)
beforeRouteUpdate(from, to, next) is called when the route changes but the component that manages it is still the same (with dynamic routing, see next )
beforeRouteLeave(from, to, next) is called when we move away from here
beforeRouteLeave(from, to, next) is called when we move away from here
We mentioned navigation. To determine if the navigation to a route is confirmed, Vue Router performs some checks:
We mentioned navigation. To determine if the navigation to a route is confirmed, Vue Router performs some checks:
it calls beforeRouteLeave guard in the current component(s)
it calls beforeRouteLeave guard in the current component(s)
it calls the router beforeEach() guard
it calls the router beforeEach() guard
it calls the beforeRouteUpdate() in any component that needs to be reused, if any exist
it calls the beforeRouteUpdate() in any component that needs to be reused, if any exist
it calls the beforeEnter() guard on the route object (I didn't mention it but you can look here)
it calls the beforeEnter() guard on the route object (I didn't mention it but you can look here )
it calls the beforeRouterEnter() in the component that we should enter into
it calls the beforeRouterEnter() in the component that we should enter into
it calls the router beforeResolve() guard
it calls the router beforeResolve() guard
- if all was fine, the navigation is confirmed! if all was fine, the navigation is confirmed!
it calls the router afterEach() guard
it calls the router afterEach() guard
You can use the route-specific guards (beforeRouteEnter and beforeRouteUpdate in case of dynamic routing) as life cycle hooks, so you can start data fetching requests for example.
You can use the route-specific guards ( beforeRouteEnter and beforeRouteUpdate in case of dynamic routing) as life cycle hooks, so you can start data fetching requests for example.
Dynamic routing (Dynamic routing)
The example above shows a different view based on the URL, handling the /, /login and /about routes.
The example above shows a different view based on the URL, handling the / , /login and /about routes.
A very common need is to handle dynamic routes, like having all posts under /post/, each with the slug name:
A very common need is to handle dynamic routes, like having all posts under /post/ , each with the slug name:
/post/first
/post/first
/post/another-post
/post/another-post
/post/hello-world
/post/hello-world
You can achieve this using a dynamic segment.
You can achieve this using a dynamic segment.
Those were static segments:
Those were static segments:
const router = new VueRouter({ routes: [ { path: '/', component: Home }, { path: '/login', component: Login }, { path: '/about', component: About } ]})We add in a dynamic segment to handle blog posts:
We add in a dynamic segment to handle blog posts:
const router = new VueRouter({ routes: [ { path: '/', component: Home }, { path: '/post/:post_slug', component: Post }, { path: '/login', component: Login }, { path: '/about', component: About } ]})Notice the :post_slug syntax. This means that you can use any string, and that will be mapped to the post_slugplaceholder.
Notice the :post_slug syntax. This means that you can use any string, and that will be mapped to the post_slug placeholder.
You’re not limited to this kind of syntax. Vue relies on this library to parse dynamic routes, and you can go wild with Regular Expressions.
You're not limited to this kind of syntax. Vue relies on this library to parse dynamic routes, and you can go wild with Regular Expressions.
Now inside the Post route component we can reference the route using $route, and the post slug using $route.params.post_slug:
Now inside the Post route component we can reference the route using $route , and the post slug using $route.params.post_slug :
const Post = { template: '<div>Post: {{ $route.params.post_slug }}</div>'}We can use this parameter to load the contents from the back-end.
We can use this parameter to load the contents from the back-end.
You can have as many dynamic segments as you want, in the same URL:
You can have as many dynamic segments as you want, in the same URL:
/post/:author/:post_slug
/post/:author/:post_slug
Remember before when we talked about what happens when a user navigates to a new route?
Remember before when we talked about what happens when a user navigates to a new route?
In the case of dynamic routes, what happens is a little different.
In the case of dynamic routes, what happens is a little different.
For Vue to be more efficient, instead of destroying the current route component and re-instantiating it, it reuses the current instance.
For Vue to be more efficient, instead of destroying the current route component and re-instantiating it, it reuses the current instance.
When this happens, Vue calls the beforeRouteUpdate life cycle event.
When this happens, Vue calls the beforeRouteUpdate life cycle event.
There you can perform any operation you need:
There you can perform any operation you need:
const Post = { template: '<div>Post: {{ $route.params.post_slug }}</div>' beforeRouteUpdate(to, from, next) { console.log(`Updating slug from ${from} to ${to}`) next() //make sure you always call next() }}Using props (Using props)
In the examples, I used $route.params.* to access the route data. A component should not be so tightly coupled with the router, and instead, we can use props:
In the examples, I used $route.params.* to access the route data. A component should not be so tightly coupled with the router, and instead, we can use props:
const Post = { props: ['post_slug'], template: '<div>Post: {{ post_slug }}</div>'}const router = new VueRouter({ routes: [ { path: '/post/:post_slug', component: Post, props: true } ]})Notice the props: true passed to the route object to enable this functionality.
Notice the props: true passed to the route object to enable this functionality.
Nested routes (Nested routes)
Before I mentioned that you can have as many dynamic segments as you want, in the same URL, like:
Before I mentioned that you can have as many dynamic segments as you want, in the same URL, like:
/post/:author/:post_slug
/post/:author/:post_slug
So, say we have an Author component taking care of the first dynamic segment:
So, say we have an Author component taking care of the first dynamic segment:
<template> <div id="app"> <router-view></router-view> </div></template><script>import Vue from 'vue'import VueRouter from 'vue-router'Vue.use(Router)const Author = { template: '<div>Author: {{ $route.params.author}}</div>'}const router = new VueRouter({ routes: [ { path: '/post/:author', component: Author } ]})new Vue({ router}).$mount('#app')</script>We can insert a second router-view component instance inside the Author template:
We can insert a second router-view component instance inside the Author template:
const Author = { template: '<div>Author: {{ $route.params.author}}<router-view></router-view></div>'}We add the Post component:
We add the Post component:
const Post = { template: '<div>Post: {{ $route.params.post_slug }}</div>'}Then we’ll inject the inner dynamic route in the VueRouter configuration:
Then we'll inject the inner dynamic route in the VueRouter configuration:
const router = new VueRouter({ routes: [{ path: '/post/:author', component: Author, children: [ path: ':post_slug', component: Post ] }]})Thank you for reading!
感謝您的閱讀!
Get this post PDF/ePub/Kindle ebook at vuehandbook.com
Get this post PDF/ePub/Kindle ebook at vuehandbook.com
翻譯自: https://www.freecodecamp.org/news/the-vue-handbook-a-thorough-introduction-to-vue-js-1e86835d8446/
vue.js手冊
總結
以上是生活随笔為你收集整理的vue.js手册_Vue手册:Vue.js的完整介绍的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 前端学习(175):弹窗
- 下一篇: 飘云阁15周年逆向破解教程