TableofContentsIntroduction
IntrotoVue
IntroductiontoVue
VueFirstApp
Tooling
TheVueCLI
DevTools
ConfiguringVSCodeforVueDevelopment
Components
Components
SingleFileComponents
Templates
StylingcomponentsusingCSS
Componentsbuildingblocks
Directives
Events
Methods
Watchers
ComputedProperties
MethodsvsWatchersvsComputedProperties
Props
Slots
Filters
Communication,statemanagementandrouting
Communicationamongcomponents
Vuex
VueRouter
2
3
IntroductionThankyouforgettingthisebook!
MynameisFlavioandIrunablogatflaviocopes.com,whereIwriteatutorialeveryday.
YoucanfindmeonTwitterat@flaviocopes
AttheendofJuly2018,IwilllaunchanonlinecourseonVue.jswithpracticaltutorialsanddirectmentorshipfromme.
Findoutmoreatvuecourse.com!
Happylearning!
Introduction
4
IntroductiontoVueVueisaveryimpressiveproject.It'saverypopularJavaScriptframework,onethat'sexperiencingahugegrowth.Itissimple,tinyandveryperformant.Learnmoreaboutit
First,whatisaJavaScriptfrontendframework?ThepopularityofVueWhydevelopersloveVueWheredoesVue.jspositionitselfintheframeworkslandscapeVue.jsisanindieproject
VueisaverypopularJavaScriptfrontendframework,onethat'sexperiencingahugegrowth.
Itissimple,tiny(~24KB)andveryperformant.ItfeelsdifferentfromalltheotherJavaScriptfrontendframeworksandviewlibraries.Let'sfindoutwhy.
First,whatisaJavaScriptfrontendframework?Ifyou'reunsurewhataJavaScriptframeworkis,Vueistheperfectfirstencounterwithone.
AJavaScriptframeworkhelpsustocreatemodernapplications.ModernJavaScriptapplicationsaremostlyusedontheWeb,butalsopoweralotofDesktopandMobileapplications.
Untiltheearly2000s,browsersdidn'thavethecapabilitiestheyhavenow.Theywerealotlesspowerful,andbuildingcomplexapplicationsinsidethemwasnotfeasibleperformance-wise,andthetoolingwasnotevensomethingthatpeoplethoughtabout.
EverythingchangedwhenGoogleunveiledGoogleMapsandGMail,twoapplicationsthatraninsidethebrowser.Ajaxmadeasynchronousnetworkrequestspossible,andovertimedevelopersstartedbuildingontopoftheWebplatform,whileengineersworkedontheplatformitself:browsers,theWebstandards,thebrowserAPIs,andtheJavaScriptlanguage.
LibrarieslikejQueryandMootoolswerethefirstbigprojectsthatbuiltuponJavaScriptandwerehugelypopularforawhile.TheybasicallyprovidedanicerAPItointeractwiththebrowserandprovidedworkaroundsforbugsandinconsistenciesamongthevariousbrowsers.
FrameworkslikeBackbone,Ember,Knockout,AngularJSwerethefirstwaveofmodernJavaScriptframeworks.Thesecondwave,whichisthecurrentone,hasReact,Angular,andVueasitsmainactors.
IntroductiontoVue
5
NotethatjQuery,EmberandtheotherprojectsImentionedarestillbeingheavilyused,activelymaintained,andmillionsofwebsitesrelyonthem.Thatsaid,techniquesandtoolsevolve,andasaJavaScriptdeveloper,you'renowlikelytoberequiredtoknowReact,AngularorVueratherthanthoseolderframeworks.
FrameworksabstracttheinteractionwiththebrowserandtheDOM.InsteadofmanipulatingelementsbyreferencingthemintheDOM,wedeclarativelydefineandinteractwiththem,atahigherlevel.
UsingaframeworkislikeusingtheCprogramminglanguageinsteadofusingtheAssemblylanguagetowritesystemprograms.It'slikeusingacomputertowriteadocumentinsteadofusingatypewriter.It'slikehavingaself-drivingcarinsteadofdrivingthecaryourself.
Well,notthatfar,butyougettheidea.Insteadofusinglow-levelAPIsofferedbythebrowsertomanipulateelements,andbuildhugelycomplexsystemstowriteanapplication,youusetoolsbuiltbyverysmartpeoplethatmakeourlifeeasier.
ThepopularityofVueHowmuchpopularisVue.js?
Vuehad:
7600starsonGitHubin201636700starsonGitHubin2017
andithasmorethan100.000+starsonGitHub,asofJune2018.
Itsnpmdownloadcountisgrowingeveryday,andnowit'sat~350.000downloadsperweek.
IwouldsayVueisalotpopular,giventhosenumbers.
Inrelativeterms,ithasapproximatelythesamenumbersofGitHubstarsofReact,whichwasbornyearsbefore.
Numbersarenoteverything,ofcourse.TheimpressionIhaveofVueisthatdevelopersloveit.
AkeypointintimeoftheriseofVuehasbeentheadoptionintheLaravelecosystem,ahugelypopularPHPwebapplicationframework,butsincethenithaswidespreadamongmanyotherdevelopmentcommunities.
WhydevelopersloveVueFirst,Vueiscalledaprogressiveframework.
IntroductiontoVue
6
Thismeansthatitadaptstotheneedsofthedeveloper.Whileotherframeworksrequireacompletebuy-infromadeveloperorteamandoftenwantyoutorewriteanexistingapplicationbecausetheyrequiresomespecificsetofconventions,Vuehappilylandsinsideyourappwithasimple scripttag,tostartwith,anditcangrowalongwithyourneeds,spreadingfrom3linestomanagingyourentireviewlayer.
Youdon'tneedtoknowaboutwebpack,Babel,npmoranythingtogetstartedwithVue,butwhenyou'rereadyVuemakesitsimpleforyoutorelyonthem.
Thisisonegreatsellingpoint,especiallyinthecurrentecosystemofJavaScriptfrontendframeworksandlibrariesthattendstoalienatenewcomersandalsoexperienceddevelopersthatfeellostintheoceanofpossibilitiesandchoices.
Vue.jsisprobablythemoreapproachablefrontendframeworkaround.SomepeoplecallVuethenewjQuery,becauseiteasilygetsintheapplicationviaascripttag,andgraduallygainsspacefromthere.Thinkofitasacompliment,sincejQuerydominatedtheWebinthepastfewyears,anditstilldoesitsjobonahugenumberofsites.
Vuepicksfromthebestideas.ItwasbuiltbypickingthebestideasofframeworkslikeAngular,ReactandKnockout,andbycherry-pickingthebestchoicesthoseframeworksmade,andexcludingsomelessbrilliantones,itkindofstartedasa"best-of"setandgrewfromthere.
WheredoesVue.jspositionitselfintheframeworkslandscapeThe2elephantsintheroom,whentalkingaboutwebdevelopment,areReactandAngular.HowdoesVuepositionitselfrelativetothose2bigandpopularframeworks?
VuewascreatedbyEvanYouwhenhewasworkingatGoogleonAngularJS(Angular1.0)appsandwasbornoutofaneedtocreatemoreperformantapplications.VuepickedsomeoftheAngulartemplatingsyntax,butremovedtheopinionated,complexstackthatAngularrequired,andmadeitveryperformant.
ThenewAngular(Angular2.0)alsosolvedmanyoftheAngularJSissues,butinverydifferentways,andrequiresabuy-intoTypeScriptwhichnotalldevelopersenjoyusing(orwanttolearn).
WhataboutReact?VuetookmanygoodideasfromReact,mostimportantlytheVirtualDOM.ButVueimplementsitwithsomesortofautomaticdependencymanagement,whichtrackswhichcomponentsareaffectedbyachangeofthestatesothatonlythosecomponentsarere-renderedwhenthatstatepropertychanges.InReactontheotherhandwhenapartofthestatethataffectsacomponentchanges,thecomponentwillbere-renderedandbydefaultallitschildrenwillbererenderedaswell.Toavoidthisyouneedtousethe
IntroductiontoVue
7
shouldComponentUpdatemethodofeachcomponentanddetermineifthatcomponentshouldbererendered.ThisgivesVueabitofadvantageintermsofeaseofuse,andoutoftheboxperformancegains.
OnebigdifferencewithReactisJSX.WhileyoucantechnicallyuseJSXinVue,it'snotapopularapproachandinsteadthetemplatingsystemisused.AnyHTMLfileisavalidVuetemplate,whileJSXisverydifferentthanHTMLandhasalearningcurveforpeopleintheteamthatmightonlyneedtoworkwiththeHTMLpartofyourapp,likedesigners.VuetemplatesarealotsimilartoMustacheandHandlebars(althoughtheydifferintermsofflexibility)andassuch,theyaremorefamiliartodevelopersthatalreadyusedframeworkslikeAngularandEmber.
Theofficialstatemanagementlibrary,Vuex,followstheFluxarchitectureandissomewhatsimilartoReduxinitsconcepts.Again,thisispartofthepositivethingsaboutVue,whichsawthisgoodpatterninReactandborrowedittoitsecosystem.AndwhileyoucanuseReduxwithVue,VuexisspecificallytailoredforVueanditsinnerworkings.
VueisflexiblebutthefactthatthecoreteammaintainstwopackagesveryimportantforanywebapplikeroutingandstatemanagementmakesitalotlessfragmentedthanReactforexample: vue-routerand vuexarekeytothesuccessofVue.Youdon'tneedtochooseorworryifthatlibraryyouchoseisgoingtobemaintainedinthefutureandwillkeepupwithframeworkupdates,andbeingofficialtheyarethecanonicalgo-tolibrariesfortheirniche(butyoucanchoosetousewhatyoulike,ofcourse).
OnethingthatputsVueinadifferentbucketcomparedtoReactandAngularisthatVueisanindieproject:it'snotbackedbyahugecorporationlikeFacebookorGoogle.Instead,it'scompletelybackedbythecommunity,whichfostersdevelopmentthroughdonationsandsponsors.ThismakessuretheroadmapofVueisnotdrivenbyasinglecompanyagenda.
IntroductiontoVue
8
VueFirstAppIfyou'venevercreatedaVue.jsapplication,Iamgoingtoguideyouthroughthetaskofcreatingone,andunderstandinghowitworks.Theappwe'regoingtobuildisalreadydone,andit'stheVueCLIdefaultapplication
FirstexampleSeeonCodepen
Secondexample:theVueCLIdefaultappUsetheVueCLIlocallyUseCodeSandboxThefilesstructure
index.html
src/main.js
src/App.vue
src/components/HelloWorld.vue
Runtheapp
Ifyou'venevercreatedaVue.jsapplication,Iamgoingtoguideyouthroughthetaskofcreatingone,andunderstandinghowitworks.
FirstexampleFirstI'llusethemostbasicexampleofusingVue.
YoucreateanHTMLfilewhichcontains
<html>
<body>
<divid="example">
<p>{{hello}}</p>
</div>
<scriptsrc="https://unpkg.com/vue"></script>
<script>
newVue({
el:'#example',
data:{hello:'HelloWorld!'}
})
</script>
</body>
</html>
VueFirstApp
9
andyouopenitinthebrowser.That'syourfirstVueapp!Thepageshouldshowa"HelloWorld!"message.
IputthescripttagsattheendofthebodysothattheyareexecutedinorderaftertheDOMisloaded.
Whatthiscodedoesis,weinstantiateanewVueapp,linkedtothe #exampleelementasitstemplate(it'sdefinedusingaCSSselectorusually,butyoucanalsopassinanHTMLElement).
Then,itassociatesthattemplatetothe dataobject.ThatisaspecialobjectthathoststhedatawewantVuetorender.
Inthetemplate,thespecial {{}}tagindicatesthat'ssomepartofthetemplatethat'sdynamic,anditscontentshouldbelookedupintheVueappdata.
SeeonCodepen
YoucanseethisexampleonCodepen:https://codepen.io/flaviocopes/pen/YLoLOp
CodepenisalittledifferentfromusingaplainHTMLfile,andyouneedtoconfigureittopointtotheVuelibrarylocationinthePensettings:
VueFirstApp
10
Secondexample:theVueCLIdefaultappLet'slevelupthegamealittlebit.Thenextappwe'regoingtobuildisalreadydone,andit'stheVueCLIdefaultapplication.
WhatistheVueCLI?It'sacommandlineutilitythathelpstospeedupdevelopmentbyscaffoldinganapplicationskeletonforyou,withasampleappinplace.
Therearetwowaysyoucangetthisapplication.
UsetheVueCLIlocally
ThefirstistoinstalltheVueCLIonyourcomputer,andrunthecommand
vuecreate<entertheappname>
VueFirstApp
11
UseCodeSandbox
Asimplerway,withouthavingtoinstallanything,istogotohttps://codesandbox.io/s/vue.
CodeSandboxisacoolcodeeditorthatallowsyoubuildappsinthecloud,whichallowsyoutouseanynpmpackageandalsoeasilyintegratewithZeitNowforaneasydeploymentandGitHubtomanageversioning.
ThatlinkIputaboveopenstheVueCLIdefaultapplication.
WhetheryouchosetousetheVueCLIlocally,orthroughCodeSandbox,let'sinspectthatVueappindetails.
Thefilesstructure
Beside package.json,whichcontainstheconfiguration,thesearethefilescontainedintheinitialprojectstructure:
index.html
src/App.vue
src/main.js
src/assets/logo.png
src/components/HelloWorld.vue
index.html
The index.htmlfileisthemainappfile.
Inthebodyitincludesjustonesimpleelement: <divid="app"></div>.ThisistheelementtheVueapplicationwillusetoattachtotheDOM.
<!DOCTYPEhtml>
<html>
<head>
<metacharset="utf-8">
<metaname="viewport"content="width=device-width,initial-scale=1.0">
<title>CodeSandboxVue</title>
</head>
<body>
<divid="app"></div>
<!--builtfileswillbeautoinjected-->
</body>
</html>
VueFirstApp
12
src/main.js
ThisisthemainJavaScriptfilesthatdriveourapp.
WefirstimporttheVuelibraryandtheAppcomponentfrom App.vue.
WesetproductionTiptofalse,justtoavoidVuetooutputa"you'reindevelopmentmode"tipintheconsole.
Next,wecreatetheVueinstance,byassigningittotheDOMelementidentifiedby #app,whichwedefinedin index.html,andwetellittousetheAppcomponent.
//TheVuebuildversiontoloadwiththe`import`command
//(runtime-onlyorstandalone)hasbeensetinwebpack.base.confwithanalias.
importVuefrom'vue'
importAppfrom'./App'
Vue.config.productionTip=false
/*eslint-disableno-new*/
newVue({
el:'#app',
components:{App},
template:'<App/>'
})
src/App.vue
App.vueisaSingleFileComponent.Itcontains3chunksofcode:HTML,CSSandJavaScript.
Thismightseemweirdatfirst,butSingleFileComponentsareagreatwaytocreateself-containedcomponentsthathavealltheyneedinasinglefile.
Wehavethemarkup,theJavaScriptthatisgoingtointeractwithit,andstylethat'sappliedtoit,whichcanbescoped,ornot.Inthiscase,it'snotscoped,andit'sjustoutputtingthatCSSwhichisappliedlikeregularCSStothepage.
Theinterestingpartliesinthe scripttag.
Weimportacomponentfromthe components/HelloWorld.vuefile,whichwe'lldescribelater.
Thiscomponentisgoingtobereferencedinourcomponent.It'sadependency.Wearegoingtooutputthiscode:
<divid="app">
<imgwidth="25%"src="./assets/logo.png">
<HelloWorld/>
</div>
VueFirstApp
13
fromthiscomponent,whichyouseereferencestheHelloWorldcomponent.Vuewillautomaticallyinsertthatcomponentinsidethisplaceholder.
src/components/HelloWorld.vue
Here'stheHelloWorldcomponent,whichisincludedbytheAppcomponent.
Thiscomponentoutputsasetoflinks,alongwithamessage.
RememberabovewetalkedaboutCSSinApp.vue,whichwasnotscoped?TheHelloWorldcomponenthasscopedCSS.
VueFirstApp
14
Youcaneasilydetermineitbylookingatthe styletag.Ifithasthe scopedattribute,thenit'sscoped: <stylescoped>
ThismeansthatthegeneratedCSSwillbetargetingthecomponentuniquely,viaaclassthat'sappliedbyVuetransparently.Youdon'tneedtoworryaboutthis,andyouknowtheCSSwon'tleaktootherpartsofthepage.
Themessagethecomponentoutputsisstoredinthe datapropertyoftheVueinstance,andoutputtedinthetemplateas {{msg}}.
Anythingthat'sstoredin dataisreachabledirectlyinthetemplateviaitsownname.Wedidn'tneedtosay data.msg,just msg.
<template>
<divclass="hello">
<h1>{{msg}}</h1>
<h2>EssentialLinks</h2>
<ul>
<li>
<a
href="https://vuejs.org"
target="_blank"
>
CoreDocs
</a>
</li>
<li>
<a
href="https://forum.vuejs.org"
target="_blank"
>
Forum
</a>
</li>
<li>
<a
href="https://chat.vuejs.org"
target="_blank"
>
CommunityChat
</a>
</li>
<li>
<a
href="https://twitter.com/vuejs"
target="_blank"
>
</a>
</li>
<br>
<li>
<a
VueFirstApp
15
href="http://vuejs-templates.github.io/webpack/"
target="_blank"
>
DocsforThisTemplate
</a>
</li>
</ul>
<h2>Ecosystem</h2>
<ul>
<li>
<a
href="http://router.vuejs.org/"
target="_blank"
>
vue-router
</a>
</li>
<li>
<a
href="http://vuex.vuejs.org/"
target="_blank"
>
vuex
</a>
</li>
<li>
<a
href="http://vue-loader.vuejs.org/"
target="_blank"
>
vue-loader
</a>
</li>
<li>
<a
href="https://github.com/vuejs/awesome-vue"
target="_blank"
>
awesome-vue
</a>
</li>
</ul>
</div>
</template>
<script>
exportdefault{
name:'HelloWorld',
data(){
return{
msg:'WelcometoYourVue.jsApp'
}
}
}
</script>
<!--Add"scoped"attributetolimitCSStothiscomponentonly-->
VueFirstApp
16
<stylescoped>
h1,
h2{
font-weight:normal;
}
ul{
list-style-type:none;
padding:0;
}
li{
display:inline-block;
margin:010px;
}
a{
color:#42b983;
}
</style>
Runtheapp
CodeSandboxhasacoolpreviewfunctionality.Youcanruntheappandeditanythinginthesourcetohaveitimmediatelyreflectedinthepreview.
VueFirstApp
17
CodeSandboxisverycoolforonlinecodingandworkingwithouthavingtosetupVuelocally.AgreatwaytoworklocallyisbysettinguptheVueCLI.Let'sfindoutmoreaboutit.
VueFirstApp
18
TheVueCLIVueisaveryimpressiveproject,andinadditiontothecoreoftheframework,itmaintainsalotofutilitiesthatmakeaVueprogrammer'slifeeasier.OneofthemistheVueCLI.
InstallationWhatdoestheVueCLIprovide?HowtousetheCLItocreateanewVueprojectHowtostartthenewlycreatedVueCLIapplicationGitrepositoryUseapresetfromthecommandlineWherepresetsarestoredPluginsRemotelystorepresetsAnotheruseoftheVueCLI:rapidprototypingWebpack
InthepreviousexampleIintroducedanexampleprojectbasedontheVueCLI.What'stheVueCLIexactly,andhowitfitsintheVueecosystem?Also,howtosetupaVueCLI-basedprojectlocally?Let'sfindout!
Vueisaveryimpressiveproject,andinadditiontothecoreoftheframework,itmaintainsalotofutilitiesthatmakeaVueprogrammer'slifeeasier.
OneofthemistheVueCLI.
CLIstandsforCommandLineInterface.
Note:ThereisahugereworkoftheCLIgoingonrightnow,goingfromversion2to3.Whilenotyetstable,Iwilldescribeversion3becauseit'sahugeimprovementoverversion2,andquitedifferent.
InstallationTheVueCLIisacommandlineutility,andyouinstallitgloballyusingnpm:
npminstall-g@vue/cli
orusingYarn:
TheVueCLI
19
yarnglobaladd@vue/cli
Onceyoudoso,youcaninvokethe vuecommand.
WhatdoestheVueCLIprovide?TheCLIisessentialforrapidVue.jsdevelopment.
Itsmaingoalistomakesureallthetoolsyouneedareworkingalong,toperformwhatyouneed,andabstractsawayallthenitty-grittyconfigurationdetailsthatusingeachtoolinisolationwouldrequire.
Itcanperformaninitialprojectsetupandscaffolding.
It'saflexibletool:onceyoucreateaprojectwiththeCLI,youcangoandtweaktheconfiguration,withouthavingtoejectyourapplication(likeyou'ddowith create-react-app).
Whenyouejectfromcreate-react-appyoucanupdateandtweakwhatyouwant,butyoucan'trelyonthecoolfeaturesthatcreate-react-appprovides
Youcanconfigureanythingandstillbeabletoupgradewithease.
Afteryoucreateandconfiguretheapp,itactsasaruntimedependencytool,builtontopofwebpack.
ThefirstencounterwiththeCLIiswhencreatinganewVueproject.
TheVueCLI
20
HowtousetheCLItocreateanewVueprojectThefirstthingyou'regoingtodowiththeCLIistocreateaVueapp:
vuecreateexample
Thecoolthingisthatit'saninteractiveprocess.Youneedtopickapreset.Bydefault,thereisonepresetthat'sprovidingBabelandESLintintegration:
I'mgoingtopressthedownarrow⬇�andmanuallychoosethefeaturesIwant:
TheVueCLI
21
Press spacetoenableoneofthethingsyouneed,andthenpress entertogoon.SinceIchosealinter/formatter,VueCLIpromptsmefortheconfiguration.IchoseESLint+Prettiersincethat'smyfavoritesetup:
Nextthingischoosinghowtoapplylinting.Ichooselintonsave.
Nextup:testing.Ipickedtesting,andVueCLIoffersmetochoosebetweenthetwomostpopularsolutions:Mocha+ChaivsJest.
TheVueCLI
22
VueCLIasksmewheretoputalltheconfiguration:ifinthe package.jsonfile,orindedicatedconfigurationfiles,oneforeachtool.Ichosethelatter.
Next,VueCLIasksmeifIwanttosavethesepresets,andallowmetopickthemasachoicethenexttimeIuseVueCLItocreateanewapp.It'saveryconvenientfeature,ashavingaquicksetupwithallmypreferencesisacomplexityreliever:
TheVueCLI
23
VueCLIthenasksmeifIpreferusingYarnornpm:
andit'sthelastthingitasksme,andthenitgoesontodownloadthedependenciesandcreatetheVueapp:
TheVueCLI
24
HowtostartthenewlycreatedVueCLIapplicationVueCLIhascreatedtheappforus,andwecangointhe examplefolderandrun yarnservetostartupourfirstappindevelopmentmode:
TheVueCLI
25
Thestarterexampleapplicationsourcecontainsafewfiles,including package.json:
TheVueCLI
26
ThisiswherealltheCLIcommandsaredefined,including yarnserve,whichweusedaminuteago.Theothercommandsare
yarnbuild,tostartaproductionbuildyarnlint,torunthelinteryarntest:unit,toruntheunittests
IwilldescribethesampleapplicationgeneratedbyVueCLIinaseparatetutorial.
Gitrepository
TheVueCLI
27
Noticethe masterwordinthelower-leftcornerofVSCode?That'sbecauseVueCLIautomaticallycreatesarepository,andmakesthefirstcommit,sowecanjumprightin,changethings,andweknowwhatwechanged:
Thisisprettycool.Howmanytimesyoudiveinandchangethings,onlytorealizewhenyouwanttocommittheresult,thatyoudidn'tcommittheinitialstate?
UseapresetfromthecommandlineYoucanskiptheinteractivepanelandinstructVueCLItouseaparticularpreset:
vuecreate-pfavouriteexample-2
WherepresetsarestoredPresetsarestoredinthe .vuejsfileinyourhomedirectory.Here'smineaftercreatingthefirst"favorite"preset
{
"useTaobaoRegistry":false,
"packageManager":"yarn",
"presets":{
"favourite":{
"useConfigFiles":true,
"plugins":{
"@vue/cli-plugin-babel":{},
"@vue/cli-plugin-eslint":{
"config":"prettier",
"lintOn":[
"save"
TheVueCLI
28
]
},
"@vue/cli-plugin-unit-jest":{}
},
"router":true,
"vuex":true
}
}
}
PluginsAsyoucanseefromreadingtheconfiguration,apresetisbasicallyacollectionofplugins,withsomeoptionalconfiguration.
Onceaprojectiscreated,youcanaddmorepluginsbyusing vueadd:
vueadd@vue/cli-plugin-babel
Allthosepluginsareusedinthelatestversionavailable.YoucanforceVueCLItouseaspecificversionbypassingtheversionproperty:
"@vue/cli-plugin-eslint":{
"version":"^3.0.0"
}
thisisusefulifanewversionhasabreakingchangeorabug,andyouneedtowaitalittlebitbeforeusingit.
RemotelystorepresetsApresetcanbestoredinGitHub(oronotherservices)bycreatingarepositorythatcontainsapreset.jsonfile,whichcontainsasinglepresetconfiguration.Extractedfromtheabove,Imadeasamplepresetinhttps://github.com/flaviocopes/vue-cli-preset/blob/master/preset.jsonwhichcontainsthisconfiguration:
{
"useConfigFiles":true,
"plugins":{
"@vue/cli-plugin-babel":{},
"@vue/cli-plugin-eslint":{
"config":"prettier",
"lintOn":[
"save"
TheVueCLI
29
]
},
"@vue/cli-plugin-unit-jest":{}
},
"router":true,
"vuex":true
}
Itcanbeusedtobootstrapanewapplicationusing:
vuecreate--presetflaviocopes/vue-cli-presetexample3
AnotheruseoftheVueCLI:rapidprototypingUntilnowI'veexplainedhowtousetheVueCLItocreateanewprojectfromscratch,withallthebells&whistles.Butforreallyquickprototyping,youcancreateareallysimpleVueapplication,evenonethat'sself-containedinasingle.vuefile,andservethat,withouthavingtodownloadallthedependenciesinthe node_modulesfolder.
How?Firstinstallthe cli-service-globalglobalpackage:
npminstall-g@vue/cli-service-global
//or
yarnglobaladd@vue/cli-service-global
Createanapp.vuefile:
<template>
<div>
<h2>Helloworld!</h2>
<marquee>Heyyy</marquee>
</div>
</template>
andthenrun
vueserveapp.vue
TheVueCLI
30
Youcanservemoreorganizedprojects,composedbyJavaScriptandHTMLfilesaswell.VueCLIbydefaultusesmain.js/index.jsasitsentrypoint,andyoucanhaveapackage.jsonandanytoolconfigurationsetup. vueservewillpickitup.
Sincethisusesglobaldependencies,it'snotanoptimalapproachforanythingmorethandemonstrationorquicktesting.
Running vuebuildwillpreparetheprojectfordeploymentin dist/,andgenerateallthecorrespondingcode,alsoforvendordependencies.
WebpackInternally,VueCLIuseswebpack,buttheconfigurationisabstractedandwedon'tevenseetheconfigfileinourfolder.Youcanstillhaveaccesstoitbycalling vueinspect:
TheVueCLI
31
TheVueCLI
32
DevToolsVuehasagreatpanelthatintegratesintotheBrowserDeveloperTools,whichletsyouinspectyourapplicationandinteractwithit,toeasedebuggingandunderstanding
InstallonChromeInstallonFirefoxInstallthestandaloneappHowtousetheDeveloperTools
FiltercomponentsSelectcomponentinthepageFormatcomponentsnamesFilterinspecteddataInspectDOMOpenineditor
Whenyou'refirstexperimentingwithVue,ifyouopentheBrowserDeveloperToolsyouwillfindthismessage:"DownloadtheVueDevtoolsextensionforabetterdevelopmentexperience:https://github.com/vuejs/vue-devtools"
ThisisafriendlyremindertoinstalltheVueDevtoolsExtension.What'sthat?Anypopularframeworkhasitsowndevtoolsextension,whichgenerallyaddsanewpaneltothebrowserdevelopertoolsthatismuchmorespecializedthantheonesthatthebrowsershipsbydefault.Inthiscase,thepanelwillletusinspectourVueapplicationandinteractwithit.
DevTools
33
ThistoolwillbeanamazinghelpwhenbuildingVueapps.ThedevelopertoolscanonlyinspectaVueapplicationwhenit'sindevelopmentmode.Thismakessurenoonecanusethemtointeractwithyourproductionapp(andwillmakeVuemoreperformantbecauseitdoesnothavetocareaboutthedevtools)
Let'sinstallit!
Thereare3waystoinstalltheVueDevTools:
onChromeonFirefoxasastandaloneapplication
Safari,Edgeandotherbrowsersarenotsupportedwithacustomextension,butusingthestandaloneapplicationyoucandebugaVue.jsapprunninginanybrowser.
InstallonChromeGotothispageontheGoogleChromeStore:https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpdandclickAddtoChrome.
Gothroughtheinstallationprocess:
DevTools
34
TheVue.jsdevtoolsiconshowsupinthetoolbar.IfthepagedoesnothaveaVue.jsinstancerunning,it'sgrayedout.
DevTools
35
IfVue.jsisdetected,theiconhastheVuelogocolors.
DevTools
36
TheicondoesnothingexceptshowingusthatthereisaVue.jsinstance.Tousethedevtools,wemustopentheDeveloperToolspanel,using"View→Developer→DeveloperTools",orCmd-Alt-i
InstallonFirefoxYoucanfindtheFirefoxdevtoolsextensionintheMozillaaddonsstore:https://addons.mozilla.org/en-US/firefox/addon/vue-js-devtools/
DevTools
37
Click"AddtoFirefox"andtheextensionwillbeinstalled.AswithChrome,agrayediconshowsupinthetoolbar
DevTools
38
AndwhenyouvisitasitethathasaVueinstancerunning,itwillbecomegreen,andwhenweopentheDevToolswewillseea"Vue"panel:
DevTools
39
InstallthestandaloneappAlternatively,youcanusetheDevToolsstandaloneapp.
Simplyinstallitusing
npminstall-g@vue/devtools
//or
yarnglobaladd@vue/devtools
andrunitbycalling
vue-devtools
ThiswillopenthestandaloneElectron-basedapplication.
now,pastethescripttagitshowsyou:
<scriptsrc="http://localhost:8098"></script>
DevTools
40
insidetheproject index.htmlfile,andwaitfortheapptobereloaded,anditwillautomaticallyconnecttotheapp:
HowtousetheDeveloperToolsAsmentioned,theVueDevToolscanbeactivatedbyopeningtheDeveloperToolsinthebrowserandmovingtotheVuepanel.
Anotheroptionistoright-clickonanyelementinthepage,andchoose"InspectVuecomponent":
DevTools
41
WhentheVueDevToolspanelisopen,wecannavigatethecomponentstree.Whenwechooseacomponentfromthelistontheleft,therightpanelshowsthepropsanddataitholds:
Onthetopthereare4buttons:
Components(thecurrentpanel),whichlistsallthecomponentinstancesrunninginthecurrentpage.Vuecanhavemultipleinstancesrunningatthesametime,forexampleit
DevTools
42
mightmanageyourshoppingcartwidgetandtheslideshow,withseparate,lightweightapps.VuexiswhereyoucaninspectthestatemanagedthroughVuex.EventsshowsalltheeventsemittedRefreshreloadsthedevtoolspanel
Noticethesmall =$vm0textbesideacomponent?It'sahandywaytoinspectacomponentusingtheConsole.Pressingthe"esc"keyshowsuptheconsoleinthebottomofthedevtools,andyoucantype $vm0toaccesstheVuecomponent:
Thisisverycooltoinspectandinteractwithcomponentswithouthavingtoassignthemtoaglobalvariableinthecode.
Filtercomponents
Starttypingacomponentname,andthecomponentstreewillfilterouttheonesthatdon'tmatch.
DevTools
43
Selectcomponentinthepage
Clickthe
buttonandyoucanhoveranycomponentinthepagewiththemouse,clickit,anditwillbeopenedinthedevtools.
Formatcomponentsnames
YoucanchoosetoshowcomponentsincamelCaseorusedashes.
Filterinspecteddata
Ontherightpanel,youcantypeanywordtofilterthepropertiesthatdon'tmatchit.
InspectDOM
ClicktheInspectDOMbuttontobebroughttotheDevToolsElementsinspector,withtheDOMelementgeneratedbythecomponent:
DevTools
44
Openineditor
Anyusercomponent(notframework-levelcomponents)hasabuttonthatopensitinyourdefaulteditor.Veryhandy.
DevTools
45
ConfiguringVSCodeforVueDevelopmentVisualStudioCodeisoneofthemostusedcodeeditorsintheworldrightnow.Whenyou'resuchapopulareditor,peoplebuildniceplugins.OneofsuchpluginsisanawesometoolthatcanhelpusVue.jsdevelopers.
VeturInstallingVeturSyntaxhighlightingSnippetsIntelliSenseScaffoldingEmmetLintinganderrorcheckingCodeFormatting
VisualStudioCodeisoneofthemostusedcodeeditorsintheworldrightnow.Editorshave,likemanysoftwareproducts,acycle.OnceTextMatewasthefavoritebydevelopers,thenitwasSublimeText,nowit'sVSCode.
Thecoolthingaboutbeingpopularisthatpeoplededicatealotoftimetobuildingpluginsforeverythingtheyimagine.
OneofsuchpluginsisanawesometoolthatcanhelpusVue.jsdevelopers.
VeturIt'scalledVetur,it'shugelypopular,withmorethan3milliondownloads,andyoucanfinditontheVisualStudioMarketplace.
ConfiguringVSCodeforVueDevelopment
46
InstallingVeturClickingtheInstallbuttonwilltriggertheinstallationpanelinVSCode:
ConfiguringVSCodeforVueDevelopment
47
YoucanalsosimplyopentheExtensionsinVSCodeandsearchfor"vetur":
Whatdoesthisextensionprovide?
ConfiguringVSCodeforVueDevelopment
48
SyntaxhighlightingVeturprovidessyntaxhighlightingforallyourVuesourcecodefiles.
WithoutVetur,a.vuefilewillbedisplayedinthiswaybyVSCode:
withVeturinstalled:
ConfiguringVSCodeforVueDevelopment
49
VSCodeisabletorecognizethetypeofcodecontainedinafilefromitsextension.
UsingSingleFileComponent,youmixdifferenttypesofcodeinsidethesamefile,fromCSStoJavaScripttoHTML.
VSCodebydefaultcannotrecognizethiskindofsituation,andVeturallowstoprovidesyntaxhighlightingforeachkindofcodeyouuse.
Veturenablessupport,amongtheothers,for
HTMLCSSJavaScriptPugHamlSCSSPostCSSSassStylusTypeScript
Snippets
ConfiguringVSCodeforVueDevelopment
50
Aswithsyntaxhighlighting,sinceVSCodecannotdeterminethekindofcodecontainedinapartofa.vuefile,itcannotprovidethesnippetswealllove:piecesofcodewecanaddtothefile,providedbyspecializedplugins.
VeturprovidesVSCodetheabilitytouseyourfavoritesnippetsinSingleFileComponents.
IntelliSenseIntelliSenseisalsoenabledbyeVetur,foreachdifferentlanguage,withautocomplete:
ScaffoldingInadditiontoenablingcustomsnippets,Veturprovidesitsownsetofsnippets.Eachonecreatesaspecifictag(template,scriptorstyle)withitsownlanguage:
scaffold
templatewithhtml
templatewithpug
scriptwithJavaScript
scriptwithTypeScript
ConfiguringVSCodeforVueDevelopment
51
stylewithCSS
stylewithCSS(scoped)
stylewithscss
stylewithscss(scoped)
stylewithless
stylewithless(scoped)
stylewithsass
stylewithsass(scoped)
stylewithpostcss
stylewithpostcss(scoped)
stylewithstylus
stylewithstylus(scoped)
Ifyoutype scaffold,you'llgetastarterpackforasingle-filecomponent:
<template>
</template>
<script>
exportdefault{
}
</script>
<style>
</style>
theothersarespecificandcreateasingleblockofcode.
Note:(scoped)meansthatitappliestothecurrentcomponentonly
EmmetEmmet,thepopularHTML/CSSabbreviationsengine,issupportedbydefault.YoucantypeoneoftheEmmetabbreviationsandbypressing tabVSCodewillautomaticallyexpandittotheHTMLequivalent:
ConfiguringVSCodeforVueDevelopment
52
LintinganderrorcheckingVeturintegrateswithESLint,throughtheVSCodeESLintplugin.
ConfiguringVSCodeforVueDevelopment
53
CodeFormatting
ConfiguringVSCodeforVueDevelopment
54
Veturprovidesautomaticsupportforcodeformatting,toformatthewholefileuponsave(incombinationwiththe "editor.formatOnSave"VSCodesetting.
Youcanchoosetodisableautomaticformattingforsomespecificlanguagebysettingthevetur.format.defaultFormatter.XXXXXto noneintheVSCodesettings.Tochangeoneofthosesettings,juststartsearchingforthestring,andoverridewhatyouwantintheusersettings(therightpanel).
MostofthelanguagessupportedusePrettierforautomaticformatting,atoolthat'sbecominganindustrystandard.
UsesyourPrettierconfigurationtodetermineyourpreferences.
ConfiguringVSCodeforVueDevelopment
55
ComponentsComponentsaresingle,independentunitsofaninterface.Theycanhavetheirownstate,markupandstyle.
HowtousecomponentsVuecomponentscanbedefinedin4mainways.
Let'stalkincode.
Thefirstis:
newVue({
/*options*/
})
Thesecondis:
Vue.component('component-name',{
/*options*/
})
Thethirdisbyusinglocalcomponents:componentsthatonlyaccessiblebyaspecificcomponent,andnotavailableelsewhere(greatforencapsulation).
Thefourthisin .vuefiles,alsocalledSingleFileComponents.
Let'sdiveintothefirst3waysindetails.
Using newVue()or Vue.component()isthestandardwaytouseVuewhenyou'rebuildinganapplicationthatisnotaSinglePageApplication(SPA)butratherusesVue.jsjustinsomepages,likeinacontactformorintheshoppingcart.OrmaybeVueisusedinallpages,buttheserverisrenderingthelayout,andyouservetheHTMLtotheclient,whichthenloadstheVueapplicationyoubuild.
InanSPA,whereit'sVuethatbuildstheHTML,it'smorecommontouseSingleFileComponentsastheyaremoreconvenient.
YouinstantiateVuebymountingitonaDOMelement.Ifyouhavea <divid="app"></div>tag,youwilluse:
newVue({el:'#app'})
Components
56
Acomponentinitializedwith newVuehasnocorrespondingtagname,soit'susuallythemaincontainercomponent.
Othercomponentsusedintheapplicationareinitializedusing Vue.component().Suchacomponentallowsyoutodefineatag,withwhichyoucanembedthecomponentmultipletimesintheapplication,andspecifytheoutputofthecomponentinthe templateproperty:
<divid="app">
<user-namename="Flavio"></user-name>
</div>
Vue.component('user-name',{
props:['name'],
template:'<p>Hi{{name}}</p>'
})
newVue({
el:'#app'
})
Whatarewedoing?WeareinitializingaVuerootcomponenton #app,andinsidethat,weusetheVuecomponent user-name,whichabstractsourgreetingtotheuser.
Thecomponentacceptsaprop,whichisanattributeweusetopassdatadowntochildcomponents.
Inthe Vue.component()callwepassed user-nameasthefirstparameter.Thisgivesthecomponentaname.Youcanwritethenamein2wayshere.Thefirstistheoneweused,calledkebab-case.ThesecondiscalledPascalCase,whichislikecamelCase,butwiththefirstlettercapitalized:
Vue.component('UserName',{
/*...*/
})
Vueinternallyautomaticallycreatesanaliasfrom user-nameto UserName,andviceversa,soyoucanusewhateveryoulike.It'sgenerallybesttouse UserNameintheJavaScript,anduser-nameinthetemplate.
LocalcomponentsAnycomponentcreatedusing Vue.component()isgloballyregistered.Youdon'tneedtoassignittoavariableorpassitaroundtoreuseitinyourtemplates.
Components
57
Youcanencapsulatecomponentslocallybyassigninganobjectthatdefinesthecomponentobjecttoavariable:
constSidebar={
template:'<aside>Sidebar</aside>'
}
andthenmakeitavailableinsideanothercomponentbyusingthe componentsproperty:
newVue({
el:'#app',
components:{
Sidebar
}
})
Youcanwritethecomponentinthesamefile,butagreatwaytodothisistouseJavaScriptmodules:
importSidebarfrom'./Sidebar'
exportdefault{
el:'#app',
components:{
Sidebar
}
}
ReusingacomponentAchildcomponentcanbeaddedmultipletimes.Eachseparateinstanceisindependentoftheothers:
<divid="app">
<user-namename="Flavio"></user-name>
<user-namename="Roger"></user-name>
<user-namename="Syd"></user-name>
</div>
Vue.component('user-name',{
props:['name'],
template:'<p>Hi{{name}}</p>'
})
newVue({
el:'#app'
Components
58
})
ThebuildingblocksofacomponentSofarwe'veseenhowacomponentcanacceptthe el, propsand templateproperties.
elisonlyusedinrootcomponentsinitializedusing newVue({}),andidentifiestheDOMelementthecomponentwillmounton.propslistsallthepropertiesthatwecanpassdowntoachildcomponenttemplateiswherewecansetupthecomponenttemplate,whichwillberesponsiblefordefiningtheoutputthecomponentgenerates.
Acomponentacceptsotherproperties:
datathecomponentlocalstatemethods:thecomponentmethodscomputed:thecomputedpropertiesassociatedwiththecomponentwatch:thecomponentwatchers
Components
59
SingleFileComponentsLearnhowVuehelpsyoucreateasinglefilethatisresponsibleforeverythingthatregardsasinglecomponent,centralizingtheresponsibilityfortheappearanceandbehavior
AVuecomponentcanbedeclaredinaJavaScriptfile( .js)likethis:
Vue.component('component-name',{
/*options*/
})
oralso:
newVue({
/*options*/
})
oritcanbespecifiedina .vuefile.
The .vuefileisprettycoolbecauseitallowsyoutodefine
JavaScriptlogicHTMLcodetemplateCSSstyling
allinjustasinglefile,andassuchitgotthenameofSingleFileComponent.
Here'sanexample:
<template>
<p>{{hello}}</p>
</template>
<script>
exportdefault{
data(){
return{
hello:'HelloWorld!'
}
}
}
</script>
<stylescoped>
p{
color:blue;
}
SingleFileComponents
60
</style>
Allofthisispossiblethankstotheuseofwebpack.TheVueCLImakesthisveryeasyandsupportedoutofthebox. .vuefilescannotbeusedwithoutawebpacksetup,andassuch,theyarenotverysuitedtoappsthatjustuseVueonapagewithoutbeingafull-blownsingle-pageapp(SPA).
SinceSingleFileComponentsrelyonWebpack,wegetforfreetheabilitytousemodernWebfeatures.
YourCSScanbedefinedusingSCSSorStylus,thetemplatecanbebuiltusingPug,andallyouneedtodotomakethishappenistodeclaretoVuewhichlanguagepreprocessoryouaregoingtouse.
Thelistofsupportedpreprocessorsinclude
TypeScriptSCSSSassLessPostCSSPug
WecanusemodernJavaScript(ES6-7-8)regardlessofthetargetbrowser,usingtheBabelintegration,andESModulestoo,sowecanuse import/exportstatements.
WecanuseCSSModulestoscopeourCSS.
SpeakingofscopingCSS,SingleFileComponentsmakeitabsolutelyeasytowriteCSSthatwon'tleaktoothercomponents,byusing <stylescoped>tags.
Ifyouomit scoped,theCSSyoudefinewillbeglobal.Butaddingthat,Vueaddsautomaticallyaspecificclasstothecomponent,uniquetoyourapp,sotheCSSisguaranteedtonotleakouttoothercomponents.
MaybeyourJavaScriptishugebecauseofsomelogicyouneedtotakecareof.WhatifyouwanttouseaseparatefileforyourJavaScript?
Youcanusethe srcattributetoexternalizeit:
<template>
<p>{{hello}}</p>
</template>
<scriptsrc="./hello.js"></script>
ThisalsoworksforyourCSS:
SingleFileComponents
61
<template>
<p>{{hello}}</p>
</template>
<scriptsrc="./hello.js"></script>
<stylesrc="./hello.css"></style>
NoticehowIused
exportdefault{
data(){
return{
hello:'HelloWorld!'
}
}
}
inthecomponent'sJavaScripttosetupthedata.
Othercommonwaysyouwillseeare
exportdefault{
data:function(){
return{
name:'Flavio'
}
}
}
(theaboveisequivalenttowhatwedidbefore)
or:
exportdefault{
data:()=>{
return{
name:'Flavio'
}
}
}
thisisdifferentbecauseitusesanarrowfunction.Arrowfunctionsarefineuntilweneedtoaccessacomponentmethod,asweneedtomakeuseof thisandsuchpropertyisnotboundtothecomponentusingarrowfunctions.Soit'smandatorytouseregularfunctionsratherthanarrowfunctions.
Youmightalsosee
module.exports={
SingleFileComponents
62
data:()=>{
return{
name:'Flavio'
}
}
}
thisisusingtheCommonJSsyntax,andworksaswell,althoughit'srecommendedtousetheESModulessyntax,asthatisaJavaScriptstandard.
SingleFileComponents
63
TemplatesVue.jsusesatemplatinglanguagethat'sasupersetofHTML.AnyHTMLisavalidVue.jstemplate,andinadditiontothat,Vue.jsprovidestwopowerfulthings:interpolationanddirectives.
Vue.jsusesatemplatinglanguagethat'sasupersetofHTML.
AnyHTMLisavalidVue.jstemplate,andinadditiontothat,Vue.jsprovidestwopowerfulthings:interpolationanddirectives.
I'mgoingtodetailinterpolationinthisarticle,andmakeanewonetomorrowfordirectives.
ThisisavalidVue.jstemplate:
<span>Hello!</span>
ThistemplatecanbeputinsideaVuecomponentdeclaredexplicitly:
newVue({
template:'<span>Hello!</span>'
})
oritcanbeputintoaSingleFileComponent:
<template>
<span>Hello!</span>
</template>
Thisfirstexampleisverybasic.Thenextstepismakingitoutputapieceofthecomponentstate,forexample,aname.
Thiscanbedoneusinginterpolation.First,weaddsomedatatoourcomponent:
newVue({
data:{
name:'Flavio'
},
template:'<span>Hello!</span>'
})
andthenwecanaddittoourtemplateusingthedoublebracketssyntax:
newVue({
data:{
Templates
64
name:'Flavio'
},
template:'<span>Hello{{name}}!</span>'
})
Oneinterestingthinghere.Seehowwejustused nameinsteadof this.data.name?
ThisisbecauseVue.jsdoessomeinternalbindingandletsthetemplateusethepropertyasifitwaslocal.Prettyhandy.
Inasinglefilecomponent,thatwouldbe:
<template>
<span>Hello{{name}}!</span>
</template>
<script>
exportdefault{
data(){
return{
name:'Flavio'
}
}
}
</script>
Iusedaregularfunctioninmyexport.Whynotanarrowfunction?
Thisisbecausein datawemightneedtoaccessamethodinourcomponentinstance,andwecan'tdothatif thisisnotboundtothecomponent,soarrowfunctionsusageisnotpossible.
Wecoulduseanarrowfunction,butthenIwouldneedtoremembertoswitchtoaregularfunctionincaseIuse this.Betterplayitsafe,Ithink.
Now,backtotheinterpolation.
{{name}}remindsofMustache/Handlebarstemplateinterpolation,butit'sjustavisualreminder.
Whileinthosetemplatingenginestheyare"dumb",inVue,youcandomuchmore,it'smoreflexible.
YoucanuseanyJavaScriptexpressioninsideyourinterpolations,butyou'relimitedtojustoneexpression:
{{name.reverse()}}
Templates
65
{{name==='Flavio'?'Flavio':'stranger'}}
Vueprovidesaccesstosomeglobalobjectsinsidetemplates,includingMathandDate,soyoucanusethem:
{{Math.sqrt(16)*Math.random()}}
It'sbesttoavoidaddingcomplexlogictotemplates,butthefactVueallowsitgivesusmoreflexibility,especiallywhentryingthingsout.
Wecanfirsttrytoputanexpressioninthetemplate,andthenmoveittoacomputedpropertyormethodlateron.
Thevalueincludedinanyinterpolationwillbeupdateduponachangeofanyofthedatapropertiesitrelieson.
Youcanavoidthisreactivitybyusingthe v-oncedirective.
Theresultisalwaysescaped,soyoucan'thaveHTMLintheoutput.
IfyouneedtohaveanHTMLsnippetyouneedtousethe v-htmldirectiveinstead.
Templates
66
StylingcomponentsusingCSSLearnalltheoptionsatyourdisposaltostyleVue.jscomponentsusingCSS
Note:thistutorialusesVue.jsSingleFileComponents
ThesimplestoptiontoaddCSStoaVue.jscomponentistousethe styletag,justlikeinHTML:
<template>
<pstyle="text-decoration:underline">Hi!</p>
</template>
<script>
exportdefault{
data(){
return{
decoration:'underline'
}
}
}
</script>
Thisisasmuchstaticasyoucanget.Whatifyouwant underlinetobedefinedinthecomponentdata?Here'showyoucandoit:
<template>
<p:style="{'text-decoration':decoration}">Hi!</p>
</template>
<script>
exportdefault{
data(){
return{
decoration:'underline'
}
}
}
</script>
:styleisashorthandfor v-bind:style.I'llusethisshorthandthroughoutthistutorial.
Noticehowwehadtowrap text-decorationinquotes.Thisisbecauseofthedash,whichisnotpartofavalidJavaScriptidentifier.
YoucanavoidthequotebyusingaspecialcamelCasesyntaxthatVue.jsenables,andrewritingitto textDecoration:
StylingcomponentsusingCSS
67
<template>
<p:style="{textDecoration:decoration}">Hi!</p>
</template>
Insteadofbindinganobjectto style,youcanreferenceacomputedproperty:
<template>
<p:style="styling">Hi!</p>
</template>
<script>
exportdefault{
data(){
return{
textDecoration:'underline',
textWeight:'bold'
}
},
computed:{
styling:function(){
return{
textDecoration:this.textDecoration,
textWeight:this.textWeight
}
}
}
}
</script>
VuecomponentsgenerateplainHTML,soyoucanchoosetoaddaclasstoeachelement,andaddacorrespondingCSSselectorwithpropertiesthatstyleit:
<template>
<pclass="underline">Hi!</p>
</template>
<style>
.underline{text-decoration:underline;}
</style>
YoucanuseSCSSlikethis:
<template>
<pclass="underline">Hi!</p>
</template>
<stylelang="scss">
body{
.underline{text-decoration:underline;}
}
StylingcomponentsusingCSS
68
</style>
Youcanhardcodetheclasslikeintheaboveexample,oryoucanbindtheclasstoacomponentproperty,tomakeitdynamic,andonlyapplytothatclassifthedatapropertyistrue:
<template>
<p:class="{underline:isUnderlined}">Hi!</p>
</template>
<script>
exportdefault{
data(){
return{
isUnderlined:true
}
}
}
</script>
<style>
.underline{text-decoration:underline;}
</style>
Insteadofbindinganobjecttoclass,likewedidwith <p:class="{text:isText}">Hi!</p>,youcandirectlybindastring,andthatwillreferenceadataproperty:
<template>
<p:class="paragraphClass">Hi!</p>
</template>
<script>
exportdefault{
data(){
return{
paragraphClass:'underline'
}
}
}
</script>
<style>
.underline{text-decoration:underline;}
</style>
Youcanassignmultipleclasseseitheraddingtwoclassesto paragraphClassinthiscaseorbyusinganarray:
<template>
<p:class="[decoration,weight]">Hi!</p>
StylingcomponentsusingCSS
69
</template>
<script>
exportdefault{
data(){
return{
decoration:'underline',
weight:'weight',
}
}
}
</script>
<style>
.underline{text-decoration:underline;}
.weight{font-weight:bold;}
</style>
Thesamecanbedoneusinganobjectinlinedintheclassbinding:
<template>
<p:class="{underline:isUnderlined,weight:isBold}">Hi!</p>
</template>
<script>
exportdefault{
data(){
return{
isUnderlined:true,
isBold:true
}
}
}
</script>
<style>
.underline{text-decoration:underline;}
.weight{font-weight:bold;}
</style>
Andyoucancombinethetwostatements:
<template>
<p:class="[decoration,{weight:isBold}]">Hi!</p>
</template>
<script>
exportdefault{
data(){
return{
decoration:'underline',
isBold:true
}
StylingcomponentsusingCSS
70
}
}
</script>
<style>
.underline{text-decoration:underline;}
.weight{font-weight:bold;}
</style>
Youcanalsouseacomputedpropertythatreturnsanobject,whichworksbestwhenyouhavemanyCSSclassestoaddtothesameelement:
<template>
<p:class="paragraphClasses">Hi!</p>
</template>
<script>
exportdefault{
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>
Noticethatinthecomputedpropertyyouneedtoreferencethecomponentdatausing this.[propertyName],whileinthetemplatedatapropertiesareconvenientlyputasfirst-levelproperties.
AnyCSSthat'snothardcodedlikeinthefirstexampleisgoingtobeprocessedbyVue,andVuedoesthenicejobofautomaticallyprefixingtheCSSforus,sowecanwritecleanCSSwhilestilltargetingolderbrowsers(whichstillmeansbrowsersthatVuesupports,soIE9+)
StylingcomponentsusingCSS
71
StylingcomponentsusingCSS
72
DirectivesVue.jsusesatemplatinglanguagethat'sasupersetofHTML.Wecanuseinterpolation,anddirectives.Thisarticleexplainsdirectives.
v-text
v-once
v-html
v-bind
Two-waybindingusing v-modelUsingexpressionsConditionalsLoopsEventsShoworhideEventdirectivemodifiersCustomdirectives
WesawinVue.jstemplatesandinterpolationshowyoucanembeddatainVuetemplates.
ThisarticleexplainstheothertechniqueofferedbyVue.jsintemplates:directives.
Directives,arebasicallylikeHTMLattributeswhichareaddedinsidetemplates.Theyallstartwith v-,toindicatethat'saVuespecialattribute.
Let'sseeeachoftheVuedirectivesindetails.
v-text
Insteadofusinginterpolation,youcanusethe v-textdirective.Itperformsthesamejob:
<spanv-text="name"></span>
v-once
Youknowhow {{name}}bindstothe namepropertyofthecomponentdata.
Anytime namechangesinyourcomponentdata,Vueisgoingtoupdatethevaluerepresentedinthebrowser.
Directives
73
Unlessyouusethe v-oncedirective,whichisbasicallylikeanHTMLattribute:
<spanv-once>{{name}}</span>
v-html
Whenyouuseinterpolationtoprintadataproperty,theHTMLisescaped.ThisisagreatwaythatVueusestoautomaticallyprotectfromXSSattacks.
TherearecaseshoweverwhereyouwanttooutputHTMLandmakethebrowserinterpretit.Youcanusethe v-htmldirective:
<spanv-html="someHtml"></span>
v-bind
Interpolationonlyworksinthetagcontent.Youcan'tuseitonattributes.
Attributesmustuse v-bind:
<av-bind:href="url">{{linkText}}</a>
v-bindissocommonthatthereisashorthandsyntaxforit:
<av-bind:href="url">{{linkText}}</a>
<a:href="url">{{linkText}}</a>
Two-waybindingusing v-modelv-modelletsusbindaforminputelementforexample,andmakeitchangetheVuedatapropertywhentheuserchangesthecontentofthefield:
<inputv-model="message"placeholder="Enteramessage">
<p>Messageis:{{message}}</p>
<selectv-model="selected">
<optiondisabledvalue="">Chooseafruit</option>
<option>Apple</option>
<option>Banana</option>
<option>Strawberry</option>
</select>
Directives
74
<span>Fruitchosen:{{selected}}</span>
UsingexpressionsYoucanuseanyJavaScriptexpressioninsideadirective:
<spanv-text="'Hi,'+name+'!'"></span>
<av-bind:href="'https://'+domain+path">{{linkText}}</a>
Anyvariableusedinadirectivereferencesthecorrespondingdataproperty.
ConditionalsInsideadirectiveyoucanusetheternaryoperatortoperformaconditionalcheck,sincethat'sanexpression:
<spanv-text="name==Flavio?'HiFlavio!':'Hi'+name+'!'"></span>
Therearededicateddirectivesthatallowyoutoperformmoreorganizedconditionals: v-if,v-elseand v-else-if.
<pv-if="shouldShowThis">Hey!</p>
shouldShowThisisabooleanvaluecontainedinthecomponent'sdata.
Loopsv-forallowsyoutorenderalistofitems.Useitincombinationwith v-bindtosetthepropertiesofeachiteminthelist.
Youcaniterateonasimplearrayofvalues:
<template>
<ul>
<liv-for="iteminitems">{{item}}</li>
</ul>
</template>
<script>
Directives
75
exportdefault{
data(){
return{
items:['car','bike','dog']
}
}
}
</script>
Oronanarrayofobjects:
<template>
<div>
<!--usinginterpolation-->
<ul>
<liv-for="todointodos">{{todo.title}}</li>
</ul>
<!--usingv-text-->
<ul>
<liv-for="todointodos"v-text="todo.title"></li>
</ul>
</div>
</template>
<script>
exportdefault{
data(){
return{
todos:[
{id:1,title:'Dosomething'},
{id:2,title:'Dosomethingelse'}
]
}
}
}
</script>
v-forcangiveyoutheindexusing:
<liv-for="(todo,index)intodos"></li>
Eventsv-onallowsyoutolistentoDOMevents,andtriggeramethodwhentheeventhappens.Herewelistenforaclickevent:
<template>
<av-on:click="handleClick">Clickme!</a>
</template>
Directives
76
<script>
exportdefault{
methods:{
handleClick:function(){
alert('test')
}
}
}
</script>
Youcanpassparameterstoanyevent:
<template>
<av-on:click="handleClick('test')">Clickme!</a>
</template>
<script>
exportdefault{
methods:{
handleClick:function(value){
alert(value)
}
}
}
</script>
andsmallbitsofJavaScript(asingleexpression)canbeputdirectlyintothetemplate:
<template>
<av-on:click="counter=counter+1">{{counter}}</a>
</template>
<script>
exportdefault{
data:function(){
return{
counter:0
}
}
}
</script>
clickisjustonekindofevent.Acommoneventis submit,whichyoucanbindusing v-on:submit.
v-onissocommonthatthereisashorthandsyntaxforit, @:
<av-on:click="handleClick">Clickme!</a>
<a@:click="handleClick">Clickme!</a>
Directives
77
ShoworhideYoucanchoosetoonlyshowanelementintheDOMifaparticularpropertyoftheVueinstanceevaluatestotrue,using v-show:
<pv-show="isTrue">Something</p>
TheelementisstillinsertedintheDOM,butsetto display:noneiftheconditionisnotsatisfied.
EventdirectivemodifiersVueofferssomeoptionaleventmodifiersyoucanuseinassociationwith v-on,whichautomaticallymaketheeventdosomethingwithoutyouexplicitlycodingitinyoureventhandler.
Onegoodexampleis .prevent,whichautomaticallycalls preventDefault()ontheevent.
Inthiscase,theformdoesnotcausethepagetobereloaded,whichisthedefaultbehavior:
<formv-on:submit.prevent="formSubmitted"></form>
Othermodifiersinclude .stop, .capture, .self, .once, .passiveandtheyaredescribedindetailsintheofficialdocs.
CustomdirectivesTheVuedefaultdirectivesalreadyletyoudoalotofwork,butyoucanalwaysaddnew,customdirectivesifyouwant.
Readhttps://vuejs.org/v2/guide/custom-directive.htmlifyou'reinterestedinlearningmore.
Directives
78
EventsVue.jsallowsustointerceptanyDOMeventbyusingthev-ondirectiveonanelement.Thistopiciskeytomakingacomponentinteractive
WhatareVue.jseventsAccesstheoriginaleventobjectEventmodifiers
WhatareVue.jseventsVue.jsallowsustointerceptanyDOMeventbyusingthe v-ondirectiveonanelement.
Ifwewanttodosomethingwhenaclickeventhappensinthiselement:
<template>
<a>Clickme!</a>
</template>
weadda v-ondirective:
<template>
<av-on:click="handleClick">Clickme!</a>
</template>
Vuealsooffersaveryconvenientalternativesyntaxforthis:
<template>
<a@click="handleClick">Clickme!</a>
</template>
Youcanchoosetousetheparenthesesornot. @click="handleClick"isequivalentto@click="handleClick()".
handleClickisamethodattachedtothecomponent:
<script>
exportdefault{
methods:{
handleClick:function(event){
console.log(event)
}
Events
79
}
}
</script>
MethodsareexplainedmoreindetailsinmyVueMethodstutorial.
Whatyouneedtoknowhereisthatyoucanpassparametersfromevents:@click="handleClick(param)"andtheywillbereceivedinsidethemethod.
AccesstheoriginaleventobjectInmanycases,youwillwanttoperformanactionontheeventobjectorlookupsomepropertyinit.Howcanyouaccessit?
Usethespecial $eventdirective:
<template>
<a@click="handleClick($event)">Clickme!</a>
</template>
<script>
exportdefault{
methods:{
handleClick:function(event){
console.log(event)
}
}
}
</script>
andifyoualreadypassavariable:
<template>
<a@click="handleClick('something',$event)">Clickme!</a>
</template>
<script>
exportdefault{
methods:{
handleClick:function(text,event){
console.log(text)
console.log(event)
}
}
}
</script>
Fromthereyoucouldcall event.preventDefault(),butthere'sabetterway:eventmodifiers
Events
80
EventmodifiersInsteadofmessingwithDOM"things"inyourmethods,tellVuetohandlethingsforyou:
@click.preventcall event.preventDefault()@click.stopcall event.stopPropagation()@click.passivemakesuseofthepassiveoptionofaddEventListener@click.captureuseseventcapturinginsteadofeventbubbling@click.selfmakesuretheclickeventwasnotbubbledfromachildevent,butdirectlyhappenedonthatelement@click.oncetheeventwillonlybetriggeredexactlyonce
Allthoseoptionscanbecombinedbyappendingonmodifieraftertheother.
Formoreonpropagation,bubbling/capturingseemyJavaScripteventsguide.
Events
81
MethodsAVuemethodisafunctionassociatedwiththeVueinstance.Methodsaredefinedinsidethe`methods`property.Let'sseehowtheywork.
WhatareVue.jsmethodsPassparameterstoVue.jsmethodsHowtoaccessdatafromamethod
WhatareVue.jsmethodsAVuemethodisafunctionassociatedwiththeVueinstance.
Methodsaredefinedinsidethe methodsproperty:
newVue({
methods:{
handleClick:function(){
alert('test')
}
}
})
orinthecaseofSingleFileComponents:
<script>
exportdefault{
methods:{
handleClick:function(){
alert('test')
}
}
}
</script>
Methodsareespeciallyusefulwhenyouneedtoperformanactionandyouattacha v-ondirectiveonanelementtohandleevents.Likethisone,whichcalls handleClickwhentheelementisclicked:
<template>
<a@click="handleClick">Clickme!</a>
</template>
Methods
82
PassparameterstoVue.jsmethodsMethodscanacceptparameters.
Inthiscase,youjustpasstheparameterinthetemplate,andyou
<template>
<a@click="handleClick('something')">Clickme!</a>
</template>
newVue({
methods:{
handleClick:function(text){
alert(text)
}
}
})
orinthecaseofSingleFileComponents:
<script>
exportdefault{
methods:{
handleClick:function(text){
alert(text)
}
}
}
</script>
HowtoaccessdatafromamethodYoucanaccessanyofthedatapropertiesoftheVuecomponentbyusing this.propertyName:
<template>
<a@click="handleClick()">Clickme!</a>
</template>
<script>
exportdefault{
data(){
return{
name:'Flavio'
}
},
methods:{
handleClick:function(){
Methods
83
console.log(this.name)
}
}
}
</script>
Wedon'thavetouse this.data.name,just this.name.Vuedoesprovideatransparentbindingforus.Using this.data.namewillraiseanerror.
Asyousawbeforeintheeventsdescription,methodsarecloselyinterlinkedtoevents,becausetheyareusedaseventhandlers.Everytimeaneventoccurs,thatmethodiscalled.
Methods
84
WatchersAVuewatcherallowsyoutolistentothecomponentdataandrunwheneveraparticularpropertychanges
AwatcherisaspecialVue.jsfeaturethatallowsyoutospyononepropertyofthecomponentstate,andrunafunctionwhenthatpropertyvaluechanges.
Here'sanexample.Wehaveacomponentthatshowsaname,andallowsyoutochangeitbyclickingabutton:
<template>
<p>Mynameis{{name}}</p>
<button@click="changeName()">Changemyname!</button>
</template>
<script>
exportdefault{
data(){
return{
name:'Flavio'
}
},
methods:{
changeName:function(){
this.name='Flavius'
}
}
}
</script>
Whenthenamechangeswewanttodosomething,likeprintingaconsolelog.
Wecandosobyaddingtothe watchobjectapropertynamedasthedatapropertywewanttowatchover:
<script>
exportdefault{
data(){
return{
name:'Flavio'
}
},
methods:{
changeName:function(){
this.name='Flavius'
}
},
watch:{
name:function(){
Watchers
85
console.log(this.name)
}
}
}
</script>
Thefunctionassignedto watch.namecanoptionallyaccept2parameters.Thefirstisthenewpropertyvalue.Thesecondistheoldpropertyvalue:
<script>
exportdefault{
/*...*/
watch:{
name:function(newValue,oldValue){
console.log(newValue,oldValue)
}
}
}
</script>
Watcherscannotbelookedupfromatemplateasyoucanwithcomputedproperties.
Watchers
86
ComputedPropertiesLearnhowyoucanuseVueComputedPropertiestocachecalculations
WhatisaComputedPropertyAnexampleofacomputedpropertyComputedpropertiesvsmethods
WhatisaComputedPropertyInVue.jsyoucanoutputanydatavalueusingparentheses:
<template>
<p>{{count}}</p>
</template>
<script>
exportdefault{
data(){
return{
count:1
}
}
}
</script>
Thispropertycanhostsomesmallcomputations,forexample
<template>
{{count*10}}
</template>
butyou'relimitedtoasingleJavaScriptexpression.
Inadditiontothistechnicallimitation,youalsoneedtoconsiderthattemplatesshouldonlybeconcernedwithdisplayingdatatotheuser,notperformlogiccomputations.
Todosomethingmoreasingleexpression,andtohavemoredeclarativetemplates,thatyouuseacomputedproperty.
Computedpropertiesaredefinedinthe computedpropertyoftheVuecomponent:
<script>
exportdefault{
ComputedProperties
87
computed:{
}
}
</script>
AnexampleofacomputedpropertyHere'sanexamplecodethatusesacomputedproperty counttocalculatetheoutput.Notice:
Ididn'thavetocall
{{count()}}
becauseVue.jsautomaticallyinvokesthefunction
Also,Iusedaregularfunction(notanarrowfunction)todefinethe countcomputedpropertybecauseIneedtobeabletoaccessthecomponentinstancethrough this.
<template>
<p>{{count}}</p>
</template>
<script>
exportdefault{
data(){
return{
items:[1,2,3]
}
},
computed:{
count:function(){
return'Thecountis'+this.items.length*10
}
}
}
</script>
ComputedpropertiesvsmethodsIfyoualreadyknowVuemethods,youmaywonderwhat'sthedifference.
First,methodsmustbecalled,notjustreferenced,soyou'dneedtodo:
<template>
<p>{{count()}}</p>
</template>
ComputedProperties
88
<script>
exportdefault{
data(){
return{
items:[1,2,3]
}
},
methods:{
count:function(){
return'Thecountis'+this.items.length*10
}
}
}
</script>
Butthemaindifferenceisthatcomputedpropertiesarecached.
Theresultofthe countcomputedpropertyisinternallycacheduntilthe itemsdatapropertychanges.
Important:computedpropertiesareonlyupdatedwhenareactivesourceupdates.RegularJavaScriptmethodsarenotreactive,soacommonexampleistouse Date.now():
<template>
<p>{{now}}</p>
</template>
<script>
exportdefault{
computed:{
now:function(){
returnDate.now()
}
}
}
</script>
Itwillrenderonce,andthenitwillnotbeupdatedevenwhenthecomponentre-renders.Justonapagerefresh,whentheVuecomponentisquitandreinitialized.
Inthiscaseamethodisbettersuitedforyourneeds.
ComputedProperties
89
MethodsvsWatchersvsComputedPropertiesVue.jsprovidesusmethods,watchersandcomputedproperties.Whentouseonevstheother?
WhentousemethodsToreactonsomeeventhappeningintheDOMTocallafunctionwhensomethinghappensinyourcomponent.Youcancallamethodsfromcomputedpropertiesorwatchers.
WhentousecomputedpropertiesYouneedtocomposenewdatafromexistingdatasourcesYouhaveavariableyouuseinyourtemplatethat'sbuiltfromoneormoredatapropertiesYouwanttoreduceacomplicated,nestedpropertynametoamorereadableandeasytouseone,yetupdateitwhentheoriginalpropertychangesYouneedtoreferenceavaluefromthetemplate.Inthiscase,creatingacomputedpropertyisthebestthingbecauseit'scached.Youneedtolistentochangesofmorethanonedataproperty
WhentousewatchersYouwanttolistenwhenadatapropertychanges,andperformsomeactionYouwanttolistentoapropvaluechangeYouonlyneedtolistentoonespecificproperty(youcan'twatchmultiplepropertiesatthesametime)Youwanttowatchadatapropertyuntilitreachessomespecificvalueandthendosomething
MethodsvsWatchersvsComputedProperties
90
PropsPropsareusedtopassdownstatetochildcomponents.Learnallaboutthem
DefineapropinsidethecomponentAcceptmultiplepropsSettheproptypeSetaproptobemandatorySetthedefaultvalueofapropPassingpropstothecomponent
DefineapropinsidethecomponentPropsarethewaycomponentscanacceptdatafromcomponentsthatincludethem(parentcomponents).
Whenacomponentexpectsoneormoreprop,itmustdefinetheminits propsproperty:
Vue.component('user-name',{
props:['name'],
template:'<p>Hi{{name}}</p>'
})
or,inaVueSingleFileComponent:
<template>
<p>{{name}}</p>
</template>
<script>
exportdefault{
props:['name']
}
</script>
AcceptmultiplepropsYoucanhavemultiplepropsbysimplyappendingthemtothearray:
Vue.component('user-name',{
props:['firstName','lastName'],
template:'<p>Hi{{firstName}}{{lastName}}</p>'
})
Props
91
SettheproptypeYoucanspecifythetypeofapropverysimplybyusinganobjectinsteadofanarray,usingthenameofthepropertyasthekeyofeachproperty,andthetypeasthevalue:
Vue.component('user-name',{
props:{
firstName:String,
lastName:String
},
template:'<p>Hi{{firstName}}{{lastName}}</p>'
})
Thevalidtypesyoucanuseare:
StringNumberBooleanArrayObjectDateFunctionSymbol
Whenatypemismatches,Vuealerts(indevelopmentmode)intheconsolewithawarning.
Proptypescanbemorearticulated.
Youcanallowmultipledifferentvaluetypes:
props:{
firstName:[String,Number]
}
SetaproptobemandatoryYoucanrequireaproptobemandatory:
props:{
firstName:{
type:String,
required:true
}
Props
92
}
SetthedefaultvalueofapropYoucanspecifyadefaultvalue:
props:{
firstName:{
type:String,
default:'Unknownperson'
}
}
Forobjects:
props:{
name:{
type:Object,
default:{
firstName:'Unknown',
lastName:''
}
}
}
defaultcanalsobeafunctionthatreturnsanappropriatevalue,ratherthanbeingtheactualvalue.
Youcanevenbuildacustomvalidator,whichiscoolforcomplexdata:
props:{
name:{
validator:name=>{
returnname==='Flavio'//onlyallow"Flavios"
}
}
}
PassingpropstothecomponentYoupassaproptoacomponentusingthesyntax
<ComponentNamecolor="white"/>
Props
93
ifwhatyoupassisastaticvalue.
Ifit'sadataproperty,youuse
<template>
<ComponentName:color=color/>
</template>
<script>
...
exportdefault{
//...
data:function(){
return{
color:'white'
}
},
//...
}
</script>
Youcanuseaternaryoperatorinsidethepropvaluetocheckatruthyconditionandpassavaluethatdependsonit:
<template>
<ComponentName:colored="color=='white'?true:false"/>
</template>
<script>
...
exportdefault{
//...
data:function(){
return{
color:'white'
}
},
//...
}
</script>
Props
94
SlotsSlotshelpyoupositioncontentinacomponent,andallowparentcomponentstoarrangeit.
Acomponentcanchoosetodefineitscontententirely,likeinthiscase:
Vue.component('user-name',{
props:['name'],
template:'<p>Hi{{name}}</p>'
})
oritcanalsolettheparentcomponentinjectanykindofcontentintoit,byusingslots.
What'saslot?
Youdefineitbyputting <slot></slot>inacomponenttemplate:
Vue.component('user-information',{
template:'<divclass="user-information"><slot></slot></div>'
})
Whenusingthiscomponent,anycontentaddedbetweentheopeningandclosingtagwillbeaddedinsidetheslotplaceholder:
<user-information>
<h2>Hi!</h2>
<user-namename="Flavio">
</user-information>
Ifyouputanycontentsidethe <slot></slot>tags,thatservesasthedefaultcontentincasenothingispassedin.
Acomplicatedcomponentlayoutmightrequireabetterwaytoorganizecontent.
Enternamedslots.
Withanamedslotyoucanassignpartsofaslottoaspecificpositioninyourcomponenttemplatelayout,andyouusea slotattributetoanytag,toassigncontenttothatslot.
Anythingoutsideanytemplatetagisaddedtothemain slot.
ForconvenienceIusea pagesinglefilecomponentinthisexample:
<template>
<div>
Slots
95
<main>
<slot></slot>
</main>
<sidebar>
<slotname="sidebar"></slot>
</sidebar>
</div>
</template>
<page>
<ulslot="sidebar">
<li>Home</li>
<li>Contact</li>
</ul>
<h2>Pagetitle</h2>
<p>Pagecontent</p>
</page>
Slots
96
FiltersFiltersarethewayVue.jsletsusapplyformattingandtransformationstoavaluethat'susedinatemplateinterpolation.
FiltersareafunctionalityprovidedbyVuecomponentsthatletyouapplyformattingandtransformationstoanypartofyourtemplatedynamicdata.
Theydon'tchangeacomponentdataoranything,buttheyonlyaffecttheoutput.
Sayyouareprintinganame:
<template>
<p>Hi{{name}}!</p>
</template>
<script>
exportdefault{
data(){
return{
name:'Flavio'
}
}
}
</script>
Whatifyouwanttocheckthat nameisactuallycontainingavalue,andifnotprint'there',sothatourtemplatewillprint"Hithere!"?
Enterfilters:
<template>
<p>Hi{{name|fallback}}!</p>
</template>
<script>
exportdefault{
data(){
return{
name:'Flavio'
}
},
filters:{
fallback:function(name){
returnname?name:'there'
}
}
}
</script>
Filters
97
Noticethesyntaxtoapplyafilter,whichis |filterName.Ifyou'refamiliarwithUnix,that'stheUnixpipeoperator,whichisusedtopasstheoutputofanoperationasaninputtothenextone.
The filterspropertyofthecomponentisanobject.Asinglefilterisafunctionthatacceptsavalueandreturnsanothervalue.
Thereturnedvalueistheonethat'sactuallyprintedintheVue.jstemplate.
Thefilter,ofcourse,hasaccesstothecomponentdataandmethods.
What'sagoodusecaseforfilters?
transformingastring,forexample,capitalizingormakingitlowercaseformattingaprice
Aboveyousawasimpleexampleofafilter: {{name|fallback}}.
Filterscanbechained,byrepeatingthepipesyntax:
{{name|fallback|capitalize}}
Thisfirstappliesthe fallbackfilter,thenthe capitalizefilter(whichwedidn'tdefine,buttrymakingone!).
Advancedfilterscanalsoacceptparameters,usingthenormalfunctionparameterssyntax:
<template>
<p>Hello{{name|prepend('Dr.')}}</p>
</template>
<script>
exportdefault{
data(){
return{
name:'House'
}
},
filters:{
prepend:(name,prefix)=>{
return`${prefix}${name}`
}
}
}
</script>
Ifyoupassparameterstoafilter,thefirstonepassedtothefilterfunctionisalwaystheiteminthetemplateinterpolation( nameinthiscase),followedbytheexplicitparametersyoupassed.
Filters
98
Youcanusemultipleparametersbyseparatingthemusingacomma.
NoticeIusedanarrowfunction.Weavoidarrowfunctioninmethodsandcomputedpropertiesgenerallybecausetheyalmostalwaysreference thistoaccessthecomponentdata,butinthiscase,thefilterdoesnotneedtoaccessthisbutreceivesallthedataitneedsthroughtheparameters,andwecansafelyusethesimplerarrowfunctionsyntax.
Thispackagehasalotofpre-madefiltersforyoutousedirectlyintemplates,whichincludecapitalize, uppercase, lowercase, placeholder, truncate, currency, pluralizeandmore.
Filters
99
CommunicationamongcomponentsHowyoucanmakecomponentscommunicateinaVue.jsapplication.
PropsEventstocommunicatefromchildrentoparentUsinganEventBustocommunicatebetweenanycomponentAlternatives
ComponentsinVuecancommunicateinvariousways.
PropsThefirstwayisusingprops.
Parents"passdown"databyaddingargumentstothecomponentdeclaration:
<template>
<div>
<Carcolor="green"/>
</div>
</template>
<script>
importCarfrom'./components/Car'
exportdefault{
name:'App',
components:{
Car
}
}
</script>
Propsareone-way:fromparenttochild.Anytimetheparentchangestheprop,thenewvalueissenttothechildandrerendered.
Thereverseisnottrue,andyoushouldnevermutateapropinsidethechildcomponent.
UsingEventstocommunicatefromchildrentoparent
Communicationamongcomponents
100
Eventsallowyoutocommunicatefromthechildrenuptotheparent:
<script>
exportdefault{
name:'Car',
methods:{
handleClick:function(){
this.$emit('clickedSomething')
}
}
}
</script>
Theparentcaninterceptthisusingthe v-ondirectivewhenincludingthecomponentinitstemplate:
<template>
<div>
<Carv-on:clickedSomething="handleClickInParent"/>
<!--or-->
<Car@clickedSomething="handleClickInParent"/>
</div>
</template>
<script>
exportdefault{
name:'App',
methods:{
handleClickInParent:function(){
//...
}
}
}
</script>
Youcanpassparametersofcourse:
<script>
exportdefault{
name:'Car',
methods:{
handleClick:function(){
this.$emit('clickedSomething',param1,param2)
}
}
}
</script>
andretrievethemfromtheparent:
Communicationamongcomponents
101
<template>
<div>
<Carv-on:clickedSomething="handleClickInParent"/>
<!--or-->
<Car@clickedSomething="handleClickInParent"/>
</div>
</template>
<script>
exportdefault{
name:'App',
methods:{
handleClickInParent:function(param1,param2){
//...
}
}
}
</script>
UsinganEventBustocommunicatebetweenanycomponentUsingeventsyou'renotlimitedtochild-parentrelationships.
Youcanusetheso-calledEventBus.
Aboveweused this.$emittoemitaneventonthecomponentinstance.
Whatwecandoinsteadistoemittheeventonamoregenerallyaccessiblecomponent.
this.$root,therootcomponent,iscommonlyusedforthis.
YoucanalsocreateaVuecomponentdedicatedtothisjob,andimportitwhereyouneed.
<script>
exportdefault{
name:'Car',
methods:{
handleClick:function(){
this.$root.$emit('clickedSomething')
}
}
}
</script>
Anyothercomponentcanlistenforthisevent.Youcandosointhe mountedcallback:
<script>
exportdefault{
Communicationamongcomponents
102
name:'App',
mounted(){
this.$root.$on('clickedSomething',()=>{
//...
})
}
}
</script>
AlternativesThisiswhatVueprovidesoutofthebox.
Whenyououtgrowthis,youcanlookintoVuexorother3rdpartlibraries.
Communicationamongcomponents
103
VuexVuexistheofficialstatemanagementlibraryforVue.js.InthistutorialI'mgoingtoexplainitsbasicusage.
IntroductiontoVuexWhyshouldyouuseVuexLet'sstartCreatetheVuexstoreAnusecaseforthestoreIntroducingthenewcomponentsweneedAddingthosecomponentstotheappAddthestatetothestoreAddamutationAddagettertoreferenceastatepropertyAddingtheVuexstoretotheappUpdatethestateonauseractionusingcommitUsethegettertoprintthestatevalueWrappingup
IntroductiontoVuexVuexistheofficialstatemanagementlibraryforVue.js.
Itsjobistosharedataacrossthecomponentsofyourapplication.
ComponentsinVue.jsoutoftheboxcancommunicateusing
props,topassstatedowntochildcomponentsfromaparentevents,tochangethestateofaparentcomponentfromachild,orusingtherootcomponentasaneventbus
Sometimesthingsgetmorecomplexthanwhatthesesimpleoptionsallow.
Inthiscase,agoodoptionistocentralizethestateinasinglestore.ThisiswhatVuexdoes.
WhyshouldyouuseVuexVuexisnottheonlystatemanagementoptionyoucanuseinVue(youcanuseReduxtoo),butitsmainadvantageisthatit'sofficial,anditsintegrationwithVue.jsiswhatmakesitshine.
Vuex
104
WithReactyouhavethetroubleofhavingtochooseoneofthemanylibrariesavailable,astheecosystemishugeandhasnode-factostandard.LatelyReduxwasthemostpopularchoice,withMobXfollowingupintermsofpopularity.WithVueI'dgoasfarastosaythatyouwon'tneedtolookaroundforanythingotherthanVuex,especiallywhenstartingout.
VuexborrowedmanyofitsideasfromtheReactecosystem,asthisistheFluxpatternpopularizedbyRedux.
IfyouknowFluxorReduxalready,Vuexwillbeveryfamiliar.Ifyoudon't,noproblem-I'llexplaineveryconceptfromthegroundup.
ComponentsinaVueapplicationcanhavetheirownstate.Forexample,aninputboxwillstorethedataenteredintoitlocally.Thisisperfectlyfine,andcomponentscanhavelocalstateevenwhenusingVuex.
YouknowthatyouneedsomethinglikeVuexwhenyoustartdoingalotofworktopassapieceofstatearound.
InthiscaseVuexprovidesacentralrepositorystoreforthestate,andyoumutatethestatebyaskingthestoretodothat.
Everycomponentthatdependsonaparticularpieceofthestatewillaccessitusingagetteronthestore,whichmakessureit'supdatedassoonasthatthingchanges.
UsingVuexwillintroducesomecomplexityintotheapplication,asthingsneedtobesetupinacertainwaytoworkcorrectly,butifthishelpssolvetheunorganizedpropspassingandeventsystemthatmightgrowintoaspaghettimessiftoocomplicated,thenit'sagoodchoice.
Let'sstartInthisexampleI'mstartingfromaVueCLIapplication.Vuexcanbeusedalsobydirectlyloadingitintoascripttag,butsinceVuexismoreintunewithbiggerapplications,it'smuchmorelikelyyouwilluseitonamorestructuredapplication,liketheonesyoucanstartupquicklywiththeVueCLI.
TheexamplesIusewillbeputCodeSandbox,whichisagreatservicethathasaVueCLIsamplereadytogoathttps://codesandbox.io/s/vue.Irecommendusingittoplayaround.
Vuex
105
Onceyou'rethere,clicktheAdddependencybutton,enter"vuex"andclickit.
NowVuexwillbelistedintheprojectdependencies.
ToinstallVuexlocallyyoucansimplyrun npminstallvuexor yarnaddvuexinsidetheprojectfolder.
CreatetheVuexstoreNowwearereadytocreateourVuexstore.
Thisfilecanbeputanywhere.It'sgenerallysuggestedtoputitinthe src/store/store.jsfile,sowe'lldothat.
InthisfileweinitializeVuexandwetellVuetouseit:
importVuefrom'vue'
importVuexfrom'vuex'
Vue.use(Vuex)
exportconststore=newVuex.Store({})
Vuex
106
WeexportaVuexstoreobject,whichwecreateusingthe Vuex.Store()API.
AnusecaseforthestoreNowthatwehaveaskeletoninplace,let'scomeupwithanideaforagoodusecaseforVuex,soIcanintroduceitsconcepts.
Forexample,Ihave2siblingcomponents,onewithaninputfield,andonethatprintsthatinputfieldcontent.
Whentheinputfieldischanged,Iwanttoalsochangethecontentinthatsecondcomponent.Verysimplebutthiswilldothejobforus.
IntroducingthenewcomponentsweneedIdeletetheHelloWorldcomponentandaddaFormcomponent,andaDisplaycomponent.
<template>
<div>
<labelfor="flavor">Favoriteicecreamflavor?</label>
<inputname="flavor">
</div>
</template>
Vuex
107
<template>
<div>
<p>Youchose???</p>
</div>
</template>
AddingthosecomponentstotheappWeaddthemtotheApp.vuecodeinsteadoftheHelloWorldcomponent:
<template>
<divid="app">
<Form/>
<Display/>
</div>
</template>
<script>
importFormfrom'./components/Form'
importDisplayfrom'./components/Display'
exportdefault{
name:'App',
components:{
Form,
Display
}
}
</script>
AddthestatetothestoreSowiththisinplace,wegobacktothestore.jsfileandweaddapropertytothestorecalledstate,whichisanobject,thatcontainsthe flavorproperty.That'sanemptystringinitially.
importVuefrom'vue'
importVuexfrom'vuex'
Vue.use(Vuex)
exportconststore=newVuex.Store({
state:{
flavor:''
}
})
We'llupdateitwhentheusertypesintotheinputfield.
Vuex
108
AddamutationThestatecannotbemanipulatedexceptbyusingmutations.WesetuponemutationwhichwillbeusedinsidetheFormcomponenttonotifythestorethatthestateshouldchange.
importVuefrom'vue'
importVuexfrom'vuex'
Vue.use(Vuex)
exportconststore=newVuex.Store({
state:{
flavor:''
},
mutations:{
change(state,flavor){
state.flavor=flavor
}
}
})
AddagettertoreferenceastatepropertyWiththatset,weneedtoaddawaytolookatthestate.Wedosousinggetters.Wesetupagetterforthe flavorproperty:
importVuefrom'vue'
importVuexfrom'vuex'
Vue.use(Vuex)
exportconststore=newVuex.Store({
state:{
flavor:''
},
mutations:{
change(state,flavor){
state.flavor=flavor
}
},
getters:{
flavor:state=>state.flavor
}
})
Noticehow gettersisanobject. flavorisapropertyofthisobject,whichacceptsthestateastheparameter,andreturnsthe flavorpropertyofthestate.
Vuex
109
AddingtheVuexstoretotheappNowthestoreisreadytobeused.Wegobacktoourapplicationcode,andinthemain.jsfile,weneedtoimportthestateandmakeitavailableinourVueapp.
Weadd
import{store}from'./store/store'
andweaddittotheVueapplication:
newVue({
el:'#app',
store,
components:{App},
template:'<App/>'
})
Onceweaddthis,sincethisisthemainVuecomponent,the storevariableinsideeveryVuecomponentwillpointtotheVuexstore.
UpdatethestateonauseractionusingcommitLet'supdatethestatewhentheusertypessomething.
Wedosobyusingthe store.commit()API.
Butfirst,let'screateamethodthatisinvokedwhentheinputcontentchanges.Weuse@inputratherthan @changebecausethelatterisonlytriggeredwhenthefocusismovedawayfromtheinputbox,while @inputiscalledoneverykeypress.
<template>
<div>
<labelfor="flavor">Favoriteicecreamflavor?</label>
<input@input="changed"name="flavor">
</div>
</template>
<script>
exportdefault{
methods:{
changed:function(event){
alert(event.target.value)
}
}
}
</script>
Vuex
110
Nowthatwehavethevalueoftheflavor,weusetheVuexAPI:
<script>
exportdefault{
methods:{
changed:function(event){
this.$store.commit('change',event.target.value)
}
}
}
</script>
seehowwereferencethestoreusing this.$store?ThisisthankstotheinclusionofthestoreobjectinthemainVuecomponentinitialization.
The commit()methodacceptsamutationname(weused changeintheVuexstore)andapayload,whichwillbepassedtothemutationasthesecondparameterofitscallbackfunction.
UsethegettertoprintthestatevalueNowweneedtoreferencethegetterofthisvalueintheDisplaytemplate,byusing$store.getters.flavor. thiscanberemovedbecausewe'reinthetemplate,and thisisimplicit.
<template>
<div>
<p>Youchose{{$store.getters.flavor}}</p>
</div>
</template>
WrappingupThat'sitforanintroductiontoVuex!
Thefull,workingsourcecodeisavailableathttps://codesandbox.io/s/zq7k7nkzkm
Therearestillmanyconceptsmissinginthispuzzle:
actionsmoduleshelpersplugins
Vuex
111
butyouhavethebasicstogoandreadaboutthemintheofficialdocs.
Happycoding!
Vuex
112
VueRouterDiscoveroneoftheessentialpiecesofaVueapplication:therouter
IntroductionInaJavaScriptwebapplication,arouteristhepartthatsyncsthecurrentlydisplayedviewwiththebrowseraddressbarcontent.
Inotherwords,it'sthepartthatmakestheURLchangewhenyouclicksomethinginthepage,andhelpstoshowthecorrectviewwhenyouhitaspecificURL.
TraditionallytheWebisbuiltaroundURLs.WhenyouhitacertainURL,aspecificpageisdisplayed.
Withtheintroductionofapplicationsthatruninsidethebrowserandchangewhattheusersees,manyapplicationsbrokethisinteraction,andyouhadtomanuallyupdatetheURLwiththebrowser'sHistoryAPI.
YouneedarouterwhenyouneedtosyncURLstoviewsinyourapp.It'saverycommonneed,andallthemajormodernframeworksnowallowyoutomanagerouting.
TheVueRouterlibraryisthewaytogoforVue.jsapplications.Vuedoesnotenforcetheuseofthislibrary.Youcanusewhatevergenericroutinglibraryyouwant,oralsocreateyourownHistoryAPIintegration,butthebenefitofusingVueRouteristhatit'sofficial.
Thismeansit'smaintainedbythesamepeoplewhomaintainVue,soyougetamoreconsistentintegrationintheframework,andtheguaranteethatit'salwaysgoingtobecompatibleinthefuture,nomatterwhat.
InstallationVueRouterisavailablevianpmwiththepackagenamed vue-router.
IfyouuseVueviaascripttag,youcanincludeVueRouterusing
<scriptsrc="https://unpkg.com/vue-router"></script>
unpkg.comisaveryhandytoolthatmakeseverynpmpackageavailableinthebrowserwithasimplelink
VueRouter
113
IfyouusetheVueCLI,installitusing
npminstallvue-router
Onceyouinstall vue-routerandmakeitavailableeitherusingascripttagorviaVueCLI,youcannowimportitinyourapp.
Youimportitafter vue,andyoucall Vue.use(VueRouter)toinstallitinsidetheapp:
importVuefrom'vue'
importVueRouterfrom'vue-router'
Vue.use(VueRouter)
Afteryoucall Vue.use()passingtherouterobject,inanycomponentoftheappyouhaveaccesstotheseobjects:
this.$routeristherouterobjectthis.$routeisthecurrentrouteobject
TherouterobjectTherouterobject,accessedusing this.$routerfromanycomponentwhentheVueRouterisinstalledintherootVuecomponent,offersmanynicefeatures.
Wecanmaketheappnavigatetoanewrouteusing
this.$router.push()
this.$router.replace()
this.$router.go()
whichresemblethe pushState, replaceStateand gomethodsoftheHistoryAPI.
push()isusedtogotoanewroute,addinganewitemtothebrowserhistory. replace()isthesame,exceptitdoesnotpushanewstatetothehistory.
Usagesamples:
this.$router.push('about')//namedroute,seelater
this.$router.push({path:'about'})
this.$router.push({path:'post',query:{post_slug:'hello-world'}})//usingquerypar
ameters(post?post_slug=hello-world)
this.$router.replace({path:'about'})
VueRouter
114
go()goesbackandforth,acceptinganumberthatcanbepositiveornegativetogobackinthehistory:
this.$router.go(-1)//goback1step
this.$router.go(1)//goforward1step
DefiningtheroutesI'musingaVueSingleFileComponentinthisexample.
InthetemplateIusea navtagthathas3 router-linkcomponents,whichhavealabel(Home/Login/About)andaURLassignedthroughthe toattribute.
The router-viewcomponentiswheretheVueRouterwillputthecontentthatmatchesthecurrentURL.
<template>
<divid="app">
<nav>
<router-linkto="/">Home</router-link>
<router-linkto="/login">Login</router-link>
<router-linkto="/about">About</router-link>
</nav>
<router-view></router-view>
</div>
</template>
A router-linkcomponentrendersan atagbydefault(youcanchangethat).Everytimetheroutechanges,eitherbyclickingalinkorbychangingtheURL,a router-link-activeclassisaddedtotheelementthatreferstotheactiveroute,allowingyoutostyleit.
IntheJavaScriptpartwefirstincludeandinstalltherouter,thenwedefine3routecomponents.
Wepassthemtotheinitializationofthe routerobject,andwepassthisobjecttotheVuerootinstance.
Here'sthecode:
<script>
importVuefrom'vue'
importVueRouterfrom'vue-router'
Vue.use(Router)
constHome={
template:'<div>Home</div>'
VueRouter
115
}
constLogin={
template:'<div>Login</div>'
}
constAbout={
template:'<div>About</div>'
}
constrouter=newVueRouter({
routes:[
{path:'/',component:Home},
{path:'/login',component:Login},
{path:'/about',component:About}
]
})
newVue({
router
}).$mount('#app')
</script>
Usually,inaVueappyouinstantiateandmounttherootappusing:
newVue({
render:h=>h(App)
}).$mount('#app')
WhenusingtheVueRouter,youdon'tpassa renderpropertybutinstead,youuse router.
Thesyntaxusedintheaboveexample:
newVue({
router
}).$mount('#app')
isashorthandfor
newVue({
router:router
}).$mount('#app')
Seeintheexample,wepassa routesarraytothe VueRouterconstructor.Eachrouteinthisarrayhasa pathand componentparams.
Ifyoupassa nameparamtoo,youhaveanamedroute.
VueRouter
116
UsingnamedroutestopassparameterstotherouterpushandreplacemethodsRememberhowweusedtheRouterobjecttopushanewstatebefore?
this.$router.push({path:'about'})
Withanamedroutewecanpassparameterstothenewroute:
this.$router.push({name:'post',params:{post_slug:'hello-world'}})
thesamegoesfor replace():
this.$router.replace({name:'post',params:{post_slug:'hello-world'}})
Whathappenswhenauserclicksa router-linkTheapplicationwillrendertheroutecomponentthatmatchestheURLpassedtothelink.
ThenewroutecomponentthathandlestheURLisinstantiatedanditsguardscalled,andtheoldroutecomponentwillbedestroyed.
RouteguardsSincewementionedguards,let'sintroducethem.
Youcanthinkofthemoflifecyclehooksormiddleware,thosearefunctionscalledatspecifictimesduringtheexecutionoftheapplication.Youcanjumpinandaltertheexecutionofaroute,redirectingorsimplycancelingtherequest.
Youcanhaveglobalguardsbyaddingacallbacktothe beforeEach()and afterEach()propertyoftherouter.
beforeEach()iscalledbeforethenavigationisconfirmedbeforeResolve()iscalledwhenbeforeEachisexecutedandallthecomponentsbeforeRouterEnterand beforeRouteUpdateguardsarecalled,butbeforethenavigationisconfirmed.Thefinalcheck,ifyouwantafterEach()iscalledafterthenavigationisconfirmed
VueRouter
117
Whatdoes"thenavigationisconfirmed"mean?We'llseeitinasecond.Inthemeantimethinkofitas"theappcangotothatroute".
Theusageis:
this.$router.beforeEach((to,from,next)=>{
//...
})
this.$router.afterEach((to,from)=>{
//...
})
toand fromrepresenttherouteobjectsthatwegotoandfrom. beforeEachhasanadditionalparameter nextwhichifwecallwith falseastheparameter,willblockthenavigation,andcauseittobeunconfirmed.LikeinNodemiddleware,ifyou'refamiliar,next()shouldalwaysbecalledotherwiseexecutionwillgetstuck.
Singleroutecomponentsalsohaveguards:
beforeRouteEnter(from,to,next)iscalledbeforethecurrentrouteisconfirmedbeforeRouteUpdate(from,to,next)iscalledwhentheroutechangesbutthecomponentthatmanagesitisstillthesame(withdynamicrouting,seenext)beforeRouteLeave(from,to,next)iscalledwhenwemoveawayfromhere
Wementionednavigation.Todetermineifthenavigationtoarouteisconfirmed,VueRouterperformssomechecks:
itcalls beforeRouteLeaveguardinthecurrentcomponent(s)itcallstherouter beforeEach()guarditcallsthe beforeRouteUpdate()inanycomponentthatneedstobereused,ifanyexistitcallsthe beforeEnter()guardontherouteobject(Ididn'tmentionitbutyoucanlookhere)itcallsthe beforeRouterEnter()inthecomponentthatweshouldenterintoitcallstherouter beforeResolve()guardifallwasfine,thenavigationisconfirmed!itcallstherouter afterEach()guard
Youcanusetheroute-specificguards( beforeRouteEnterand beforeRouteUpdateincaseofdynamicrouting)aslifecyclehooks,soyoucanstartdatafetchingrequestsforexample.
Dynamicrouting
VueRouter
118
TheexampleaboveshowsadifferentviewbasedontheURL,handlingthe /, /loginand/aboutroutes.
Averycommonneedistohandledynamicroutes,likehavingallpostsunder /post/,eachwiththeslugname:
/post/first
/post/another-post
/post/hello-world
Youcanachievethisusingadynamicsegment.
Thosewerestaticsegments:
constrouter=newVueRouter({
routes:[
{path:'/',component:Home},
{path:'/login',component:Login},
{path:'/about',component:About}
]
})
weaddinadynamicsegmenttohandleblogposts:
constrouter=newVueRouter({
routes:[
{path:'/',component:Home},
{path:'/post/:post_slug',component:Post},
{path:'/login',component:Login},
{path:'/about',component:About}
]
})
Noticethe :post_slugsyntax.Thismeansthatyoucanuseanystring,andthatwillbemappedtothe post_slugplaceholder.
You'renotlimitedtothiskindofsyntax.Vuereliesonthislibrarytoparsedynamicroutes,andyoucangowildwithRegularExpressions.
NowinsidethePostroutecomponentwecanreferencetherouteusing $route,andthepostslugusing $route.params.post_slug:
constPost={
template:'<div>Post:{{$route.params.post_slug}}</div>'
}
Wecanusethisparametertoloadthecontentsfromthebackend.
VueRouter
119
Youcanhaveasmanydynamicsegmentsasyouwant,inthesameURL:
/post/:author/:post_slug
Rememberwhenbeforewetalkedaboutwhathappenswhenausernavigatestoanewroute?
Inthecaseofdynamicroutes,whathappensisalittledifferent.
Vuetobemoreefficientinsteadofdestroyingthecurrentroutecomponentandre-instantiatingit,itreusesthecurrentinstance.
Whenthishappens,Vuecallsthe beforeRouteUpdatelifecycleevent.Thereyoucanperformanyoperationyouneed:
constPost={
template:'<div>Post:{{$route.params.post_slug}}</div>'
beforeRouteUpdate(to,from,next){
console.log(`Updatingslugfrom${from}to${to}`)
next()//makesureyoualwayscallnext()
}
}
UsingpropsIntheexamples,Iused $route.params.*toaccesstheroutedata.Acomponentshouldnotbesotightlycoupledwiththerouter,andinstead,wecanuseprops:
constPost={
props:['post_slug'],
template:'<div>Post:{{post_slug}}</div>'
}
constrouter=newVueRouter({
routes:[
{path:'/post/:post_slug',component:Post,props:true}
]
})
Noticethe props:truepassedtotherouteobjecttoenablethisfunctionality.
NestedroutesBeforeImentionedthatyoucanhaveasmanydynamicsegmentsasyouwant,inthesameURL,like:
VueRouter
120
/post/:author/:post_slug
So,saywehaveanAuthorcomponenttakingcareofthefirstdynamicsegment:
<template>
<divid="app">
<router-view></router-view>
</div>
</template>
<script>
importVuefrom'vue'
importVueRouterfrom'vue-router'
Vue.use(Router)
constAuthor={
template:'<div>Author:{{$route.params.author}}</div>'
}
constrouter=newVueRouter({
routes:[
{path:'/post/:author',component:Author}
]
})
newVue({
router
}).$mount('#app')
</script>
Wecaninsertasecond router-viewcomponentinstanceinsidetheAuthortemplate:
constAuthor={
template:'<div>Author:{{$route.params.author}}<router-view></router-view></div>'
}
weaddthePostcomponent:
constPost={
template:'<div>Post:{{$route.params.post_slug}}</div>'
}
andthenwe'llinjecttheinnerdynamicrouteintheVueRouterconfiguration:
constrouter=newVueRouter({
routes:[{
path:'/post/:author',
component:Author,
children:[
path:':post_slug',
VueRouter
121
component:Post
]
}]
})
VueRouter
122