vue学习笔记

1.设计模式

MVVM(Model-View-ViewModel)是一种软件设计模式,是一种简化用户界面的事件驱动编程方式

MVVM源自于经典的MVC(Model-View-Controller)模式。MVVM的核心是ViewModel层,负责转换Model中的数据对象来让数据变得更容易管理和使用。其作用如下:

  • 该层向上与视图层进行双向数据绑定
  • 向下与Model层通过接口请求进行数据交互
  • MVVM模式和MVC模式一样,主要目的是分离视图(View)和模型(Model) 

View是视图层, 也就是用户界面 

Model是指数据模型, 泛指后端进行的各种业务逻辑处理和数据操控, 主要围绕数据库系统展开。这里的难点主要在于需要和前端约定统一的接口规则.

ViewModel是由前端开发人员组织生成和维护的视图数据层。View Model所封装出来的数据模型包括视图的状态和行为两部分, 而Model层的数据模型是只包含状态的

实现了双向绑定, View Model的内容会实时展现在View层, 这是激动人心的, 因为前端开发者再也不必低效又麻烦地通过操纵DOM去更新视图。

Vue.js就是一个MV VM的实现者, 他的核心就是实现了DOM监听与数据绑定

2.vue

在idea中记得下载vue.js插件,这样新建的时候就有vue component选项

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

</head>
<body>

<!--view层,模板-->
<div id="app">
    {{message}}
</div>

<!--1.导入Vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script type="text/javascript">
    var vm = new Vue({
        el:"#app",
        /*Model:数据*/
        data:{
            message:"hello,vue!"
        }
    });
</script>
</body>
</html>

我们新建一个vue对象 var v = new Vue();然后在括号里面添加花括号就可以写东西了。 

el:"",是与标签进行双向绑定;data是对象,所以要用花括号包括起来,然后我们可以在里面放数据,这样前端也可以自己有数据,而不用去后端拿。

2.1基本语法

2.1.1 v-bind

绑定元素特性

<!--view层,模板-->
<div id="app">
    <span v-bind:title="message">
    鼠标悬停几秒钟查看此处动态绑定的提示信息!
  </span>
</div>

2.1.2 v-if v-else-if v-else

<div id="app">
  <h1 v-if="type==='a'">A</h1>
  <h1 v-else-if="type==='b'">B</h1>
  <h1 v-else>K</h1>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
  var vm = new Vue({
    el:"#app",
    data: {
     type: 'a'
    }
  });

2.1.3 v-for

注意{{item}},引用即用双花括号包围起来,其中item是数组的单一元素,而items则是数组。

<div id="app">
    <li v-for="(item,index) in items">
        {{item.message}}---{{index}}
    </li>

</div>

<!--1.导入Vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script type="text/javascript">
    var vm = new Vue({
        el:"#app",
        /*Model:数据*/
        data:{
            items:[
                {message:'狂神说Java'},
                {message:'狂神说前端'},
                {message:'狂神说运维'}
            ]
        }
    });

2.1.4 v-on

注意:this即表示这个对象,而且定义方法要用methods,然后用花括号括起来,之后就可以在里面写方法,即方法名:funtion(event){},记得在括号中加入响应事件event.

<div id="app">
    <button v-on:click="sayHi">点我</button>
</div>

<script src="../js/vue.js"></script>
<script type="text/javascript">
    var vm = new Vue({
        el:"#app",
        data:{
            message:'Hello World'
        },
        methods:{
            sayHi:function(event){
                //'this'在方法里面指向当前Vue实例
                alert(this.message);
            }
        }
    });

2.1.5 v-model

数据双向绑定, 即当数据发生变化的时候, 视图也就发生变化, 当视图发生变化的时候,数据也会跟着同步变化。

v-model会忽略所有表单元素的valuecheckedselected特性的初始值而总是将Vue实例的数据作为数据来源。

v-model="";这里面填的即为data中的某个属性,之后就会与其双向绑定,并且可以调用

input标签中的type="radio"是单选框

<div id="app">
  性别:
  <input type="radio" v-model="sex" value="男" > 男
  <input type="radio" v-model="sex" value="女">  女
  <br>
  你的性别是:{{sex}}
</div>


<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
  var vm = new Vue({
    el:"#app",
    data: {
      sex: ''
    }
  });
</script>

 复选框

