VUE Development
Rapid prototyping
have access to vue serve and vue build Command to single .vue File for rapid prototyping . But it needs to be installed first @vue/cli-service-global
plug-in unit .
npm install -g @vue/cli-service-global
Copy code
Create a new one .vue file , Then start a service and run the prototype :
vue serve file name .vue
Copy code
Scaffolding creation project
vue create
vue create my-vue
Copy code
choice Default ([Vue 2] babel, eslint)
That's all right. .
If you want to configure it yourself , Then you can choose the third one :
Default or select the default configuration babel、linter, Others choose according to their own needs .
enter next step :(2.x Version and 3.x Version selection )
enter Next step into EsLint To configure :( Very strict or just prompt in the command line , It is recommended to choose the first one by default )
enter next step :( Do it when you save it Lint When it's submitted )
enter next step :( Configuration file selection )
And then execute :
cd Project name
yarn serve
Then open it in the browser http://192.168.8.132:8080/
You can see the welcome screen .
Project document description :
vue ui
Graphical project management :
vue ui
Copy code
Installing a plug-in
Vue CLI Using a plug-in based architecture . The plug-in can be modified webpack Internal configuration , Also you can ask the vue-cli- service Injection order . In the process of project creation , Most of the features listed are implemented through plug-ins .
Install a plug-in in a project that has been created , have access to vue add command . For example, install the routing plug-in :
vue add router
Copy code
( Then you will be prompted to change the code )
Input y continue :
And then you type in y, Plug in added successfully .
( Add the plug-in , There may be disruptive structural changes to the project , Even the modification of the file content . For example, view main.js and App.vue. So it's better to back up the version before installation .)
Processing resource paths
When you are in JavaScript、CSS or *.vue Use relative paths in files ( Must be . start ) When referring to a static resource , The resource will be webpack Handle .
Conversion rules :
-
If URL It's an absolute path ( for example /images/foo.png ), It will remain unchanged .
<img alt="logo" src="/assets/pyy.png"> // Will be in public Look in the folder , The name will not be changed :webpack It won't be right public Do anything <img alt="pyy" src="https://www.baidu.com/xxx/pyy.png"> // Address access in the picture server Copy code
-
If URL With . The beginning will be interpreted as a relative module request and based on the file system relative path .
// Will be webpack compile ( Open the inspector to see the picture src, We can see that the result of the final compilation is the file hash) // About pictures webpack Operation done : Images are processed in batches , Use it as a resource 、 Module to do the processing , If it's small enough , Will turn it into url route , Do string encoding . If it's big enough , Will have a proper name , Put it in the right place . <img alt="logo" src="./assets/pyy.png"> Copy code
-
If URL With @ The beginning will be parsed as a module request .Vue CLI By default, a point to src Another name for @ .
<img alt="logo" src="@/assets/pyy.png"> // @ representative src root directory Copy code
-
Expand : If URL With ~ The beginning will be parsed as a module request . This means that you can even quote Node Resources in the module (node_modules Medium )
<img src="~xxx-npm-package/pyy.png"> Copy code
So when to use public Folder ?
adopt webpack And get the following benefits :
-
Scripts and stylesheets are compressed and packaged together , To avoid additional network requests .
-
If the file is lost, an error will be reported directly during compilation , It's not generated on the client side 404 error .
-
The resulting file name contains the content hash , So don't worry about browsers caching their old versions .
Use public Scene :
-
You need to specify a fixed file name in the build output .
-
There are so many pictures , You need to dynamically reference their paths .
-
Compatibility needs to be considered , Use script Tags introduced .
Be careful :
If the application is packaged and uploaded to the server , Not deployed at the root of the domain name , Then configuration is required publicPath Prefix :
On the outermost layer of the project , Add a vue.config.js file , Add the following code to the file :
module.exports = {
// Judge the current running environment Production environment or development environment
// Add... To the production environment / The folder name in the deployment server /, You don't add
publicPath: process.env.NODE_ENV === 'production'? '/ The folder name in the deployment server /': '/'
}
Copy code
The preprocessor
If you don't select the preprocessor you need when you create the project (Sass/Less/Stylus), You need to manually install the corresponding loader.
# Sass
yarn add sass-loader node-sass
# Less
yarn add less-loader less
# Stylus
yarn add stylus-loader stylus
Copy code
The installation is complete , You can use it .
<style scoped lang='scss'>
$color: green;
h1 {
color: $color;
}
</style>
Copy code
Be careful : When <style>
The label has scoped Attribute , its CSS Only the elements in the current component , The principle is through the use of PostCSS To implement the transformation .
<template>
// Add custom attributes to tags data-v-f3edg9
<div class="green" data-v-f3edg9>hi</div>
</template>
<style>
// Tag added custom properties and postcss Corresponding
.green[data-v-f3edg9] {
color: green;
}
</style>
Copy code
Expand 1:
If we need to use many components scss Variable , So what to do , At this time, we can put forward the public opinion . Like the one above us $color: green Variables are put forward to .
stay src So let's make a new one styles Folder , And then add a common.scss file , hold $color: green Cut into this file .
Then install style-resources-loader
plug-in unit .
yarn add style-resources-loader
Copy code
And then in vue.config.js In file , Change the code to :
const path = require('path')
function addStyleResource(rule) {
rule.use('style-resource')
.loader('style-resources-loader')
.options({
patterns: [
path.resolve(__dirname, './src/styles/common.scss'),
],
})
}
module.exports = {
publicPath: process.env.NODE_ENV === 'production'? '/ The folder name in the deployment server /': '/',
chainWebpack: config => {
const types = ['vue-modules', 'vue', 'normal-modules', 'normal']
types.forEach(type => addStyleResource(config.module.rule('scss').oneOf(type)))
},
}
Copy code
And then restart the project .
At the beginning of the program , Load this file first , Then all the other files can be used .
Expand 2:
Depth action selector : >>>
In Africa css In the preprocessor , Use >>> Operators can make scoped A selector in the pattern works “ deeper ”, For example, influence
Child components ( It must be written in scoped In the style ).
<style scoped>
#app >>> p {
color: green
}
</style>
Copy code
stay css The preprocessor cannot parse properly >>> . We use /deep/ or ::v-deep The operator .
<style scoped lang="scss">
#app {
// /deep/ p{
// color: green;
// }
::v-deep p{
color: green;
}
}
</style>
Copy code
route
install
If you didn't choose to create a project before router, Then you need to install the routing plug-in .
vue add router
Copy code
Based on using
stay router/index.js, Routing can be configured .
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
// Use webpack+vue Provide asynchronous components to achieve lazy loading
// In the future, the code will be split into a separate chunk( The pattern of fragmentation )
// Only access to this route , To download this component in real time , Because it's packed separately , This will shorten the loading time
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
}
]
Copy code
Route exit
Generally in App.vue in , Use the total exit of the route : <router-view></router-view>
<template>
<div id="app">
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</div>
<!-- The exit of the route -->
<router-view/>
</div>
</template>
Copy code
Dynamic routing matching
We often need to match a pattern to all the routes , All mapped to the same component . for example , We have a Detail Components , For all ID Different products , Use this component to render . that , We can do it in vue-router Used in the routing path of “ Dynamic path parameters ”(dynamic segment) To achieve this effect :
{ path: '/detail/:id', component: Detail }
Copy code
// router/index.js Add :
{
// :id Mark dynamic routing
path: '/detail/:id',
name: 'Detail',
component: () => import('../views/Detail.vue')
},
Copy code
Route navigation
grammar :<router-link :to='' />
Use router-link Route navigation is available ,to It's about navigating to where , It says routing path.
Use :
<li v-for="item of goodsList" :key='item.id'>
<router-link :to='`/detail/${item.id}`'>
{{item.name}} - {{item.price | symbol("$")}}
</router-link>
</li>
Copy code
obtain :
<template>
<div>
<h1> Product details page </h1>
<p>{{$route.params.id}}</p>
</div>
</template>
<script>
export default {
// Respond to changes in routing parameters
// If you don't listen like this , So when switching between multiple , Components for performance , There will be no destruction or reconstruction , That is to say, below mounted perhaps created No more triggers
watch: {
$route: {
immediate: true,
// deep: true,
handler() {
console.log(' adopt id To get the details ');
}
}
},
mounted () {
console.log(this.$route.params.id);
},
created () {
console.log(' Initiate request ');
},
}
</script>
Copy code
wildcard
{
// Will match all paths
// Match from top to bottom , When nothing else matches , It means the route is wrong , At this time, we can load what we write 404 Prompt page
// In general , Will be put to the end
path: '*',
component: () => import('../views/404.vue')
}
Copy code
Nested Route
The actual application interface , It is usually composed of multiple nested components . similarly ,URL The dynamic path of each segment in also corresponds to the nested components of each layer according to a certain structure .
Add... To the routing object children attribute , Value is an array object .
{
path: '/about',
name: 'About',
component: () => import('../views/About.vue'),
children: [
{
path: 'detail/:id',
name: 'Detail',
component: () => import('../views/Detail.vue')
}
]
},
Copy code
reform about Page add nested route exit :
<template>
<div class="about">
<h1>about</h1>
<ul>
<li v-for="item of goodsList" :key='item.id'>
<router-link :to='`/about/detail/${item.id}`'>
{{item.name}} - {{item.price | symbol("$")}}
</router-link>
</li>
</ul>
<!-- Nested route exit -->
<router-view></router-view>
</div>
</template>
Copy code
This is the time ,(1) visit /detail/:id, It's a separate detail page ,(2)/about It's a list of products ,(3)/about/detail/:id It's the product list, and the product details .
Routing jump
grammar :router.push(location, onComplete?, onAbort?)
// character string
router.push('/')
// object
router.push({ path: `/about/detail/${item.id}` })
// Named route
router.push({
name: 'Detail', // In the routing file , To match We wrote name value
params: { id: item.id } // Parameters
})
// With query parameters , It will eventually become /goods?price=100
router.push({ path: 'goods', query: { price: 100 }})
Copy code
Road load by lazy
Lazy loading of routing components can divide components corresponding to different routes into different code blocks , Then the corresponding component is loaded when the route is accessed , It's more efficient .
Block components by component :
() => import(/* webpackChunkName: "group-about" */ "../views/About.vue")
Copy code
Advanced routing
Route guard
vue-router The navigation guard provided is mainly used to guard the navigation by jumping or canceling . There are many opportunities to be embedded in the routing navigation process : Overall , Single route exclusive , Or component level .
Global guard
router.beforeEach((to, from, next) => {
xxx Code
// to: Route: The goal to enter Routing objects
// from: Route: The route that the current navigation is about to leave
// next: Function: Be sure to call this method resolve This hook .
})
Copy code
stay router/index.js in , add to
// Global guard
// to: Where to go from: Where to come from next: release
router.beforeEach((to, from, next) => {
// Judge whether the route needs to be guarded
// meta data
if (to.meta.auth) {
// Log in
if (window.isLogin) { // If you save a variable globally isLogin, To determine whether to log in or not
next() // release
} else {
next('/login?redirect='+to.fullPath) // Jump to landing , Then log in successfully and redirect to the page you want to go to
}
} else {
next()
}
})
Copy code
Route exclusive guard
And the global guard beforeEach The parameters are consistent .
beforeEnter((to, from, next) => {
xxx Code
// to: Route: The goal to enter Routing objects
// from: Route: The route that the current navigation is about to leave
// next: Function: Be sure to call this method resolve This hook .
})
Copy code
for example :
{
path: '/about',
name: 'About',
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue'),
children: [
{
path: 'detail/:id',
name: 'Detail',
component: () => import('../views/Detail.vue')
}
],
beforeEnter(to, from, next) {
// Log in
if (window.isLogin) { // If you save a variable globally isLogin, To determine whether to log in or not
next() // release
} else {
next('/login?redirect=' + to.fullPath) // Jump to landing , Then log in successfully and redirect to where you want to go page
}
}
},
Copy code
Guard inside the assembly
You can directly define the following routing navigation guards in the routing component ( Methods written in components ):
-
beforeRouteEnter
-
beforeRouteUpdate
-
beforeRouteLeave
// About.vue
beforeRouteEnter(to, from, next) {
if (window.isLogin) {
next();
} else {
next("/login?redirect=" + to.fullPath);
}
}
Copy code
Dynamic routing
adopt router.addRoutes(routes) Way to dynamically add routes
For example, it is very common to require users to log in , Otherwise, you have to go to the login page .
Change the global guard to :
router.beforeEach((to, from, next) => {
// Logged in
if (window.isLogin) {
if (to.path === '/login') {
// There is no need to go to the login page , Redirect to home page
next('/')
} else {
// Go to other pages
next()
}
} else {
// No sign in
if (to.path === '/login') {
// If you want to go to the landing page, just let it go
next()
} else {
// Otherwise, redirect to the login page
next('/login?redirect=' + to.fullPath)
}
}
})
Copy code
modify Login.vue, When the user logs in successfully, dynamically add /about
login() {
window.isLogin = true;
// Note that the parameters need to be array objects , If you are not logged in , Then there won't be this route
this.$router.addRoutes([{
path: "/about",
name: "About",
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
// Use webpack+vue Provide asynchronous components to achieve lazy loading
// In the future, the code will be split into a separate chunk( The pattern of fragmentation )
// Only access to this route , To download this component in real time , Because it's packed separately , This will shorten the loading time
component: () =>
import(/* webpackChunkName: "about" */ "../views/About.vue"),
children: [
{
path: "detail/:id",
name: "Detail",
component: () => import("../views/Detail.vue")
}
],
beforeEnter(to, from, next) {
// Log in
if (window.isLogin) {
// If you save a variable globally isLogin, To determine whether to log in or not
next(); // release
} else {
next("/login?redirect=" + to.fullPath); // Jump to landing , Then log in successfully and redirect to where you want to go page
}
}
}]);
// Using parameters with query , So it's getting query
this.$router.push(this.$route.query.redirect);
}
Copy code
then , Think about it , Although the authority authentication has been done , But there's a problem , When I refresh , The added route is gone , We have to go through the login process , This must be unreasonable , So how to solve it ? Try it on your own .
Component cache
keep-alive
utilize keepalive Do component caching , Keep component state , Improve execution efficiency .
for example : cache about Components .
stay App.vue in , Modified code :
<!-- Cache components -->
<keep-alive include="about" max='5'>
<!-- Pay attention to include Or exclude when , To match is in the component name value , Not in routing name -->
<!-- include Is the component to cache ,exclude Is a component that is not cached , If more than one ,name Values are separated by commas , for example include="about,detail" -->
<!-- attribute max, Is the maximum number that needs to be cached , If it goes beyond , Will cache the oldest t get out , Add the latest cache , To optimize resources -->
<router-view/>
</keep-alive>
Copy code
because keep-alive Appearance , There are two special hooks :activated、deactivated.
stay about Component to monitor :
// By keep-alive The cache triggers
activated(){
console.log('activated');
},
deactivated(){
console.log('deactivated');
},
Copy code