Vue框架✧从入门到放弃

15 篇文章 0 订阅
8 篇文章 0 订阅

🍜VUE✧框架



概述: 前端三要素,结构层html表现层css行为层js(es5规范/es6),vue基于es6,尤雨溪是Vue.js的作者,Vue:一款渐进式框架,综合了Angular,和React(只关注视图)。

  • JQuery简化DOM,缺点DOM操作太频繁
  • Angular(NG):双向绑定思想,MVVM
  • React:Facebook,提出虚拟DOM概念,DOM就是xml节点
  • MVVM(Model-View-ViewModel)核心是ViewModel,通过它实现双向绑定,其中路由主要就是实现单页面,不做跳转,每次操作都是单页面渲染

目前前端UI框架:ElementUI(饿了么出品),BootStrap,Amazeui 妹子UI(国产),Layui。


前后端演变史

  • 后端MVC时代
  • 基于Ajax的SPA时代
  • 前端为主的MV*时代
  • NodeJs带来的全栈时代
  • 前端MVVM模式

一、Vue声明周期

1、什么是声明周期?

Vue 实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模板、挂载 DOM、渲染→更新→渲染、卸载等一系列过程,我们称这是 Vue 的生命周期。通俗说就是 Vue 实例从创建到销毁的过程,就是生命周期。(官方图:)
在这里插入图片描述


2、钩子函数
  • beforeCreate:实例化之后,事件配置之前
  • created:实例化之后被调用,挂载未开始之前
  • beforeMount:挂在开始之前(rednder函数首次被调用)
  • mounted:el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。
  • beforeUpdate:数据更新之前
  • updated:数据更新之后
  • beforeDestroy:实例销毁之前
  • destroyed:Vue实例销毁后调用

代码测试;》》》》

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

<div id="app">
   {{ message }}
</div>


<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
    var app = new Vue({
        el:"#app",
        data:{
            message:"hello vue"
        },
        // 在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。
        beforeCreate:function (){
            console.log("数据获取--->"+this.message)
        },
        /*
        * 在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:
        *      数据观测 (data observer),
        *      property 和方法的运算,
        *      watch/event 事件回调。
        * 然而,挂载阶段还没开始,$el property 目前尚不可用。
        * */
        created:function (){
            console.log("实例创建完成后执行created 时间..."+this.message)
        },
        //在挂载开始之前被调用:相关的 render 函数首次被调用。
        beforeMount:function (){
            console.log("编译完成的html 被挂载到虚拟dom 前触发,此时页面还无内容...");
        },
        /*
        * 实例被挂载后调用,这时 el 被新创建的 vm.$el 替换了。如果根实例挂载到了一个文档内的元素上,当 mounted 被调用时 vm.$el 也在文档内。
            注意 mounted 不会保证所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以在 mounted 内部使用 vm.$nextTick:
        */
        mounted:function (){
            console.log("编译好的html 挂载到页面完毕执行mounted 事件");
        },
        // 数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。
        beforeUpdate:function (){
            console.log("更新前执行beforeUpdate事件...");
        },
        // 由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。
        updated:function (){
            console.log("更新后执行updated 事件...");
        },
        //实例销毁之前调用。在这一步,实例仍然完全可用。
        beforeDestroy:function (){
            console.log("实例被销毁前执行beforeDestroy 事件...")
        },
        /*
        * 实例销毁后调用。该钩子被调用后,对应 Vue 实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁。
        */
        destroyed:function (){
            console.log("实例销毁完成后执行destroyed 事件...")
        }
    })
    
    setTimeout(function (){
    //10000s后修改message的数据
        app.message="message is updated....";
    },10000);

</script>
</body>
</html>

未更新前
在这里插入图片描述

更新后
在这里插入图片描述


二、基本操作

1、条件渲染(数据绑定)
  • v-if、v-else(if…else)
  • v-bind
<!DOCTYPE html>
<html lang="en">
<head>
    <title>Document</title>
    <script src="js/vue.js" ></script>
</head>
<body>
    <div id="app">
        <h4 v-if="status">欢迎登录</h4>
        <h4 v-else>登录成功</h4>
        <span v-bind:status="status">{{status}}</span>
    </div>
    <script>
        var app=new Vue({
            el:"#app",
            data:{
                status:true
            }
        })
    </script>
</body>
</html>