input标签中checkbox这类型说明是选择框,id则是与下面的label相关联,当我们勾选的时候,他就会将value值放入v-model相关量的data数据中去。

<div id="app">
  多复选框:
  <input type="checkbox" id="oneman" value="Jack" v-model="checkedNames">
  &nbsp;&nbsp;
  <label for="oneman">Jack</label>
  <br>
  <span>选中的值:{{checkedNames}}</span>
</div>


<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
  var vm = new Vue({
    el:"#app",
    data:{
      checkedNames:[]
    }
  });
</script>

下拉框

<div id="app">  
下拉框:
    <select v-model="pan">
        <option value="" disabled>---请选择---</option>
        <option>A</option>
        <option>B</option>
        <option>C</option>
        <option>D</option>
    </select>
    <span>value:{{pan}}</span>
</div>

<script src="../js/vue.js"></script>
<script type="text/javascript">
    var vm = new Vue({
        el:"#app",
        data:{
            pan:"A"
        }
    });

3.组件

3.1定义

组件是可复用的Vue实例, 说白了就是一组可以重复使用的模板

组件一般也是写在script中,然后要先注册,类似于方法,前面是标签名,后面再花括号中添加template模板。

<body>
<div id="app">
  <pan></pan>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
  //先注册组件
  Vue.component("pan",{
    template:'<li>Hello</li>'
  });
  //实例话vue
  var vm = new Vue({
    el:"#app",
  });
</script>
</body>

3.2往组件中传参数

<div id="app">
  <pan v-for="item in items" v-bind:damage="item"></pan>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
  //先注册组件
  Vue.component("pan",{
    props:['damage'],
    template:'<li>{{damage}}</li>'
  });
  //实例话vue
  var vm = new Vue({
    el:"#app",
    data: {
      items: ["pig","dog","panda"]
    }
  });

组件没有办法直接从实例化vue中拿数据,故需要一个props:['']

v-for="item in items"这个是从data中获得数据,遍历Vue实例中定义的名为items的数组,并创建同等数量的组件

v-bind:damage="item" 这个中的damage实际是id,即是填在props:['']中的值

然后这个item是遍历出来的数据都与damage相关联,也可以理解为两者相等

将遍历的item项绑定到组件中props定义名为damage属性上

4.Axios异步通信

Axios可以用在浏览器端和Node JS的异步通信框架。

这里的data(),mounted()都是函数来着,而且在data函数中格式是一定的,即return{info{}}

mounted()中调用axios的get方法获取json文件中数据,再用then(response=>(this.info=response.data))

<body>

<div id="vue">
    <div> address: {{info.address.country}}</div>
    <a v-bind:href="info.links[2].url">跳转</a>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
    var v = new Vue({
        el: '#vue',
        data(){
            return {
                info: {
                    name: null,
                    address: {
                        country: null,
                        city: null,
                        street: null
                    },
                    url: null
                }
            }
        },
        mounted(){//钩子函数
            axios
                .get('../date.json')
                .then(response=>(this.info=response.data));
        }
    });
</script>
</body>

5.计算属性

可以理解为将不怎么变的值计算出来,最后赋值给属性,而且这是以内存的形式存储,相当于缓存的作用,这就给浏览器节约了很大的内存。

它就是一个能够将计算结果缓存起来的属性(将行为转化成了静态的属性)。

注意在computed中方法名在引用时不需要加入(),{{currentTime2}}

this.message是为了能够让currentTime2观察到数据变化而变化,这样我们在控制条刷新vm.message后就能看到时间戳的变化。


<div id="app">
  time: <p>{{currentTime1()}}</p>
  time2: <p>{{currentTime2}}</p>

</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
  var vm = new Vue({
    el:"#app",
    methods: {
      currentTime1: function (){
        return  Date.now();
      }
    },
    computed: {
      currentTime2: function (){
        this.message;
        return  Date.now();
      }
    },
    data: {
      message: "damage"
    }
  });

6.插槽Slot

先编写一个组件,template:' ',单引号里面用来存放整体框架,然后记得要在动态的地方添加为插槽并命名,注意在每个标签后加上\就可以正常编写。

v-bind:item = "item"可以缩写为 :item = "item",前面可以理解为绑定id,引号中的是从data中拿出数据

todo-title和todo-items组件分别被分发到了todo组件的todo-title和todo-items插槽中

