19.vue-cli学习2.x②

53 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 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)

    1. params:

    配置路由格式:/router/:id(在router/index.js 里面的路由中国 path 格式)

    传递方式:在path后面加对应的值

    传递后的形成的路径:/router/123

    1. 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组件封装:

链接:pan.baidu.com/s/1md5VeItD…

提取码:ar50

复制这段内容后打开百度网盘手机App,操作更方便哦

九. 路径别名:

3.x:

项目根目录创建vue.config.js:

chainWebpack:

const path = require("path");

function resolve(dir) {

  return path.join(__dirname, dir);

}

module.exports = {

  chainWebpackconfig => {

    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'