在这里插入图片描述
在这里插入图片描述


2、列表渲染
  • 循环遍历语句:v-for
<!DOCTYPE html>
<html lang="en">
<head>
    <title>Document</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        <ul>
            <li v-for="id in ids">
                {{id}}
            </li>
        </ul>
    </div>
    <script>
        var app=new Vue({
            el:"#app",
            data:{
                ids:[1,2,3,4,5]
            }
        })
    </script>
</body>
</html>

在这里插入图片描述


3、事件处理
  • v-on:事件
  • eg:click,focus,blur等

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Document</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        <!-- <input v-on:focus="onfocus" v-model="userName" /> -->
        <input @blur="onblur">
    </div>
    <script>
        var app=new Vue({
            el:"#app",
            data:{
                userName:'lisi'
            },
            methods:{
                onfocus:function(){
                    alert("获取到焦点了🎀");
                },
                onblur:function(){
                    alert("失去焦点🎀~")
                }
            }
        })
    </script>
</body>
</html>

在这里插入图片描述


4、表单输入绑定
  • 什么是数据双向绑定:Vue.js 是一个 MVVM 框架,即数据双向绑定,即当数据发生变化的时候,视图也就发生变化,当视图发生变化的时候,数据也会跟着同步变化。这也算是 Vue.js 的精髓之处了。值得注意的是,我们所说的数据双向绑定,一定是对于 UI 控件来说的

表单数据双向绑定演示:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Document</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        <form>
            用户名:<input v-model="userName">
            密码:<input v-model="userPass"><br>
            <textarea v-model="message"></textarea><br>
            打游戏:<input type="checkbox" value="game" v-model="checks">
            学习:<input type="checkbox" value="study" v-model="checks" ><br>
            <p>单选按钮</p>
            <input type="radio" id="one" value="One" v-model="picked"/>
            <label for="one">One</label>
            <br>
            <input type="radio" id="two" value="Two" v-model="picked"/>
            <label for="two">Two</label>
            <br>
            <span>Picked:{{picked}}</span>
            <p>选择框</p>
            <select v-model="selected">
            <option disabled value =""></option>
            <option>A</option>
            <option>B</option>
            <option>C</option>
            </select>
            <span>Selected :{{selected}}</span>

            <input type="submit" value="提交">
        </form>
    </div>
    <script>
        var app=new Vue({
            el:"#app",
            data:{
                userName:"李四",
                userPass:12345,
                message:"hello vue",
                checks:[],
                picked:"",
                selected:""
            }
        })
    </script>
</body>
</html>

在这里插入图片描述


三、Axios实现异步通信框架

1、什么是 Axios?

Axios 是一个开源的可以用在浏览器端和 NodeJS 的异步通信框架,它的主要作用就是实现 AJAX 异步通信(底层依旧是Ajax),其功能特点如下:

  • 从浏览器中创建 XMLHttpRequests
  • node.js 创建 http 请求
  • 支持 Promise API
  • 拦截请求和响应
  • 转换请求数据和响应数据
  • 取消请求
  • 自动转换 JSON 数据
  • 客户端支持防御 XSRF(跨站请求伪造)

案例:新建一个data.json文件,通过axios发送请求获取数据

{
    "name": "百度",
    "url": "http://www.baidu.com",
    "page": 66,
    "isNonProfit": true,
    "address": {
      "street": "海定区",
      "city": "北京市",
      "country": "中国"
    },
    "links": [
      {
        "name": "Google",
        "url": "http://www.google.com"
      },
      {
        "name": "Baidu",
        "url": "http://www.baidu.com"
      },
      {
        "name": "Sougou",
        "url": "http://www.sougou.com"
      }
    ]
  }

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Title</title>
</head>
<body>

<div id="example">
    <div>
        名称:{{info.name}}
    </div>
    <div>
        地址:{{info.address.country}}-{{info.address.city}}-{{info.address.street}}
    </div>
    <div>
        链接:<a v-bind:href="info.url" target="_blank">{{info.url}}</a>
    </div>
    <ul>
        <li v-for="link in info.links">{{link.name}}-{{link.url}}</li>
    </ul>
</div>


<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript" src="js/axios.min.js"></script>
<script type="text/javascript">
    var example = new Vue({
        el: '#example',
        data() {
            return {
                info: {
                    name: '',
                    address: {
                        country: '',
                        city: '',
                        street: ''
                    },
                    links: []
                }
            }
        },
        mounted() {
            axios.get('data.json').then(response => this.info = response.data)
        }
    })