<body>
<div id="app">
    <todo>
      <todo-title  slot="todo-title" :title="title"></todo-title>
      <todo-items v-for="item in items" slot="todo-items" v-bind:item="item"></todo-items>
    </todo>
</div>


<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
  Vue.component("todo",{
    template: '<div>\
                <slot name="todo-title"></slot>>\
                  <ul>\
                    <slot name="todo-items"></slot>>\
                  </ul>\
                </div>'
  });
  Vue.component('todo-title',{
    props:['title'],
    template:'<div>{{title}}</div>'
  });
  Vue.component("todo-items",{
      props: ['item'],
      template: '<li>{{item}}</li>'
  })

  var vm = new Vue({
    el:"#app",
    data: {
      title:"计算机语言",
      items: ["java","python","c++"]
    }
  });

</script>

7.自定义事件

在视图层中,一般通过vue的方法将组件还有实例化vue联系起来

①(v-bind:itme_p="item"),前面的item即与component中的props[‘’]相对应(props里的参数都得单引号),而后面的"item"既是从data获取。

②(v-on:remove="removeItems(index)"),remove是组件中自定义事件this.$emit("remove",index)

而removeItems(index)对应实例化的方法。

js中spice是对数组的操作,格式为spice(index,num,elm1,elm22)

index表从数组的哪个下标开始删除或增加,num表删除的个数,可以为0,elm1表增加的元素。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--view层,模板-->
<div id="vue">
    <todo>
        <todo-title slot="todo-title" :title="title_text"></todo-title>
        <!--<todo-items slot="todo-items" v-for="(item,index) in todoItems" v-bind:item="item"></todo-items>-->
        <!--如下为简写-->
        <todo-items slot="todo-items" v-for="(item,index) in todoItems"
                    :item_p="item" :index_p="index" v-on:remove="removeItems(index)" :key="index"></todo-items>
    </todo>
</div>
<!--1.导入Vue.js-->
<script src="../js/vue.js"></script>
<script type="text/javascript">
    Vue.component('todo',{
        template:'<div>\
                <slot name="todo-title"></slot>\
                <ul>\
                    <slot name="todo-items"></slot>\
                </ul>\
            </div>'
    });
    Vue.component('todo-title',{
        props:['title'],
        template:'<div>{{title}}</div>'
    });
    //这里的index,就是数组的下标,使用for循环遍历的时候,可以循环出来!
    Vue.component("todo-items",{
        props:["item_p","index_p"],
        template:"<li>{{index_p+1}},{{item_p}} <button @click='remove_methods'>删除</button></li>",
        methods:{
            remove_methods:function (index) {
                //this.$emit 自定义事件分发
                this.$emit('remove',index);
            }
        }
    });

    var vm = new Vue({
        el:"#vue",
        data:{
            title_text:"秦老师系列课程",
            todoItems:['test1','test2','test3']
        },
        methods:{
            removeItems:function(index){
                console.log("删除了"+this.todoItems[index]+"OK");
                this.todoItems.splice(index,1);
            }
        }
    });
</script>
</body>
</html>

8.入门小结

核心:数据驱动,组件化

优点:借鉴了AngularJS的模块化开发和React的虚拟Dom,虚拟Dom就是把Demo操作放到内存中执行;

常用的属性:

  • v-if
  • v-else-if
  • v-else
  • v-for
  • v-on绑定事件,简写@
  • v-model数据双向绑定
  • v-bind给组件绑定参数,简写:

组件化:

  • 组合组件slot插槽
  • 组件内部绑定事件需要使用到this.$emit("事件名",参数);
  • 计算属性的特色,缓存计算数据

遵循SoC关注度分离原则,Vue是纯粹的视图框架,并不包含,比如Ajax之类的通信功能,为了解决通信问题,我们需要使用Axios框架做异步通信;

9.第一个vue-li项目

9.1 nodejs安装

  • cmd下输入node -v,查看是否能够正确打印出版本号即可!
  • cmd下输入npm -v,查看是否能够正确打印出版本号即可!
    这个npm,就是一个软件包管理工具,就和linux下的apt软件安装差不多!

9.2镜像安装

  • 安装Node.js淘宝镜像加速器(cnpm),用于快速下载(管理员身份运行:cmd,ctrl+shitf+enter)
  • # -g 就是全局安装
    npm install cnpm -g

    # 或使用如下语句解决npm速度慢的问题
    npm install --registry=https://registry.npm.taobao.org

