vue学习

Vue

一、Vue核心

数据驱动,组件化

Soc(关注点分离原则)

HTML+CSS+JS -> 视图层:给用户看,刷新后台给的数据

网络通信:axios

页面跳转:vue-router

状态管理:vuex

Vue-UI:ICE

1.1、什么是MVVM

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

  • 该层向上与视图层进行双向数据绑定
  • 向下与Model层通过接口请求进行数据交互
    在这里插入图片描述

1.2、为什么要用MVVM

MVVM模式和MVC模式一样,主要目的是分离视图(View)和模型(Model),有几大好处

  • 低耦合:视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的View上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
  • 可复用:可以把一些视图逻辑放在一个ViewModel里面,让很多View重用这段视图逻辑。
  • 独立开发:开发人员可以专注于业务逻辑和数据的开发(ViewMode),设计人员可以专注于页面设计。
  • 可测试:界面素来是比较难以测试的,而现在测试可以针对ViewModel来写。
    在这里插入图片描述

(1)View

View是视图层, 也就是用户界面。前端主要由HTH L和csS来构建, 为了更方便地展现vi eu to del或者Hodel层的数据, 已经产生了各种各样的前后端模板语言, 比如FreeMarker,Thyme leaf等等, 各大MV VM框架如Vue.js.Angular JS, EJS等也都有自己用来构建用户界面的内置模板语言。

(2)Model

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

(3)ViewModel

ViewModel是由前端开发人员组织生成和维护的视图数据层。在这一层, 前端开发者对从后端获取的Model数据进行转换处理, 做二次封装, 以生成符合View层使用预期的视图数据模型。

需要注意的是View Model所封装出来的数据模型包括视图的状态和行为两部分, 而Model层的数据模型是只包含状态的

  • 比如页面的这一块展示什么,那一块展示什么这些都属于视图状态(展示)

  • 页面加载进来时发生什么,点击这一块发生什么,这一块滚动时发生什么这些都属于视图行为(交互)

视图状态和行为都封装在了View Model里。这样的封装使得View Model可以完整地去描述View层。由于实现了双向绑定, View Model的内容会实时展现在View层, 这是激动人心的, 因为前端开发者再也不必低效又麻烦地通过操纵DOM去更新视图。

MVVM框架已经把最脏最累的一块做好了, 我们开发者只需要处理和维护View Model, 更新数据视图就会自动得到相应更新,真正实现事件驱动编程。

View层展现的不是Model层的数据, 而是ViewModel的数据, 由ViewModel负责与Model层交互, 这就完全解耦了View层和Model层, 这个解耦是至关重要的, 它是前后端分离方案实施的重要一环

1.3、Vue

1)MVVM模式的实现者

  • Model:模型层, 在这里表示JavaScript对象

  • View:视图层, 在这里表示DOM(HTML操作的元素)

  • ViewModel:连接视图和数据的中间件, Vue.js就是MVVM中的View Model层的实现者

  • 在MVVM架构中, 是不允许数据和视图直接通信的, 只能通过ViewModel来通信, 而View Model就是定义了一个Observer观察者

  • ViewModel能够观察到数据的变化, 并对视图对应的内容进行更新

  • ViewModel能够监听到视图的变化, 并能够通知数据发生改变

  • 至此, 我们可以大致了解, Vue.js就是一个MV VM的实现者, 他的核心就是实现了DOM监听与数据绑定

2)为什么使用Vue.js

  • 轻量级, 体积小是一个重要指标。Vue.js压缩后有只有20多kb(Angular压缩后56kb+,React压缩后44kb+)
  • 移动优先。更适合移动端, 比如移动端的Touch事件
  • 易上手,学习曲线平稳,文档齐全
  • 吸取了Angular(模块化) 和React(虚拟DOM) 的长处, 并拥有自己独特的功能,如:计算属性
  • 开源,社区活跃度高

二、Vue语法

<!-- 1.导入vue.js   -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
    var vm = new Vue({
        el:"#app",  //通过element元素绑定id为app的模块
        //Model:数据
        data:{
           message: ""
        }
    });
</script>

以v-开头,位于便签中

2.1、判断-循环