</script>
</body>
</html>

在这里插入图片描述


四、Vue组件

  • 什么是组件:组件其实就是一个可以重复使用的模板,与thymeleaf,freemarker模板语言有异曲同工之妙

1、组件入门demo
<body>
    <div id="app">
        <demo1 v-bind:mg="msg"></demo1>
    </div>
  <script>
        // 组件一
        Vue.component("demo1",{
            props:['mg'],
            template:"<span>{{mg}}</span>"
        })
          //设置具体数据
        var app=new Vue({
            el:"#app",
            data:{
                msg:"Vue is Good"
            },
           
        })
	</script>
</body>

在这里插入图片描述


2、组件配合事件
<body>
    <div id="app">
        <demo1 v-bind:mg="msg"></demo1>
        <ul>
            <li>
                <demo2 v-for="it in items" v-bind:item="it"></demo2>  
            </li>
        </ul> 
    </div>

    <script>
        // 组件一
        Vue.component("demo1",{
            props:['mg'],
            template:"<span>{{mg}}</span>"
        })

        // 组件二
        Vue.component("demo2",{
            props:['item'],
            template:"<li>{{item}}<button v-on:click='test'>删除</button></li>",
            methods:{
                test:function(){
                    alert('删除')
                }
            }
        })

        //设置具体数据
        var app=new Vue({
            el:"#app",
            data:{
                msg:"Vue is Good",
                items:[1111,2222,3333,4444]
            },
        })
    </script>
</body>

在这里插入图片描述


3、插槽与自定义事件
①、什么是插槽?
  • 个人理解:插槽,插入的卡槽,我们定义的每个组件可以视为卡,当我们用组件定义一个大的插槽,那么这个插槽里便可以插入若干个组件(卡)。
②、案例Demo(自定义删除事件)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        <todo>
            <demo1 slot="demo1" v-bind:title="title"></demo1>
            <demo2 slot="demo2" v-for="(item,index) in items" v-bind:item="item" 
            v-bind:index="index" v-on:remove="removes"></demo2>
        </todo>
    </div>
    
    
    <script>
        Vue.component('todo',{
            template:"<div><slot name='demo1'></slot><ul><slot name='demo2'></slot></ul></div>"
        });
        Vue.component('demo1',{
            props:['title'],
            template:"<span>{{title}}</span>"
        });
        Vue.component('demo2',{
            props:['item','index'],
            template:"<li>{{index}}----{{item}}<button v-on:click=\"$emit('remove')\">删除</button></li>",
        })

        var app=new Vue({
            el:"#app",
            data:{
                title:"hello Vue",
                items:['aa','bb','cc','dd']
            },
            methods:{
                removes:function(index){
                    this.items.splice(index,1)
                }
            }
        })
    </script>
</body>
</html>

在这里插入图片描述


4、计算属性

计算属性是用来声明式的描述一个值依赖了其它的值。当你在模板里把数据绑定到一个计算属性上时,Vue 会在其依赖的任何值导致该计算属性改变时更新 DOM。这个功能非常强大,它可以让你的代码更加声明式、数据驱动并且易于维护。简单点说,它就是一个能够将计算结果缓存起来的属性(将行为转化成了静态的属性),仅此而已;


<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			<p>当前时间方法:{{getCurrentTime()}}</p>
			<p>当前时间属性:{{getCurrentTime1}}</p>
		</div>
		<script type="text/javascript">
			var app = new Vue({
				el:'#app',
				methods:{
					getCurrentTime:function(){
						return Date.now();
					}
				},
				computed:{
					getCurrentTime1:function(){
						return Date.now();
					}
				}
			});
		</script>
	</body>
</html>

说明

  • methods:定义方法,调用方法使用 getCurrentTime(),需要带括号,时间会随再方法调用时刷新。
  • computed:定义计算属性,调用属性使用 getCurrentTime01,不需要带括号;
  • 注意:methodscomputed 里不能重名

在这里插入图片描述


五、Vue-cil脚手架

1、什么是脚手架?

大白话就是给你建一个空的Vue项目框架,快速生成一个项目模板。

  • 环境要求:Node.js(>= 6.x,首选 8.x)
  • 官网下载地址 http://nodejs.cn/download