9.3安装vue-cli

  • cnpm instal1 vue-cli-g

  • #查看可以基于哪些模板创建vue应用程序,通常我们vue list

9.4基于webpack的vue程序

1.创建一个Vue项目,我们随便建立一个空的文件夹在电脑上,我这里在D盘下新建一个目录

D:\Project\vue-study;

2.创建一个基于webpack模板的vue应用程序

#1、首先需要进入到对应的目录 cd D:\Project\vue-study
#2、这里的myvue是顶日名称,可以根据自己的需求起名
vue init webpack myvue

3.初始化并运行

cd myvue
npm install
npm run dev

 9.5webpack安装

WebPack是一款模块加载器兼打包工具, 它能把各种资源, 如JS、JSX、ES 6、SASS、LESS、图片等都作为模块来处理和使用。
安装:

npm install webpack -g
npm install webpack-cli -g

测试安装成功

  • webpack -v
  • webpack-cli -v

10.webpack使用

  1. 创建空项目
  2. 创建一个名为modules的目录,用于放置JS模块等资源文件
  3. 在modules下创建模块文件,如hello.js,用于编写JS模块相关代码

注意exports.方法名 = function(){}

	//暴露一个方法:sayHi
	exports.sayHi = function(){
		document.write("<div>Hello Webpack</div>");
	}
  • 在modules下创建一个名为main.js的入口文件,用于打包时设置entry属性
//require 导入一个模块,就可以调用这个模块中的方法了
var hello = require("./hello");
hello.sayHi();
  • 在项目目录下创建webpack.config.js配置文件,在terminal中使用webpack命令打包

entry是项目入口文件,output是文件打包后的位置及命名

module.exports = {
	entry:"./modules/main.js",
	output:{
		filename:"./js/bundle.js"
	}

}
  • 在项目目录下创建HTML页面,如index.html,导入webpack打包后的JS文件
	<!doctype html>
	<html lang="en">
		<head>
			<meta charset="UTF-8">
			<title>狂神说Java</title>
		</head>
		<body>
			<script src="dist/js/bundle.js"></script>
		</body>
	</html>

 # 参数--watch 用于监听变化
webpack --watch,相当于热部署(即修改内容后会重新打包)

11.vue-router

11.1插入包

vue-router是一个插件包, 所以我们还是需要用npm/cn pm来进行安装的。

打开命令行工具,进入你的项目目录,输入下面命令。

npm install vue-router --save-dev

bug:在package.json中有对应的依赖版本号,我们需要通过修改与对应vue一致的版本。

如果在一个模块化工程中使用它,必须要通过Vue.use()来安装路由功能:

一般是在router目录下的index.js配置文件中来使用

import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter);

11.2目录结构

定义一个Content.vue 的组件

template中存放html,script中是导出组件信息

<template>
	<div>
		<h1>内容页</h1>
	</div>
</template>

<script>
	export default {
		name:"Content"
	}
</script>

      在src目录下,新建一个文件夹:router,专门存放路由,添加一个路由配置文件index.js,然后在里面引用路由,接着再配置路由地址还有对应的组件 。 

import Vue from'vue'
//导入路由插件
import Router from 'vue-router'
//导入上面定义的组件
import Content from '../components/Content'
import Main from '../components/Main'
//安装路由
Vue.use(Router) ;
//配置路由
export default new Router({
	routes:[
		{
			//路由路径
			path:'/content',
			//路由名称
			name:'content',
			//跳转到组件
			component:Content
			},{
			//路由路径
			path:'/main',
			//路由名称
			name:'main',
			//跳转到组件
			component:Main
			}
		]
	});

main.js(唯一入口)中配置路由

import Vue from 'vue'
import App from './App'

//导入上面创建的路由配置目录
import router from './router'//自动扫描里面的路由配置

//来关闭生产模式下给出的提示
Vue.config.productionTip = false;

new Vue({
	el:"#app",
	//配置路由
	router,
	components:{App},
	template:'<App/>'
});

6、在App.vue(主页面)中使用路由

<template>
	<div id="app">
		<!--
			router-link:默认会被渲染成一个<a>标签,to属性为指定链接
			router-view:用于渲染路由匹配到的组件
		-->
		<router-link to="/">首页</router-link>
		<router-link to="/content">内容</router-link>
		<router-view></router-view>
	</div>