v-if
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--View层 模版Template-->
<div id="app">
    <h1 v-if="ok">Yes</h1>
    <h1 v-else>No</h1>
</div>


<!-- 导入vue.js   -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
    var vm = new Vue({
        el:"#app",  //通过element元素绑定id为app的模块
        //Model:数据
        data:{
            ok: true
        }
    });
</script>


</body>
</html>

测试

1.在浏览器上运行,打开控制台
2.在控制台输入vm.ok=false然后回车,你会发现浏览器中显示的内容会直接变成NO
  注:使用vm.属性绑定数据是不需要双花括号包裹的

for
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Vue数组练习</title>
</head>

<body>
  <!--View层 模版Template-->
  <div id="app">
    <!-- 类似Foreach循环 -->
    <li v-for="item in items">
      {{item.message}}
    </li>

  </div>

  <!-- 导入vue.js   -->
  <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
  <script>
    var vm = new Vue({
      el: "#app", //通过element元素绑定id为app的模块
      //Model:数据
      data: {
        //数组
        items: [{
            message: 'Darwin'
          },
          {
            message: 'Zhong'
          },
          {
            message: 'Clinkz'
          },
        ]
      }
    });
  </script>

</body>

</html>

2.2、事件

on
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>

<body>
  <!--View层 模版Template-->
  <div id="app">
    <button v-on:click="sayHi">Click</button>
  </div>
  <!-- 导入vue.js   -->
  <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
  <script>
    var vm = new Vue({
      el: "#app", //通过element元素绑定id为app的模块
      //Model:数据
      data: {
        message: 'Darwin'
      },
      methods: { //方法必须定义在methods中
        sayHi: function () {
          alert(this.message);
        }
      }
    });
  </script>

</body>

</html>
双向绑定

v-model

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

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Vue双向绑定</title>
</head>

<body>
  <!--View层 模版Template-->
  <div id="app">
    下拉框:
    <select v-model="message">
      <option value="" disabled>请选择</option>
      <option>A</option>
      <option>B</option>
      <option>C</option>
    </select>
    value:{{message}}

  </div>
  <!-- 1.导入vue.js   -->
  <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
  <script>
    var vm = new Vue({
      el: "#app", //通过element元素绑定id为app的模块
      //Model:数据
      data: {
        message: ""
      }
    });
  </script>

</body>

</html>

2.3、网络通信

  • JQuery.ajax()

  • Axios

    用在浏览器和Nodejs的异步通信框架,实现AJAX异步通信功能

    1. 从浏览器创建 XMLHttpRequest
    2. 从node.js创建http请求
    3. 支持Promise API [JS中链式编程]
    4. 拦截请求和响应
    5. 转换请求数据和响应数据
    6. 取消请求
    7. 自动转换JSON数据
    8. 客户端支持防御XSRF(跨站请求伪造)

伪数据:

{
  "name": "darwin",
  "url": "https://www.google.com",
  "page": 1,
  "isNonProfit": true,
  "address": {
    "street": "含光门",
    "city": "陕西西安",
    "country": "中国"
  },
  "links": [
    {
      "name": "bilibili",
      "url": "https://bilibili.com"
    },
    {
      "name": "darwin",
      "url": "https://www.google.com"
    },
    {
      "name": "百度",
      "url": "https://www.baidu.com/"
    }
  ]
}

测试代码:

<!DOCTYPE html>
<html lang="en" xmlns:v-binf="http://www.w3.org/1999/xhtml" xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!--v-cloak 解决闪烁问题-->
    <style>
        [v-cloak]{
            display: none;
        }
    </style>
</head>
<body>
<div id="vue" v-cloak>
    <div>地名:{{info.name}}</div>
    <div>地址:{{info.address.country}}--{{info.address.city}}--{{info.address.street}}</div>
    <div>链接:<a v-bind:href="info.url">{{info.url}}</a> </div>
</div>

<!--引入js文件-->
<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 type="text/javascript">
    var vm = new Vue({
        el:"#vue",
        //data:属性:vm
        data(){
            return{
                info:{
                    name:null,
                    address:{
                        country:null,
                        city:null,
                        street:null
                    },
                    url:null
                }
            }
        },
        mounted(){//钩子函数
            axios
                .get('../data.json')
                .then(response=>(this.info=response.data));
        }
    });