2、环境搭建
# 下载cnpm -g全局使用
npm install cnpm -g

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

# 安装脚手架
cnpm install vue-cli -g

# 查看可以基于哪些模板创建 vue 应用程序,通常我们选择 webpack
vue list
# 如下图完成:

在这里插入图片描述


3、入门案例
①生成项目模板
# 项目名随意demo
vue init webapp demo

在这里插入图片描述

  • Project name:项目名称,默认 回车 即可
  • Project description:项目描述,默认 回车 即可
  • Author:项目作者,默认 回车 即可
  • Install vue-router:是否安装 vue-router,选择 n 不安装(后期需要再手动添加)
  • Use ESLint to lint your code:是否使用 ESLint 做代码检查,选择 n 不安装(后期需要再手动添加)
  • Set up unit tests:单元测试相关,选择 n 不安装(后期需要再手动添加)
  • Setup e2e tests with Nightwatch:单元测试相关,选择 n 不安装(后期需要再手动添加)
  • Should we run npm install for you after the project has been created:创建完成后直接初始化,选择 n,我们手动执行

为了快速建立项目,全都NO,最后选择第三个省的去下载资源


② 初始化运行
# 进入项目文件夹
cd firstvue
# 初始化项目
npm install
# 运行项目
npm run dev

在这里插入图片描述

在这里插入图片描述


六、WebPack打包

  • 就是对项目的打包

① 添加modules/main.js和hello.js

# hello.js
exports.sayHi = function () {
    document.write("<div>Hello WebPack</div>");
  };
# main.js
var hello = require("./hello");
hello.sayHi();

② 添加配置文件src/webpack.config.js和index.html

# index.html
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script src="dist/js/bundle.js"></script>
	</body>
</html>

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

打包

# 用于监听变化
webpack --watch

运行html,浏览器会显示

Hello WebPack

七、vue-router路由插件

1、什么是路由?
  • 主要就是进行单页面的构建,统一对请求访问路径的管理,实现单页面效果

2、安装✧案例
①安装

进入项目内进行安装,属于Vue插件

npm install vue-router --save-dev

② 入门案例

编写组件页面Contend.vue

<template>
  <div>
    我是内容页
  </div>
</template>

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

配置路由:

import Vue from 'vue'
// 导入路由插件
import Router from 'vue-router'
// 导入自定义的组件
import Content from '../components/Content'
// 安装路由
Vue.use(Router);

// 配置路由
export default new Router({
  routes: [
    {
    // 路由路径
    path: '/content',
    // 路由名称
    name: 'Content',
    // 跳转的组件
    component: Content
    },
]
});

使用路由修改App.vue

<template>
  <div id="app">
    <img src="./assets/logo.png">
    <!-- 路由链接 -->
    <router-link to="/">首页</router-link>
    <router-link to="/content">内容页</router-link>
    <!-- 路由组件 -->
    <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

import Vue from 'vue'
import App from './App'
import VueRouter from 'vue-router'
// 导入路由配置目录
import router from './router'

Vue.use(VueRouter);

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  // 配置路由
  router,
  components: { App },
  template: '<App/>',
  render: h => h(App)
})

在这里插入图片描述


3、整合ElementUI
①、创建项目
# 使用 webpack 打包工具初始化一个名为 vue-elementui 的工程
vue init webpack vue-elementui
# 需要安装四个插件
# 进入工程目录
cd vue-elementui
# 安装 vue-router
npm install vue-router --save-dev
# 安装 element-ui
npm i element-ui -S
# 安装 SASS 加载器
npm install sass-loader@7.3.1 node-sass --save-dev
# 安装项目所有依赖
npm install

安装完npm run dev作为测试,查看是否成功

附:NPM 相关命令说明

  • npm install moduleName:安装模块到项目目录下
  • npm install -g moduleName:-g 的意思是将模块安装到全局,具体安装到磁盘哪个位置,要看 npm config prefix 的位置
  • npm install -save moduleName:–save 的意思是将模块安装到项目目录下,并在 package 文件的 dependencies 节点写入依赖,-S 为该命令的缩写
  • npm install -save-dev moduleName:–save-dev 的意思是将模块安装到项目目录下,并在 package 文件的 devDependencies 节点写入依赖,-D 为该命令的缩写

②、入门ElementUI案例