</template>

<script>
	export default{
		name:'App'
	}
</script>
<style></style>

 12.实战上手

12.1环境准备

1、创建一个名为hello-vue的工程vue init webpack hello-vue
2、安装依赖, 我们需要安装vue-router(可在创建项目时勾选)、element-ui、sass-loader和node-sass四个插件

#进入工程目录
cd hello-vue
#安装vue-routern 
npm install vue-router --save-dev
#安装element-ui
npm i element-ui -S
#安装依赖
npm install
# 安装SASS加载器
cnpm install sass-loader node-sass --save-dev
#启功测试
npm run dev

把没有用的初始化东西删掉!
  在源码目录中创建如下结构:

  • assets:用于存放资源文件
  • components:用于存放Vue功能组件
  • views:用于存放Vue视图组件
  • router:用于存放vue-router配置

12.2代码实现

创建首页视图,在views目录下创建一个名为Main.vue的视图组件:

<template>
	<div>首页</div>
</template>
<script>
	export default {
			name:"Main"
	}
</script>
<style scoped>
</style>

创建登录页视图在views目录下创建名为Login.vue的视图组件,其中el-*的元素为ElementUI组件;

<template>
  <div>
    <el-form ref="loginForm" :model="form" :rules="rules" label-width="80px" class="login-box">
      <h3 class="login-title">欢迎登录</h3>
      <el-form-item label="账号" prop="username">
        <el-input type="text" placeholder="请输入账号" v-model="form.username"/>
      </el-form-item>
      <el-form-item label="密码" prop="password">
        <el-input type="password" placeholder="请输入密码" v-model="form.password"/>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" v-on:click="onsubmit('loginForm')">登录</el-button>
      </el-form-item>
    </el-form>

    <el-dialog title="温馨提示" :visible.sync="dialogVisible" width="30%" :before-close="handleClose">
      <span>请输入账号和密码</span>
      <span slot="footer" class="dialog-footer">
          <el-button type="primary" @click="dialogVisible = false">确定</el-button>
        </span>
    </el-dialog>
  </div>
</template>

<script>
    export default {
        name: "Login",
      data(){
          return{
            form:{
              username:'',
              password:''
            },
            //表单验证,需要在 el-form-item 元素中增加prop属性
            rules:{
              username:[
                {required:true,message:"账号不可为空",trigger:"blur"}
              ],
              password:[
                {required:true,message:"密码不可为空",tigger:"blur"}
              ]
            },

            //对话框显示和隐藏
            dialogVisible:false
          }
      },
      methods:{
          onSubmit(formName){
            //为表单绑定验证功能
            this.$refs[formName].validate((valid)=>{
              if(valid){
                //使用vue-router路由到指定界面,该方式称为编程式导航
                this.$router.push('/main');
              }else{
                this.dialogVisible=true;
                return false;
              }
            });
          }
      }
    }
</script>

<style lang="scss" scoped>
  .login-box{
    border:1px solid #DCDFE6;
    width: 350px;
    margin:180px auto;
    padding: 35px 35px 15px 35px;
    border-radius: 5px;
    -webkit-border-radius: 5px;
    -moz-border-radius: 5px;
    box-shadow: 0 0 25px #909399;
  }
  .login-title{
    text-align:center;
    margin: 0 auto 40px auto;
    color: #303133;
  }
</style>

创建路由,在router目录下创建一个名为index.js的vue-router路由配置文件

//导入vue
import Vue from 'vue';
import VueRouter from 'vue-router';
//导入组件
import Main from "../views/Main";
import Login from "../views/Login";
//使用
Vue.use(VueRouter);
//导出
export default new VueRouter({
  routes: [
    {
      //登录页
      path: '/main',
      component: Main
    },
    //首页
    {
      path: '/login',
      component: Login
    },
  ]

})

APP.vue

<template>
  <div id="app">
    <router-view></router-view>
  </div>
</template>

<script>


export default {
  name: 'App',

}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

main.js

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from "./router"

import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'

Vue.use(router)
Vue.use(ElementUI)

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  render:h=>h(App)
})