</script>
</body>
</html>

说明:

  1. v-bind将a:href的属性值和vue中的实例数据绑定
  2. 使用axios框架的get方法请求ajax并自动将数据封装到vue实例对象
  3. data中的数据结构必须和ajax响应的数据格式匹配

2.4、计算属性

计算出来的结果保存在属性中,内存中运行:虚拟DOM

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>

<body>
  <!--View层 模版Template-->
  <div id="app">
    <p>currentTime1:{{currentTime1()}}</p>
    <p>currentTime2:{{currentTime2}}</p>
  </div>


  <!-- 导入vue.js   -->
  <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
  <script>
    var vm = new Vue({
      el: "#app", //通过element元素绑定id为app的模块
      data: {
        message: "hello,Vue!"
      },
      methods: {
        currentTime1: function () {
          return Date.now(); //返回当前时间戳
        }
      },
      computed: { //计算属性:methods和computed里的方法不能重名
        //跑一次之后就缓存到内存中,如果改变其中数据则再次重新计算
        currentTime2: function () {
          this.message; // 
          return Date.now(); //返回当前时间戳
        }
      }
    });
  </script>
</body>

</html>

2.5、组件化

自定义组件
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>定义一个Vue组件</title>
</head>

<body>
  <!--View层 模版Template-->
  <div id="app">

    <darwin v-for="item in items" v-bind:bind="item"></darwin>
    <li v-for="item in items">{{item}}</li>

  </div>
  <!-- 1.导入vue.js   -->
  <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
  <script>
    //定义一个Vue组件
    Vue.component("darwin", {
      props: ['bind'], //props属性:接收参数
      template: ' <li>{{bind}}</li>'
    })

    var vm = new Vue({
      el: "#app", //通过element元素绑定id为app的模块
      //Model:数据
      data: {
        message: "",
        items: ["Java", "GoLang", "Python"]
      }
    });
  </script>

</body>

</html>
动态可拔插:slot插槽

通过定义slot形成插槽,自定义组件插入插槽实现动态可拔插

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>

<body>
  <!--View层 模版Template-->
  <div id="app">
    <todo>
      <todo-title slot="todo-title" :title="title"></todo-title>
      <todo-items slot="todo-items" v-for="item in todoItems" :item="item"></todo-items>
    </todo>
  </div>


  <!-- 导入vue.js   -->
  <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
  <script>
    //slot:插槽插入数据
    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", //通过element元素绑定id为app的模块
      data: {
        title: "hello,Vue!",
        todoItems: ['Java', 'Python', 'Linux']
      },

    });
  </script>
</body>
</html>
自定义事件分发

由于自定义的插槽组件的作用域仅仅是插槽,但是数据位于Vue的对象内,插槽里的按钮作用不到。因此通过自定义标签绑定Vue对象里的方法和值,然后传入自定义的插槽组件中

在自定义标签绑定Vue对象的方法时,v-on:自定义方法名=“Vue对象方法名”,进行方法和参数的传递。通过this.$emit(‘自定义方法名’,‘参数’);接收完成绑定。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>

<body>
  <!--View层 模版Template-->
  <div id="app">
    <todo>
      <todo-title slot="todo-title" :title="title"></todo-title>
      <todo-items slot="todo-items" v-for="(item,index) in todoItems" :item="item" :index="index"
        v-on:remove="removeItems(index)" ></todo-items>
    </todo>
  </div>


  <!-- 导入vue.js   -->
  <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
  <script>
    //slot:插槽插入数据
    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', 'index'],
      template: ' <li>{{index}}----{{item}}<button @click="remove">Delete</button></li>',
      //只能绑定当前组件的方法,而拿不到vm对象的方法
      methods: {
        remove: function (index) {
            //自定义事件分发
          this.$emit('remove', index);
          alert("Complete delete");
        }
      }
    });

    var vm = new Vue({
      el: "#app", //通过element元素绑定id为app的模块
      data: {
        title: "hello,Vue!",
        todoItems: ['Java', 'Python', 'Linux']
      },
      methods: {
        removeItems: function (index) {
          console.log("删除了:" + this.todoItems[index])
          //splice(index,int,"String","String");index:下标,int:删除当前下标下多少个元素,String:添加的项目
          this.todoItems.splice(index, 1); //一次删除一个元素
        }
      }

    });
  </script>
