持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第19天,点击查看活动详情
一.3.x和2.x的区别:
3.x是基于webpack4,2.x是基于webpack3
3.x 0配置,移除了build和config等目录,将配置文件隐藏了
3.x 提供了 vue ui 命令,提供了可视化的配置
移除了static文件夹,新增了 public 文件夹 并将 index.html 移入了改文件夹。
二. 怎样修改已经被隐藏的配置:
执行命令 vue ui 什么地方执行都可以,它是开启一个本地服务器,不是针对某一个项目的。
node_modules/@vue/cli-service 里面存在配置
在项目根目录 创建 vue.config.js:(添加自己的配置)
module.exports = {
}
vue.config.js实现路径别名配置:
const path = require("path"); function resolve(dir) { return path.join(__dirname, dir); } module.exports = { chainWebpack: config => { config.resolve.alias .set("@", resolve("src")) .set("assets", resolve("src/assets")) .set("components", resolve("src/components")) .set("views", resolve("src/views")) }, }
三. 单页面富应用:
SPA页面:
最大的特点是在前后端分离的基础上加上了前端路由,来维护了一套映射关系。
整个网页只有一个html页面。
前端路由:通过js实现显示不同的组件。(前端通过url来与页面实现映射关系)
前端的阶段:后端渲染 --> 前后端分离 --> SPA页面(前端路由)
前端路由的核心:
一但url 发生改变,前端立马从公共总js里面抽离出一部分代码去渲染,
整个页面是不用刷新的。(不会在重新请求服务器资源)
###四. 改变url页面不刷新:
-
1.hash:
location.hash='aaa' :
变化:http://localhost:8080/#/ ------> http://localhost:8080/#/aaa
-
2.history:
history.pushState( {} ,'title' , url ) (是一种栈结构,会存在记录,后进先出)
history.replaceState( {} ,'title' , url ) (不会放入栈里面,没有存在记录。)
五. vue-router(适合用于构建单页面应用)
安装:
npm install vue-router --save
使用:
-
1.导入路由对象,调用Vue.use(VueRouter)
-
2.创建路由实例,传入路由映射对象
-
3.Vue实例里面挂载创建的路由对象(组件)
router-link:
属性:
-
1.to: 跳转的地址
-
2.tag:将跳转按钮渲染成 设置的 标签。(tag='button')
-
3.replace: 按钮的点击会存在历史,无法返回(
<router-link to='/about' tag='button' replace>关于</router-link>) -
4.active-class:选中属性 (active-class='active')
在 router/index.js里面更改:
mode:'history',这个可以去除默认的#
linkActiveClass: '',//是模糊匹配点击的是哪个路由
linkExactActiveClass: 'active',//是精准匹配点击的是哪个路由
router-view:
决定 router-link 改变路径对应组件的位置
- js实现路由跳转:
this.$router.push:跳转到指定url路径,并想history栈中添加一个记录,点击后退会返回到上一个页面
this.$router.replace:跳转到指定url路径,但是history栈中不会有记录,点击返回会跳转到上上个页面
this.$router.go(n):向前或者向后跳转n个页面,n可为正整数或负整数
this.$router.push('/user/edit?id='+id+'&index='+index)
this.$router.push({path:'/user/add'})
-
页面传值:(params和 query)
- params:
配置路由格式:/router/:id(在router/index.js 里面的路由中国 path 格式)
传递方式:在path后面加对应的值
传递后的形成的路径:/router/123
- query:
router-link: :to="{path:'/user',query:{name:'1'}}"
传递后的形成的路径:/user?name="1"
在js中实现跳转,传值的方式就是将url拼接成 对应格式的 url
获取传值:
params:
```javascript
{
path: '/about:id', component: About
}
<router-link to="'/about'+userId" tag='button' replace>关于</router-link>
created(){
console.log(this.$route.params.id)
},
```
query:
```javascript
{
path: '/about', component: About
}
<router-link to="{path:'/about',query:{id:'1'}}" tag='button' replace>关于</router-link>
created(){
console.log(this.$route.query.id)
},
```
打包文件解析:
-
dist/static/js
-
app.xxx.js: 所有业务代码的js
-
mainfest.xxx.js : 打包做底层支持的js
-
vendor.xxx.js: 所有第三方的 js
懒加载使用:(用到时再加载)
因为会把业务层的所有代码打包到一个js文件(app.xxx.js), 文件很大,一次性请求下来就会出现页面空白.
把不同的路由对应的组件分割成不同的代码块,当路由访问时再加载组件,提高效率.
import HelloWorld from '@/components/HelloWorld' 引入后直接使用,不是懒加载
const HelloWorld = ()=>import('@/components/HelloWorld) 懒加载引入
实现:
const routes=[
{
path: '/',
redirect:'home'
},{
path:'/home',
component:HelloWorld (引入后直接使用,不是懒加载)
},{
path:'/about',
component: ()=>import('@/components/About')(使用时才引入实现懒加载,ES6写法)
// component: (resolve)=>require(['@/components/About'],resolve),//(AMD 写法)
// component: (resolve)=>{require.ensure(['@/components/About'],()=>{resolve(require('@/components/About'))})},
//(Vue异步组件和webpack一起)
}
]
在路由中component 使用时才引入,可以实现懒加载.
打包时会将懒加载文件的业务的js分开
-
路由嵌套:
home页面:
<router-link to='/home/user'>用户</router-link> <router-link to='/home/other'>其他</router-link> <router-view></router-view> router/index.js配置理由: const routes=[ { path: '/', redirect:'home' },{ path:'/home', component: ()=>import('@/components/HelloWorld'), children:[ { path:'/', redirect:'user' }, { path:'user', component: ()=>import('@/components/home/user'), }, { path:'other', component: ()=>import('@/components/home/other'), } ] } ]
六. vue-route导航守卫(监听页面来回跳转,并执行事件)
点击某个页面更新页面 title 和 动态修改keywords和description:
router/index.js 路由配置meta
{
path: '/about', component: ()=>import('@/components/About') , meta: { title:'关于' }
}
router.beforeEach 方法监听全局导航修改。
路由:
const routes=[
{
path: '/about', component: ()=>import('@/components/About') ,
meta: {
title:'关于' ,
content:{
keywords:'关于先农氏,智能碾米机,先农氏智能无人碾米机',
description:'关于先农氏智能无人碾米机,中国首台智能无人碾米机,专利产品。拥有先进核心技术,更智能、碾米速度更快,诚招加盟合作,政策多样。'
}
}
]
定义Router实例:
import VerRouter from 'vue-router'
Vue.use(VerRouter)
const router=new VerRouter({
// 配置路由和组件之间的映射关系:routes
mode:'history',
routes
})
export default router
// 使用Router实例里面的方法:
router.beforeEach((to, from, next) => {
console.log(to);
document.title=to.matched[0].meta.title
/*********动态修改keywords和description*************/
if(Object.keys(to.meta).length>0 && to.matched.length>0){
let this_meta=to.matched[to.matched.length-1].meta
let head = document.getElementsByTagName('head');
let meta_keyword=document.createElement('meta');
if(document.querySelector('meta[name="keywords"]')){
document.querySelector('meta[name="keywords"]').setAttribute('content',this_meta.content.keywords)
}else{
meta_keyword.setAttribute('name','keywords')
meta_keyword.setAttribute('content',this_meta.content.keywords)
head[0].appendChild(meta_keyword)
}
let meta_description=document.createElement('meta');
if(document.querySelector('meta[name="description"]')){
document.querySelector('meta[name="description"]').setAttribute('content',this_meta.content.description)
}else{
meta_description.setAttribute('name','description')
meta_description.setAttribute('content',this_meta.content.description)
head[0].appendChild(meta_description)
}
}
/**********************************************/
next();
});
(或) 在app.vue的created中加入下面代码,然后进行判断
this.$router.beforeEach((to, from, next) => {
console.log(to);
document.title=to.matched[0].meta.title
next();
});
vue 监听路由变化:
watch:{
$route:{
handler(val,oldval){
console.log(val);//新路由信息
console.log(oldval);//老路由信息
},
// 深度观察监听
deep: true
}
}
解释:
beforeEach:前置钩子 (跳转前回调)
afterEach :后置钩子 (跳转后回调)
全局守卫:
const router=new VerRouter({})
router.beforeEach
路由独享守卫:
在路由配置里面使用beforeEach等方法
const routes=[
{
path: '/about', component: ()=>import('@/components/About') ,
beforeEach:(to,from,next)=>{
}
]
组件内守卫:(created(){}方法一级)
beforeRouterEnter(to,from,next){}:在渲染组件对应路由时,(组件实例还没有创建没有this)
beforeRouterUpdate(to,from,next){}:路由被改变,但该组件被复用
beforeRouterLeave(to,from,next){}:导航离开该组件路由
七. vue-router-keep-alive:(保留组件内部的状态,切换导航时,将上一个组件的内容保留,实现不用再次刷新)
将router-view放入keep-alive 切换的组件就不会销毁重新加载,提高效率,不容再次请求数据:
<keep-alive><router-view/></keep-alive>
组件内子组件切换保存:(记住二级导航的选中路由)
data () {
return {
path:"/home/user",(初始进入父组件应该显示的子组件路由)
}
},
created () {
console.log(this.$route.params)
},
activated () {
this.$router.push(this.path)(父组件被选中时,进行跳转到指定的路由)
},
beforeRouteLeave(to, from, next){(导航离开该组件路由)
console.log(this.$route.path)(父组件离开时,离开页面的路由)
this.path=this.$route.path(记录离开时的路由)
next();
}
keep-alive属性:
include:只有匹配的组件才会被缓存
exclude:匹配的组件会排除,不需要缓存----->某些组件不需要缓存,每次都重新加载,
exclude=‘组件的名字,组件的名字’( export default { name:'About' } )
<keep-alive exclude="About"> <router-view/></keep-alive>
八. tabbar组件封装:
提取码:ar50
复制这段内容后打开百度网盘手机App,操作更方便哦
九. 路径别名:
3.x:
项目根目录创建vue.config.js:
chainWebpack:
const path = require("path");
function resolve(dir) {
return path.join(__dirname, dir);
}
module.exports = {
chainWebpack: config => {
config.resolve.alias
.set("@", resolve("src"))
.set("assets", resolve("src/assets"))
.set("components", resolve("src/components"))
.set("views", resolve("src/views"))
},
}
configureWebpack:
const webpack = require('webpack');
const path=require('path')
module.exports = {
configureWebpack:{
resolve: {
alias: {
'assets': path.resolve('src/assets'),
}
},
}
}
2.x:
webpack.config.js:
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'@': resolve('src'),
'assets': resolve('src/assets'),
}
},
<img class="yong" slot="item-icon-active" src="~assets/img/tabbar/yong.png">
在html 里面使用时 需要 加上 ‘~’符号哦那个
js中使用 import TabBar from '@/components/tabbar/TabBar'
他们都是绝对路径
十. 引入normalize.css 解决 input等在浏览器的兼容性:
方式:
www.githup.com : 搜索:normalize
npm install --save normalize.css
使用:
mian.js:
import 'normalize.css/normalize.css'
或者直接下载normalize.css文件拷贝到你的css目录下,并在你的css文件最前面引入:
@import 'normalize.css'