测试:在浏览器打开 http://localhost:8080/#/login
如果出现错误: 可能是因为sass-loader的版本过高导致的编译错误,当前最高版本是8.0.2,需要退回到7.3.1 ;
去package.json文件里面的 "sass-loader"的版本更换成7.3.1,然后重新cnpm install就可以了;

13.路由嵌套(child)

嵌套路由又称子路由,在实际应用中,通常由多层嵌套的组件组合而成。
demo
1、 创建用户信息组件,在 views/user 目录下创建一个名为 Profile.vue 的视图组件;
Profile.vue

<template>
  <h1>个人信息</h1>
</template>
<script>
  export default {
    name: "UserProfile"
  }
</script>
<style scoped>
</style>

2、在用户列表组件在 views/user 目录下创建一个名为 List.vue 的视图组件;
List.vue

<template>
  <h1>用户列表</h1>
</template>
<script>
  export default {
    name: "UserList"
  }
</script>
<style scoped>
</style>

3、 修改首页视图,我们修改 Main.vue 视图组件,此处使用了 ElementUI 布局容器组件,代码如下:
Main.vue

<template>
    <div>
      <el-container>
        <el-aside width="200px">
          <el-menu :default-openeds="['1']">
            <el-submenu index="1">
              <template slot="title"><i class="el-icon-caret-right"></i>用户管理</template>
              <el-menu-item-group>
                <el-menu-item index="1-1">
                <!--插入的地方-->
                  <router-link to="/user/profile">个人信息</router-link>
                </el-menu-item>
                <el-menu-item index="1-2">
                <!--插入的地方-->
                  <router-link to="/user/list">用户列表</router-link>
                </el-menu-item>
              </el-menu-item-group>
            </el-submenu>
            <el-submenu index="2">
              <template slot="title"><i class="el-icon-caret-right"></i>内容管理</template>
              <el-menu-item-group>
                <el-menu-item index="2-1">分类管理</el-menu-item>
                <el-menu-item index="2-2">内容列表</el-menu-item>
              </el-menu-item-group>
            </el-submenu>
          </el-menu>
        </el-aside>

        <el-container>
          <el-header style="text-align: right; font-size: 12px">
            <el-dropdown>
              <i class="el-icon-setting" style="margin-right: 15px"></i>
              <el-dropdown-menu slot="dropdown">
                <el-dropdown-item>个人信息</el-dropdown-item>
                <el-dropdown-item>退出登录</el-dropdown-item>
              </el-dropdown-menu>
            </el-dropdown>
          </el-header>
          <el-main>
          <!--在这里展示视图-->
            <router-view />
          </el-main>
        </el-container>
      </el-container>
    </div>
</template>
<script>
    export default {
        name: "Main"
    }
</script>
<style scoped lang="scss">
  .el-header {
    background-color: #B3C0D1;
    color: #333;
    line-height: 60px;
  }
  .el-aside {
    color: #333;
  }
</style>

4、 配置嵌套路由修改 router 目录下的 index.js 路由配置文件,使用children放入main中写入子模块,代码如下
index.js

//导入vue
import Vue from 'vue';
import VueRouter from 'vue-router';
//导入组件
import Main from "../views/Main";
import Login from "../views/Login";
//导入子模块
import UserList from "../views/user/List";
import UserProfile from "../views/user/Profile";

//使用
Vue.use(VueRouter);
//导出
export default new VueRouter({
  routes: [
    {
      //登录页
      path: '/main',
      component: Main,
      //  写入子模块
      children: [
        {
          path: '/user/profile',
          component: UserProfile,
        }, {
          path: '/user/list',
          component: UserList,
        },
      ]
    },
    //首页
    {
      path: '/login',
      component: Login

    },
  ]
})

 14.参数传递

第一种取值方式
1、 修改路由配置, 主要是router下的index.js中的 path 属性中增加了 :id 这样的占位符

{
	path: '/user/profile/:id', 
	name:'UserProfile', 
	component: UserProfile
}

2、传递参数
 此时我们在Main.vue中的route-link位置处 to 改为了 :to,是为了将这一属性当成对象使用,注意 router-link 中的 name 属性名称 一定要和 路由中的 name 属性名称 匹配,因为这样 Vue 才能找到对应的路由路径;

<!--name是组件的名字 params是传的参数 如果要传参数的话就需要用v:bind:来绑定-->
<router-link :to="{name:'UserProfile',params:{id:1}}">个人信息</router-link>
12