</body>

</html>

三、Vue项目

所有元素必须包含在标签中,即根节点下

vuec-cli是官方提供的脚手架,用于快速生成一个vue项目模版

3.1、创建Vue项目

# 进入目录工程
#安装vue-router
    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

3.2、Npm命令解释

npm install moduleName:安装模块到项目目录下

npm install -g moduleName:-g 的意思是将模块安装到全局,具体到磁盘中哪个位置看 npm config ls 中的 prefix位置

npm install -save moduleName:–save的意思是将模块安装到项目目录下,并在package文件的dependencies节点写入依赖,-S为该命令缩写

npm install -save-dev moduleName:–save-dev的意思是将模块安装到项目目录下,并在package文件的devDependencies节点写入依赖,-D为该命令缩写

3.3、Router路由配置

小问题:在项目搭建中遇到了个小问题,sass-loader的版本是7.3.1,node-sass的版本是4不兼容,npm uninstall node-sass卸载node-sass,npm install sass@1.26.5 --save-dev安装1.26.5版本即可(因为nodejs版本是16所以sass加载器版本必须在7以上)

配置步骤:

  1. 检查项目node model中是否存在vue-router
  2. 新建router文件夹,用来存放路由,引入路由之后必须通过Vue.use(VueRouter);安装

例:新建一个index.js的路由

注意:routes数组里每条路由的path路径是访问路径,即在浏览器的搜索框里输入path跳转至对应页面,绝对路径已经在import导入时与组件绑定,因此path无关紧要

import Vue from 'vue'
import Router from 'vue-router'
import Main from '../views/Main.vue'
import Login from '../views/Login.vue'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/login',
      component: Login
    }, {
      path: '/main',
      component: Main
    }
  ]
})

  1. 在main.js中引入路由

例:

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) /* ElementUI的官方配置 */
})

  1. 定义组件

Main首页:

<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">
                <!--插入的地方-->
                <!-- name:组件名,通过params传递参数   vm双向绑定  -->
                <router-link :to="{name:'profile', params:{id:1}}">个人信息</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: #5ba1fd;
  color: #333;
  line-height: 60px;
}
.el-aside {
  color: #333;
}
</style>

Login登录:

<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="dialogVisiable"
               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) {
      // 为表单绑定验证功能
        //通过$refs引用数据
      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 hsl(220, 4%, 58%);
}
.login-title {
  text-align: center;
  margin: 0 auto 40px auto;
  color: #303133;
}
</style>

  1. 在App.vue主入口中使用路由
<template>
  <div id="app">
    <router-link to="/login">login</router-link>
    <router-view></router-view>
  </div>
</template>
<script>
export default {
  name: 'App'
}
</script>

<style>
</style>

3.4、嵌套路由

嵌套路由又称子路由,即多层嵌套的组件组合而成,URL中各段状态路径也按某种结构对应嵌套的各层组件

在路由中import导入组件后,在需要嵌套的路由下添加children属性,配置子路由方式和普通路由一致

{
      path: '/main',
      component: Main,
      // 嵌套路由
      children: [
        {path: '/user/profile/:id',
          name: 'profile',
          component: UProfile},
        {path: '/user/list', component: UList}
      ]
    }

例子中通过路由给页面传递参数:改变了to的值,将其作为对象使用需要双向绑定,并且里面的属性必须和路由中定义的属性名对应

  <el-menu-item index="1-1">
    <!--插入的地方-->
    <!-- name:组件名,通过params传递参数   vm双向绑定  -->
    <router-link :to="{name:'profile', params:{id:1}}">个人信息</router-link>
  </el-menu-item>

嵌套路由的页面:

**比较接收参数的方式!**此处通过route取

<template>
  <div>
    <h1>个人信息</h1>
    {{$route.params.id}}
  </div>