(1)编写登录视图页面:Views/Login.vue

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

<script>
  export default {
    name: 'Login',
    data() {
      return {
        form: {
          name: '',
          password: '',
        },
        rules: {
          name: [{
            required: true,
            message: '请输入用户名',
            trigger: 'blur'
          }],
          password: [{
            required: true,
            message: '请输入密码',
            trigger: 'blur'
          }]
        }
      };
    },
    methods: {
      onSubmit(form) {
        this.$refs[form].validate((valid) => {
          if (valid) {
            // 设置用户登录成功
      // sessionStorage.setItem('isLogin', 'true');
            this.$router.push("/main");
          } else {
            this.$message.error('请输入用户名或密码');
            return false;
          }
        });
      }
    }
  }
</script>

<style lang="css" scoped>
  .login-box {
    /* // 宽度 */
    width: 400px;
    /* // 边距 */
    margin: 200px auto;
    /* // 边框 */
    border: 1px solid #DCDFE6;
    /* // 内边距 */
    padding: 40px;
    /* // 边框圆角 */
    border-radius: 10px;
    /* // 阴影 */
    box-shadow: 0 0 30px #DCDFE6;
  }

  .login-title {
    /* // 文本居中 */
    text-align: center;
  }
</style>

(2)配置路由router/index.js

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

Vue.use(Router);

export default new Router({
    // mode:'history',地址栏访问格式
  routes:[
    {
      // 登录页
      path:'/login',
      name:'Login',
      component:Login
    },
  ]
});

(3)引入路由至main.js

import Vue from 'vue'
import App from './App'
import VueRouter from 'vue-router'
// import Vuex from 'vuex'

// 引入ElementUI
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import router from './router'

// Vue.use(Vuex);
Vue.use(VueRouter);
// 安装ElementUI
Vue.use(ElementUI);

Vue.config.productionTip = false

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

(4)修改App.Vue

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

<script>

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

在这里插入图片描述


③、路由嵌套,参数传递,路由重定向案例
  • 此案例直接包含路由嵌套,参数传递,重定向三个知识点(再上一个登录案例上进行修改)

(1)编写主视图和子视图以及404视图

主视图:views/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-message"></i>会员管理</template>
            <el-menu-item index="1-1">
              <router-link to="/members/list">会员列表</router-link>
            </el-menu-item>
            <el-menu-item index="1-2">
              <!-- <router-link to="/members/level/2">会员等级</router-link> -->
              <router-link :to="{name:'MemberLevel',params:{id:2}}">会员等级</router-link>
            </el-menu-item>
              <el-menu-item index="1-3">
              <router-link to="/goMain2/admin12345">返回首页</router-link>
            </el-menu-item>
          </el-submenu>
          <el-submenu index="2">
            <template slot="title"><i class="el-icon-message"></i>商品管理</template>
            <el-menu-item index="2-1">商品分类</el-menu-item>
            <el-menu-item index="2-2">商品列表</el-menu-item>
          </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>
          <span>admin</span>
        </el-header>
        <el-main>
          {{$route.params.name}}
           <!-- <span>{{$store.getters.getUser.name}}</span> -->
          <router-view />
        </el-main>
      </el-container>
    </el-container>
  </div>
</template>

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

<style>
  .el-header {
    background-color: #B3C0D1;
    color: #333;
    line-height: 60px;
  }

  .el-aside {
    color: #333;
  }
</style>

子视图:views/members/memberLevel.vue和memberList.vue

<template>
  <div>
    会员等级--->{{$route.params.id}}--->{{id}}
  </div>
</template>

<script>
  export default{
    name:'MemberLevel',
    props: ['id'],
     beforeRouteEnter: (to,from,next) => {
      console.log("进入会员等级页面");
      console.log(to);
      console.log(from);
      next("/Login");
    },
    beforeRouteLeave:(to,from,next)=>{
      console.log("离开会员等级页面");
      next();
    }
  }
</script>

<style>
</style>

<template>
  <div>
    会员列表
  </div>
</template>

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

<style>
</style>

404页面未找到视图:NotFound.vue

<template>
  <div>404</div>
</template>
<script>
export default {
    name:'NotFound'
}
</script>
<style>
</style>

(2) 修改路由配置

router/index.js

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

// 用于嵌套路由的组件
import MemberList from '../views/members/MemberList'
import MemberLevel from '../views/members/MemberLevel'