3、在要展示的组件Profile.vue中接收参数 使用 {{$route.params.id}}来接收
Profile.vue 部分代码

<template>
  <!--  所有的元素必须在根节点下-->
  <div>
    <h1>个人信息</h1>
    {{$route.params.id}}
  </div>
</template>

第二种取值方式 使用props 减少耦合
1、修改路由配置 , 主要在router下的index.js中的路由属性中增加了 props: true 属性

{
	path: '/user/profile/:id', 
	name:'UserProfile', 
	component: UserProfile, 
	props: true
}

2、传递参数和之前一样 在Main.vue中修改route-link地址

<!--name是组件的名字 params是传的参数 如果要传参数的话就需要用v:bind:来绑定-->
<router-link :to="{name:'UserProfile',params:{id:1}}">个人信息</router-link>

3、在Profile.vue接收参数为目标组件增加 props 属性
Profile.vue

<template>
  <div>
    个人信息
    {{ id }}
  </div>
</template>
<script>
    export default {
      props: ['id'],
      name: "UserProfile"
    }
</script>
<style scoped>
</style>

12.5、组件重定向

重定向的意思大家都明白,但 Vue 中的重定向是作用在路径不同但组件相同的情况下,比如:
在router下面index.js的配置

{
  path: '/main',
  name: 'Main',
  component: Main
},
{
  path: '/goHome',
  redirect: '/main'
}

说明:这里定义了两个路径,一个是 /main ,一个是 /goHome,其中 /goHome 重定向到了 /main 路径,由此可以看出重定向不需要定义组件;

使用的话,只需要在Main.vue设置对应路径即可;

<el-menu-item index="1-3">
    <router-link to="/goHome">回到首页</router-link>
</el-menu-item>

 15.路由模式与 404

路由模式有两种

修改路由配置,代码如下:

export default new Router({
  mode: 'history',
  routes: [
  ]
});

404 demo
1.创建一个NotFound.vue视图组件
NotFound.vue

<template>
    <div>
      <h1>404,你的页面走丢了</h1>
    </div>
</template>
<script>
    export default {
        name: "NotFound"
    }
</script>
<style scoped>
</style>

2.修改路由配置index.js

import NotFound from '../views/NotFound'
{
   path: '*',
   component: NotFound
}

3.效果图

路由钩子与异步请求

beforeRouteEnter:在进入路由前执行
beforeRouteLeave:在离开路由前执行

在Profile.vue中写

  export default {
    name: "UserProfile",
    beforeRouteEnter: (to, from, next) => {
      console.log("准备进入个人信息页");
      next();
    },
    beforeRouteLeave: (to, from, next) => {
      console.log("准备离开个人信息页");
      next();
    }
  }

参数说明:
to:路由将要跳转的路径信息
from:路径跳转前的路径信息
next:路由的控制参数
next() 跳入下一个页面
next(’/path’) 改变路由的跳转方向,使其跳到另一个路由
next(false) 返回原来的页面
next((vm)=>{}) 仅在 beforeRouteEnter 中可用,vm 是组件实例

在钩子函数中使用异步请求

1、安装 Axios

cnpm install --save vue-axios

2、main.js引用 Axios

import axios from 'axios'
import VueAxios from 'vue-axios'
Vue.use(VueAxios, axios)

3、准备数据 : 只有我们的 static 目录下的文件是可以被访问到的,所以我们就把静态文件放入该目录下。
数据和之前用的json数据一样 需要的去上述axios例子里

// 静态数据存放的位置
static/mock/data.json

4.在 beforeRouteEnter 中进行异步请求
Profile.vue

  export default {
    //第二种取值方式
    // props:['id'],
    name: "UserProfile",
    //钩子函数 过滤器
    beforeRouteEnter: (to, from, next) => {
      //加载数据
      console.log("进入路由之前")
      next(vm => {
        //进入路由之前执行getData方法
        vm.getData()
      });
    },
    beforeRouteLeave: (to, from, next) => {
      console.log("离开路由之前")
      next();
    },
    //axios
    methods: {
      getData: function () {
        this.axios({
          method: 'get',
          url: 'http://localhost:8080/static/mock/data.json'
        }).then(function (response) {
          console.log(response)
        })
      }
    }
  }

5.路由钩子和axios结合图

前端:在component下新建一个组件之后就得在router下导入        

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值