</template>

<script>
export default {
  name: 'profile'
}
</script>

<template>
  <h1>用户列表</h1>
</template>

<script>
export default {
  name: 'list'
}
</script>

3.5、参数传递

通过props解耦

将路由中的props属性设为true

此处遇到小问题:配置路由时props位于conponent上方报错

index.js:

import Vue from 'vue'
import Router from 'vue-router'
import Main from '../views/Main.vue'
import Login from '../views/Login.vue'
import UList from '../views/user/List.vue'
import UProfile from '../views/user/Profile.vue'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/login',
      component: Login
    }, {
      path: '/main',
      component: Main,
      // 嵌套路由
      children: [
        {path: '/user/profile/:id',
          name: 'profile',
          component: UProfile,
          props: true},
        {path: '/user/list', component: UList}
      ]

    }
  ]
})

profile:通过props组件

<template>
  <div>
    <h1>个人信息</h1>
    <!-- {{$route.params.id}} -->
    {{id}}
  </div>
</template>

<script>
export default {
  props: ['id'],
  name: 'profile'
}
</script>

3.6、重定向

重定向即添加一个新的路由路径,增加redirect属性指定一个需要跳转的路径,再页面中添加互动标签导入此路由即可

import Vue from 'vue'
import Router from 'vue-router'
import Main from '../views/Main.vue'
import Login from '../views/Login.vue'
import UList from '../views/user/List.vue'
import UProfile from '../views/user/Profile.vue'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/login',
      component: Login
    }, {
      path: '/main',
      component: Main,
      // 嵌套路由
      children: [
        {path: '/user/profile/:id',
          name: 'profile',
          component: UProfile,
          props: true},
        {path: '/user/list', component: UList}
      ]
    },
    {
      path: '/gohome',
      redirect: '/main'
    }
  ]
})

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">
                <!--插入的地方-->
                <!-- name:组件名,通过params传递参数   vm双向绑定  -->
                <router-link :to="{name:'profile', params:{id:1}}">个人信息</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-menu-item index="1-3">
              <!--插入的地方-->
              <router-link to="/gohome">主界面</router-link>
            </el-menu-item>
          </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: #5ba1fd;
  color: #333;
  line-height: 60px;
}
.el-aside {
  color: #333;
}
</style>

解决url总有个井号的问题

路由模式有两种

  • hash:路由路径带#符号,如 http://localhost/#/login
  • history:路径不带井号,如http://localhost/login

修改路由配置,例子修改的是index:

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

3.7、404界面

当访问访问不到的路径时,弹出404页面,路径用 * 表示,即能访问到的路径直接进入,访问不到一律走404

NotFound界面:

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

index路由配置:

{
      path: '*',
      component: NotFound
    }

3.8、路由钩子和异步请求

vue生命周期
在这里插入图片描述

beforeRouteEnter:在进入路由前执行

beforeRouteLeave:在离开路由前执行

export default {
  props: ['id'],
  name: 'profile',
  // 过滤器
  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是组件实例

通过next获取数据:

  1. 配置main.js安装axios,并在static/mock下建立伪数据(参考之前网络通信)

    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'
    
    import axios from 'axios'
    import VueAxios from 'vue-axios'
    
    Vue.use(router)
    Vue.use(ElementUI)
    Vue.use(VueAxios, axios)
    
    /* eslint-disable no-new */
    new Vue({
      el: '#app',
      router,
      render: h => h(App) /* ElementUI的官方配置 */
    })
    
  2. 在next方法中编写对象实例,调用本对象的方法,并在方法中编写获取数据的方法,利用控制台输出response对象

    export default {
      props: ['id'],
      name: 'profile',
      // 过滤器
      beforeRouteEnter: (to, from, next) => {
        console.log('进入之前')
        next(vm => {
          vm.getData()
        })
      },
      beforeRouteLeave: (to, from, next) => {
        console.log('离开')
        next()
      },
      methods: {
        getData: function () {
          this.axios({
            method: 'get',
            url: 'http://localhost:8080/static/mock/data.json'
          }).then(function (response) {
            console.log(response)
          })
        }
      }
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值