Vue.use(Router);

export default new Router({
    // mode:'history',
  routes:[
    {
      // 登录页
      path:'/login',
      name:'Login',
      component:Login
    },
    {
      // 首页
      path:'/main/:name',
      name:'Main',
      component:Main,
       // 嵌套路由
       children:[
        {
          // 会员等级
          path:'/members/level/:id',
          name:'MemberLevel',
          component:MemberLevel,
          props: true
        },
        {
          // 会员列表
          path:'/members/list',
          name:'MemberList',
          component:MemberList
        }
       ]
    },
    {
        path: '/goMain',
        redirect: '/main'
    },
    {
        path: '/goMain2/:name',
        redirect: '/main/:name'
    },
    {
        path:'*',
        name:'NotFound',
        component:NotFound
    }
  ]
});

(3) 测试结果

在这里插入图片描述


总结:参数传递的两种方式:①:/:id 和{{ $route.params.id }} ②:props: ['id']和{{id}},重定向两种方式;①:直接再标签写router-link to="/goMain ②:配置路由redirect: '/main/:name'"
最后是路由的钩子函数:

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

参数说明:

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

八、VueX状态管理模式

Vuex 是一个专为 Vue.js 应用程序开发的 状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。


1、通过VueX实现登录状态的管理

接上面的项目继续修改---》》》》》
①安装下载Vuex

npm install vuex --save

②判断是否登录
Login.vue中的判断是否登录成功中添加:

 // 设置用户登录成功Session Storage
 sessionStorage.setItem('isLogin', 'true');

③在程序入口main.js中用钩子函数判断

# 引入vuex
import Vuex from 'vuex'
Vue.use(Vuex);

#钩子函数进行判断
// 路由跳转前执行
router.beforeEach((to,from,next)=>{
  // 获取用户登录状态
	let isLogin = sessionStorage.getItem('isLogin');

	// 注销
	if(to.path=='/logout'){
    // 清空
		sessionStorage.clear();
    // 跳转到登录页面
		next({path:'/login'});
	}else if(to.path=='/login'){
        if(isLogin != null){
          next({path:'/main'});
        }
  }else if(isLogin == null){
    next({path:'/login'});
  }
  // 下一个路由
	next();
})


在这里插入图片描述

主要就是实现了,未登录无法访问别的页面


2、解决页面刷新与用户数据展示问题

(1)配置vuex(store/index.js)

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex);

// 全局state对象,用于保存所有组件的公共数据
// const state={
//     user:{
//         name:''
//     }
// };
const state = sessionStorage.getItem('state') ? JSON.parse(sessionStorage.getItem('state')) : {
    user: {
      username: ''
    }
  };
// 监听state值的最新状态(计算属性)
const getters={
    getUser(state){
        return state.user;
    }
};

// 唯一可以改变state值的方法(同步执行)
const mutations={
    updateUser(state,user){
        state.user=user;
    }
}

// 异步执行mutations方法
const actions={
    asyncUpdateUser(context,user){
        context.commit('updateUser',user);
    }
}
export default new Vuex.Store({
    state,
    getters,
    mutations,
    actions
})

(2) 修改Login.vue

    methods: {
      onSubmit(form) {
        this.$refs[form].validate((valid) => {
          if (valid) {
            // 设置用户登录成功Session Storage
            sessionStorage.setItem('isLogin', 'true');
            this.$store.dispatch('asyncUpdateUser',{name:this.form.name})
            this.$router.push("/main");
          } else {
            this.$message.error('请输入用户名或密码');
            return false;
          }
        });
      }
    }

(3) 引入配置至main.js

//主要增加内容:
import axios from 'axios'
import store from './store'
// 安装axios
Vue.prototype.axios=axios;

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

(4)修改main.vue文件

//展示用户名的地方改成这个
  <span>{{$store.getters.getUser.name}}</span>

(5)添加页面刷新监听App.vue

  export default {
    name: 'App',
    mounted() {
      window.addEventListener('unload', this.saveState);
    },
    methods: {
      saveState() {
        sessionStorage.setItem('state', JSON.stringify(this.$store.state));
      }
    }
  }

在这里插入图片描述

模块化:就是将功能划分模块,存放在一个modules下的文件夹里,只需要用主文件调用即可


请添加图片描述

  • 13
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

每日小新

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值