【Vue】快速掌握Vue的基本使用

1、vue概述

Vue (读音/vju/, 类似于view)是一套用于构建用户界面的渐进式JavaScript框架,发布于2014年2月。与其它大型框架不同的是,Vue被设计为可以自底向上逐层应用。Vue的核心库只关注视图层,不仅易于上手,还便于与第三方库(如: vue-router: 跳转,vue-resource: 通信,vuex:管理)或既有项目整合

官网:https://cn.vuejs.org/v2/guide/

vue.js优点

  1. 体积小

    压缩后33K

  2. 更高的运行效率

    基于虚拟dom,一种可以预先通过JavaScript进行各种计算,把最终的dom操作计算出来并优化的技术,由于这个dom操作时预处理,并没有真实操作dom,所以叫做虚拟dom

  3. 双向数据绑定

    让开发者不用再去操作dom对象,把更多的精力投入到业务逻辑上。

  4. 生态丰富,学习成本低

    市场上拥有大量成熟、稳定的基于vue.js的ui框架,常用组件,拿来即用实现快速开发!

    对初学者友好,入门容易,学习资料多

vue.js – 前端开发人员必修技能

  1. 使用场景广泛

    被广泛的应用于web端,移动端,跨平台应用开发

  2. 招聘市场需求大,前景较好

2、前端知识体系

2.1、前端三要素

  • HTML (结构) :超文本标记语言(Hyper Text Markup Language) ,决定网页的结构和内容
  • CSS (表现) :层叠样式表(Cascading Style sheets) ,设定网页的表现样式
  • JavaScript (行为) :是一种弱类型脚本语言,其源代码不需经过编译,而是由浏览器解释运行,用于控制网页的行为

2.2、结构层(html)

可以看我之前的博客: 【前端三要素】HTML详解

2.3、表现层(css)

可以看我之前的博客: 【前端三要素】CSS快速入门

2.4、行为层(JavaScript)

可以看我之前的博客: 【前端三要素】JavaScript入门

4、第一个vue程序

4.1、什么是MVVM

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

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

  • 该层向上与视图层进行双向数据绑定
  • 向下与model层通过接口请求进行数据交互

image-20220626103446738

MVVM已经相当成熟了。主要运用单不仅仅在网络应用程序开发中。当下流行的MVVM框架有VUE.js和AngularJS等

4.2、为什么要使用MVVM

MVVM模式和MVC模式一样,主要目的是分离视图(view)和模型(model),有几个好处:

  • 低耦合

    视图(view)可以独立于model变化和修改,一个ViewModel可以绑定到不同的view上,当view变化的时候model可以不变,当model变化的时候view也可以不变

  • 可复用

    你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑

  • 独立开发

    开发成员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计

  • 可测试

    界面素来是比较难于测试的,而现在测试可以针对ViewModel来写

image-20220626110954580

4.3、MVVM模式的实现者 – vue

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

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

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

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

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

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

至此,我们就明白了,vue就是一个MVVM的实现者,它的核心就是实现了DOM监听与数据绑定。

4.4、第一个vue程序

对于完全0基础的同学,可以先去看我的另一个博客,算是预科知识吧,当然继续跟着这个博客也可以往下走【Vue】学习Vue前所需要知道的一些前端知识

  1. idea安装vue插件

    image-20220626110016192

  2. 新建一个空白项目Vue

  3. 新增一个文件demo01.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    
    <!-- view层 模板 -->
    <div id="app">
        <h2>{{message}}</h2>
    </div>
    
    <!-- 1. 导入vue.js -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    <script>
        var vm = new Vue({
            el:"#app",
            // Model 数据
            data:{
                message:"hello,vue"
            }
        });
    </script>
    </body>
    </html>
    
  4. 用浏览器打开

    image-20220626110200134

  5. 浏览器控制台修改

    vm.message='zyy'
    

    发现页面也修改了

    image-20220626110333259

Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统

img

八大生命周期钩子函数

函数调用时间
beforeCreatevue实例初始化之前调用
createdvue实例初始化之后调用
beforeMount挂载到dom树之前调用
mounted挂载到dom树之后调用
beforeUpdate数据更新之前调用
updated数据更新之后调用
beforeDestroyvue实例销毁之前调用
destroyedvue实例销毁之后调用

5、vue基本基本语法

5.1、v-bind

除了文本插值,我们还可以像这样来绑定元素 attribute

<div id="app">
  <span v-bind:title="message">鼠标悬停几秒钟查看此处动态绑定的提示信息!</span>
</div>
var vm = new Vue({
    el: "#app",
    // Model 数据
    data: {
        message:  message:"hello Vue!"
    }
});

这里我们遇到了一点新东西。你看到的 v-bind attribute 被称为指令。指令带有前缀 v-,以表示它们是 Vue 提供的特殊 attribute。可能你已经猜到了,它们会在渲染的 DOM 上应用特殊的响应式行为。在这里,该指令的意思是:“将这个元素节点的 title attribute 和 Vue 实例的 message property 保持一致”。

如果你再次打开浏览器的 JavaScript 控制台,输入 vm2.message = '新消息',就会再一次看到这个绑定了 title attribute 的 HTML 已经进行了更新。

5.2、v-if…v-else-if…v-else

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

<div id="app">
  <h v-if="ok">Yes</h>
  <h v-else>No</h>

  <h v-if="type==='A'">A</h>
  <h v-else-if="type==='B'">B</h>
  <h v-if="type==='C'">C</h>
  <h v-else>D</h>
</div>

<!--  1. 导入vue.js  -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>

<script>
  var vm = new Vue({
    el:"#app",
    data:{
      ok: true,
      type: 'A'
    }
  });
</script>
</body>
</html>

5.3、v-for

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

<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.6.14/dist/vue.js"></script>

<script>
  var vm = new Vue({
    el:"#app",
    data:{
        items: [
            {message: "Genius Sue"},
            {message: "Genius"},
        ]
    }
  });
</script>
</body>
</html>

6、vue绑定事件

6.1、v-on

<!DOCTYPE html>
<head xmlns:v-on="http://www.w3.org/1999/xhtml">
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<!-- view层 模板 -->
<div id="app">
    <button v-on:click="sayHello">点击</button>
</div>


<!-- 1. 导入vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
    var vm = new Vue({
        el: "#app",
        data: {
        },
        methods: {//方法必须定义在vue methods对象中
            sayHello: function () {
                alert("hello");
            }
        }
    });
</script>

</body>
</html>

7、vue双向绑定

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

7.1、v-model

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

<div id="app">
    输入的文本:<input type="text" v-model="message">{{message}}
</div>

<!--  1. 导入vue.js  -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
  var vm = new Vue({
    el:"#app",
    data:{
        message: "Genius Sue"
    }
  });
</script>
</body>
</html>
<!DOCTYPE html>
<head xmlns:v-model="http://www.w3.org/1999/xhtml">
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div id="app">
    性别:
    <input type="radio" value="1" name="sex" v-model="Genius"><input type="radio" value="2" name="sex" v-model="Genius"><p>选中了{{Genius}}</p>
</div>

<!-- 1. 导入vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
    var vm = new Vue({
        el: "#app",
        data: {
            "Genius":""
        }
    });
</script>

</body>
</html>

8、vue组件讲解

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

在这里插入图片描述

8.1、Vue.component

1. 使用组件

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

<div id="app">
   <sue>6</sue>
</div>

<!--  1. 导入vue.js  -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
    /*定义一个Vue组件component
    注意这里的组件名不能用驼峰命名,只能是小写并且不能空格
    */
    Vue.component("sue",{
        "template": '<li>Hello</li>'
    });

  var vm = new Vue({
    el:"#app",
    data:{

    }
  });
</script>
</body>
</html>

2. 传递 props

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

<div id="app">
    <!--  组件:传递给组件中的值:props  -->
   <sue v-for="item in items" v-bind:Genius="item"></sue>
</div>

<!--  1. 导入vue.js  -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
    //定义一个Vue组件component
    Vue.component("sue",{
        props:['Genius'],
        "template": '<li>{{Genius}}</li>'
    });

  var vm = new Vue({
    el:"#app",
    data:{
        items:["Java","Linux","前端"]
    }
  });
</script>
</body>
</html>

9、Axios异步通讯

Axios 是一个基于 promise 网络请求库,作用于node.js 和浏览器中。 它是 isomorphic 的(即同一套代码可以运行在浏览器和node.js中)。在服务端它使用原生 node.js http 模块, 而在客户端 (浏览端) 则使用 XMLHttpRequests。

特性

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

新建一个文件data.json

{
  "name": "狂神说Java",
  "url": "https://www.baidu.com",
  "page": 1,
  "isNonProfit": true,
  "address": {
    "street": "含光门",
    "city": "陕西西安",
    "country": "中国"
  },
  "links": [
    {
      "name": "bilibili",
      "url": "https://space.bilibili.com/95256449"
    },
    {
      "name": "狂神说Java",
      "url": "https://blog.kuangstudy.com"
    },
    {
      "name": "百度",
      "url": "https://www.baidu.com/"
    }
  ]
}

新建一个html

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

<!--  cloak:解决闪烁问题  -->
    <style>
        /*属性选择器*/
        [v-cloak]{
            display: none;
        }
    </style>

</head>
<body>

<div id="vue" v-cloak>
    <div>{{info.name}}</div>
    <div>{{info.address.street}}</div>
    <div>{{info.address.city}}</div>
    <div>{{info.address.country}}</div>
    <a v-bind:href="info.url">点我</a>
</div>

<!--  1. 导入vue.js  -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
  var vm = new Vue({
    el:"#vue",
      data(){
        return{
            //请求的返回参数格式,必须和json字符串一样
            info:{
                name: null,
                url: null,
                address: {
                    street: null,
                    city: null,
                    country: null
                }
            }
        }
      },
    mounted(){//钩子函数,链式编程
        axios.get('../data.json').then(response=>(this.info=response.data));
    }
  });
</script>
</body>
</html>

10、计算属性

什么是计算属性?

计算属性的重点突出在属性两个字上(属性是名词),首先它是个属性其次这个属性有计算的能力(计算是动词),这里的计算就是个函数:简单点说,它就是一个能够将计算结果缓存起来的属性(将行为转化成了静态的属性),仅此而已;可以想象为缓存!

10.1、computed

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

<div id="vue">
    <!--  method通过方法()来调用  nowTime()  -->
<!--    <p>NowTime=>{{nowTime()}}</p>-->
    <!--  computed通过属性来调用  nowTime  -->
    <p>NowTime=>{{nowTime}}</p>
</div>

<!--  1. 导入vue.js  -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
  var vm = new Vue({
    el:"#vue",
      data:{
        message: "Genius Sue"
      },
      // methods: {
      //   nowTime: function (){
      //       console.log("methods");
      //       return Date.now();//返回一个时间戳
      //   }
      // },
      computed:{//计算属性:methods和computed中的方法名不能重名,重名后只会调用methods
          nowTime: function (){
              console.log("computed");
              return Date.now();//返回一个时间戳
          }
      }
  });
</script>
</body>
</html>

11、插槽solt

11.1、slot

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

<!-- view层 模板 -->
<div id="app">
    <!-- 老代码 -->
    <!--<p>课程</p>
    <ul>
        <li>java</li>
        <li>linux</li>
    </ul>-->
    <todo>
        <!-- <todo-head slot="todo-head" v-bind:title="ti"></todo-head> -->
        <!-- v-bind可以简写为 -->
        <todo-head slot="todo-head" :title="ti"></todo-head>
        <todo-item slot="todo-item" v-for="it in its" :item="it"></todo-item>
    </todo>
</div>


<!-- 1. 导入vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
    Vue.component("todo", {
        template: '<div>\
                       <slot name="todo-head"></slot>\
                       <ul>\
                           <slot name="todo-item"></slot>\
                       </ul>\
                   </div>'
    });

    Vue.component("todo-head", {
        props: ['title'],
        template: '<p>{{title}}</p>'
    });


    Vue.component("todo-item", {
        props: ['item'],
        template: '<li>{{item}}</li>'
    });
    var vm = new Vue({
        el: "#app",
        data: {
            ti:'必修课程',
            its:['java','linux','spring']
        },
    });
</script>

</body>
</html>

image-20220628180921023

12、自定义事件内容分发

12.1、this.$emit

this.$emit==>子组件向父组件传值

语法:this.$emit(“function”,param); //其中function为父组件定义函数,param为需要传递参数

image-20220630223827933

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

<div id="vue">
    <todo>
        <todo-title slot="todo-title" v-bind:title="title"></todo-title>
        <todo-items slot="todo-items" v-for="(item,index) in todoItems"
                    v-bind:items="item" v-bind:index="index" v-on:remove="removeItem(index)"></todo-items>
    </todo>
</div>
<!--  1. 导入vue.js  -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.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:['items','index'],
        //只能绑定当前组件的方法
        template:
            `<li>{{index}}---{{ items }}   <button v-on:click="remove()">删除</button></li>`,
        methods:{
            remove: function (index){
                //this.#emit 自定义事件分发
                this.$emit('remove',index);
            }
        }
    });

    var vm = new Vue({
        el:"#vue",
        data:{
            title: "Genius Sue",
            todoItems:['Java','Linux','C','C++']
        },
        methods: {
            removeItem: function (index){
                console.log("删除了=>",this.todoItems[index]);
                this.todoItems.splice(index,1);//一次删除一个元素
            }
        }
    });
</script>
</body>
</html>

在这里插入图片描述

13、第一个vue-cli程序

13.1、什么是vue-cli

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

预先定义好的目录结构及基础代码,就好比咱们在创建 Maven 项目时可以选择创建一个骨架项目,这个骨架项目就是脚手架,我们的开发更加的快速;

主要功能:

  • 统一的目录结构
  • 本地调试
  • 热部署
  • 单元测试
  • 集成打包上线

13.2、需要的环境

  • 安装nodejs
  • 安装git

确认nodejs安装成功

  • cmd 下输入 node -v,查看是否能够正确打印出版本号即可!
  • cmd 下输入 npm -v,查看是否能够正确打印出版本号即可!

image-20220704224321833

npm

npm 是JavaScript 世界的包管理工具,并且是Node.js 平台的默认包管理工具。通过npm 可以安装、共享、分发代码,管理项目依赖关系。

安装 Node.js 淘宝镜像加速器(cnpm)

这样子的话,下载会快很多~

# -g 就是全局安装
npm install cnpm -g

# 若安装失败,则将源npm源换成淘宝镜像
# 因为npm安装插件是从国外服务器下载,受网络影响大
npm install --registry=https://registry.npm.taobao.org
# 然后再执行
npm install cnpm -g

安装位置

C:\Users\{管理员}\AppData\Roaming\npm\node_modules

13.3、安装vue-cli

#在命令台输入
cnpm instal1 vue-cli -g
#测试是否安装成功#查看可以基于哪些模板创建vue应用程序,通常我们选择webpack
vue list

在这里插入图片描述

13.4、第一个vue-cli应用程序

  1. 新建一个空白文件夹VUE

  2. 打开cmd命令窗口,然后进去刚才新建的目录

  3. 执行命令

    vue init webpack myvue
    
    1.Project name:项目名称 ,默认回车即可
    2.Project description:项目描述,默认回车即可
    3.Author:作者,如果有配置git的作者,自动会读取。默认回车即可
    4.vue build (Use arrow keys) 有下面两个选择,推荐选择第一个
    > Runtime + Compiler:recommended for most users
    > Runtime-only:about 6KB lighter min+gzip,but templates (or any Vue-specific HTML) are ONLY 
    5.Install vue-router? 是否安装vue的路由插件,选择n不安装(后期需要在手动添加)
    6.Use ESLint to lint your code? 是否用ESLint来限制你的代码错误和风格。选择n不安装(后期需要在手动添加)
    7.setup unit tests? 是否需要安装单元测试工具,选择n不安装(后期需要在手动添加)
    8.Setup e2e tests with Nightwatch? 是否安装e2e来进行用户行为模拟测试,选择n不安装(后期需要在手动添加)
    9.Should we run 'npm install' for you after the project has been created? 有下面三个选择,这里选择最后一个
    > yes,use npm 使用npm
    > yes,use yarn  使用yarn
    > no,I will handle that myself 自己操作
    

在这里插入图片描述

  1. 进入刚才创建的项目myvue,安装并运行

    cd myvue
    npm install
    npm run dev
    

在这里插入图片描述

打开网页:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-usgEfdUg-1663904402069)(C:\Users\Genius Sue\AppData\Roaming\Typora\typora-user-images\image-20220922153300611.png)]

14、webpack学习使用

什么是webpack? – 静态模板打包工具

本质上,webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具。当 webpack 处理应用程序时,它会在内部从一个或多个入口点构建一个 依赖图(dependency graph),然后将你项目中所需的每一个模块组合成一个或多个 bundles,它们均为静态资源,用于展示你的内容。

安装webpack

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

测试安装成功

webpack -v
webpack-cli -v

在这里插入图片描述

案例

  1. 新建一个项目(PS:新增一个文件夹),webpack-study,然后用idea打开

  2. 新增一个目录modules

  3. 在modules下新建hello.js

    exports.sayHi = function () {
        document.write("<h1>Genius Sue</h1>")
    }
    
  4. 在modules下新建main.js

    var hello = require('./hello');
    hello.sayHi();
    
  5. 最外层目录新建webpack.config.js

    module.exports={
        entry:'./modules/main.js',
        output:{
            filename:"./js/bundle.js"
        }
    }
    
  6. 命令窗口中输入webpack

在这里插入图片描述

生成文件

在这里插入图片描述

  1. 最外层目录新建index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    
    <script src="dist/js/bundle.js"></script>
    
    </body>
    </html>
    
  2. 用浏览器打开

在这里插入图片描述

热部署效果(修改了代码,无需执行webpack命令,直接页面刷新即可)

webpack --watch

15、vue-router路由

官方文档:https://router.vuejs.org/zh/guide/#html

安装

npm install vue-router --save-dev
# 上面报错的话,可以尝试降低版本
npm install vue-router@3.5.2 --save-dev

在这里插入图片描述

验证

  1. 打开之前的第一个vue-cli项目 myvue

  2. 清理src/assets/的所有文件,和src/components下的所有文件

  3. 新增一个内容页components/Content.vue

    <template>
    
      <h1>内容页</h1>
      
    </template>
    
    <script>
    export default {
      name: "Content"
    }
    </script>
    
    <style scoped>
    
    </style>
    
    
  4. 新增一个首页components/Main.vue

    <template>
      <h1>首页</h1>
    </template>
    
    <script>
      export default {
        name: "Main"
      }
    </script>
    
    <style scoped>
    
    </style>
    
  5. 新增一个目录src/router,并在这个目录下新增一个配置路由文件index.js

    import Vue from 'vue'
    import VueRouter from 'vue-router'
    import Content from '../components/Content'
    import Main from '../components/Main'
    
    //安装路由
    Vue.use(VueRouter);
    
    //配置导出路由
    export default new VueRouter({
      routes:[
        {
          //路由路径---->页面跳转 @RequestMapping
          path:'/content',
          pathname:'content',
          //跳转的组件
          component:Content
        },
        {
          //路由路径---->页面跳转
          path:'/main',
          pathname:'main',
          //跳转的组件
          component:Main
        }
      ]
    });
    
    
  6. main.js中添加路由

    import Vue from 'vue'
    import App from './App'
    import router from "./router";//自动扫描里面的路由配置
    
    Vue.config.productionTip = false
    
    
    //显示声明使用VueRouter
    // Vue.use(VueRouter);
    
    new Vue({
      el: '#app',
      //配置路由
      router,
      components: { App },
      template: '<App/>'
    })
    
    
  7. App.vue中使用路由

    <template>
      <div id="app">
        <h1>Genius Sue</h1>
        <router-link to="/main">首页</router-link>
        <router-link to="/content">内容页</router-link>
        <!--控制页面展示-->
        <router-view></router-view>
    
      </div>
    </template>
    
    <script>
    import Content from "./components/Content";
    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>
    
    
  8. 命令行运行npm run dev

  9. 打开浏览器验证

在这里插入图片描述

16、vue+elementUI

  1. 创建一个名为hello-vue的工程

    vue init webpack hello-vue
    
  2. 进入工程目录,并安装依赖

    # 进入工程目录
    cd hello-vue
    # 安装vue-routern 报错的都可以尝试用cnpm去安装
    npm install vue-router --save-dev
    # 上面报错的话,可以尝试降低版本
    npm install vue-router@3.5.2 --save-dev
    # 安装element-ui
    npm i element-ui -S
    # 安装依赖
    npm install
    # 安装SASS加载器 可能会报错,可以尝试降低版本
    cnpm install sass-loader node-sass --save-dev
    # 启功测试
    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为该命令的缩写
    
  3. idea 打开创建好的项目,并清理无用的文件,并创建好项目结构,如下图

在这里插入图片描述

  1. 在views下新增Main.vue

    <template>
    
      <h1>首页</h1>
    
    </template>
    
    <script>
    export default {
      name: "main"
    }
    </script>
    
    <style scoped>
    
    </style>
    
  2. 在views下新增Login.vue

    <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: "密码不可为空", trigger: "blur"}
              ]
            },
    
            //对话框显示和隐藏
            dialogVisible: false
          }
        },
        methods: {
          handleClose: function () {
            this.dialogVisible = false;
          },
          onsubmit(formName) {
            //为表单绑定验证功能
            this.$refs[formName].validate((valid) => {
              if (valid) {
                //使用vue-router路由到指定界面,该方式称为编程式导航
                this.$router.push('/main');
              } else {
                this.dialogVisible = true;
                return false;
              }
            });
          }
        }
      }
    </script>
    
    <style 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>
    
  3. 在router下新增index.js

    import Vue from "vue";
    import Router from 'vue-router';
    
    import Main from "../views/Main";
    import Login from "../views/Login";
    
    Vue.use(Router);
    
    export default new Router({
      routes:[
        {
          path:"/login",
          pathname:"login",
          component:Login
        },
        {
          path:"/main",
          pathname:"main",
          component:Main
        }
      ]
    })
    
  4. 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>
    
  5. 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);
    
    new Vue({
      el: '#app',
      router:router,
      render:h=>h(App)//ElementUI
    })
    
  6. 测试npm run dev

在这里插入图片描述

17、嵌套路由

就在上面的项目中继续优化

  1. views目录下新建文件夹user,并在下面创建List.vue 和Profile.vue

    List.vue

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

    Profile.vue

    <template>
    
      <h1>个人信息</h1>
    
    </template>
    
    <script>
    export default {
      name: "UserProfile"
    }
    </script>
    
    <style scoped>
    
    </style>
    
  2. index.js 添加嵌套路由

    import Vue from "vue";
    import Router from 'vue-router';
    
    import Main from "../views/Main";
    import Login from "../views/Login";
    import List from "../views/user/List";
    import Profile from "../views/user/Profile";
    
    Vue.use(Router);
    
    export default new Router({
      routes:[
        {
          path:"/Login",
          component:Login
        },
        {
          path:"/Main",
          component:Main,
          children:[
            {path:"/user/Profile",component:Profile},
            {path:"/user/List",component:List},
          ]
        }
      ]
    })
    
    
  3. 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-submenu index="3">
                <template slot="title"><i class="el-icon-caret-right"></i>系统管理</template>
                <el-menu-item-group>
                  <el-menu-item index="3-1">用户设置</el-menu-item>
                  <el-menu-item index="3-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>
    .el-header {
      background-color: #0fa9e5;
      color: #333;
      line-height: 60px;
    }
    .el-aside {
      color: #333;
    }
    </style>
    
  4. 刷新网页

在这里插入图片描述

18、参数传递及重定向

18.1、参数传递

在上面的demo中继续改造,怎么传递参数呢?

  1. 修改Main.vue

    <el-menu-item index="1-1">
                    <!--插入的地方-->
                    <!--name传组件名,params传递参数,需要v-bind绑定参数 name属性的值需要和路由name保持一致-->
                    <router-link v-bind:to="{name:'UserProfile',params:{id:1}}" >个人信息</router-link>
    </el-menu-item>
    
  2. 修改路由配置index.js

    {
          path:"/Main",
          component:Main,
          children:[
            {path:"/user/Profile/id",name:'UserProfile',component:Profile},
            {path:"/user/List",name:'UserList',component:List},
          ]
    }
    
  3. 修改Profile.vue

    <template>
    
      <!-- 注意这里所有元素必须在根节点下,这里根节点就是div -->
      <div>
        <h1>个人信息</h1>
        <!-- 注意这里的route不要写错了 -->
        {{$route.params.id}}
      </div>
    
    </template>
    
    <script>
    export default {
      name: "UserProfile"
    }
    </script>
    
    <style scoped>
    
    </style>
    

上面的基础上再优化一下,用props减少耦合

  1. 修改路由配置props:true

     {
          path:"/Main",
          component:Main,
          children:[
            {path:"/user/Profile/id",name:'UserProfile',component:Profile,props:true},
            {path:"/user/List",name:'UserList',component:List},
          ]
    }
    
  2. 修改Profile.vue

    <template>
    
      <!-- 注意这里所有元素必须在根节点下,这里根节点就是div -->
      <div>
        <h1>个人信息</h1>
        {{id}}
      </div>
    
    </template>
    
    <script>
    export default {
      props:['id'],
      name: "UserProfile"
    }
    </script>
    
    <style scoped>
    
    </style>
    
  3. 验证同上

  4. 修改Login.vue 跳转主页面的时候带上用户名

    onsubmit(formName) {
    //为表单绑定验证功能
    this.$refs[formName].validate((valid) => {
    if (valid) {
    //使用vue-router路由到指定界面,该方式称为编程式导航
    this.$router.push('/main/'+this.form.username);
    } else {
    this.dialogVisible = true;
    return false;
    }
    });
    }
    
  5. 修改路由配置index.js

    {
          path:"/Main/:name",
          props:true,
          component:Main,
          children:[
            {path:"/user/Profile/id",name:'UserProfile',component:Profile,props:true},
            {path:"/user/List",name:'UserList',component:List},
          ]
    },
    
  6. 修改Main.vue

    <el-header style="text-align: right; font-size: 12px">
        <span>{{name}}</span>
        <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>
    
  7. 验证

    image-20220709112341289

18.2、重定向

  1. 修改index.js redirect

    {
          path:'/goHome',
          redirect:'/main'
    },
    
  2. 修改Main.vue

              <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传递参数,需要v-bind绑定参数 name属性的值需要和路由name保持一致-->
                    <router-link v-bind:to="{name:'UserProfile',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 index="1-3">
                    <!--插入的地方-->
                    <router-link to="/goHome">回到首页</router-link>
                  </el-menu-item>
                </el-menu-item-group>
              </el-submenu>
    
  3. 验证

    image-20220709105431950

19、404和路由钩子

19.1、404

地址输入了一个不存在的,怎么办?另外地址中的#怎么可以不显示?

  1. 创建一个views/NotFound.vue

    <template>
      <div>
        <h1>404,你的页面走丢了</h1>
      </div>
    </template>
    
    <script>
    export default {
      name: "NoFound"
    }
    </script>
    
    <style scoped>
    
    </style>
    
  2. 修改index.js

    import Vue from "vue";
    import Router from 'vue-router';
    
    import Main from "../views/Main";
    import Login from "../views/Login";
    import List from "../views/user/List";
    import Profile from "../views/user/Profile";
    import NoFound from "../views/NoFound";
    import Axios from "axios";
    import VueAxios from 'vue-axios'
    
    Vue.use(Router);
    Vue.use(VueAxios, Axios)
    
    export default new Router({
      mode:"history",
      routes:[
        {
          path:"/Login",
          component:Login
        },
        {
          path:"/Main/:name",
          props:true,
          component:Main,
          children:[
            {path:"/user/Profile/id",name:'UserProfile',component:Profile,props:true},
            {path:"/user/List",name:'UserList',component:List},
          ]
        },
        {
          path:'/goHome',
          redirect:'/main'
        },
        {
          path:'*',
          component:NoFound
        }
      ]
    })
    
  3. 验证

    image-20220709114718621

路由模式:

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

修改路由配置

// ...
export default new VueRouter({
  mode: 'history',
  routes: []
// ...

19.2、钩子

路由导航守卫

  • beforeRouteEnter

    在渲染该组件的对应路由被验证前调用
    不能获取组件实例 `this` !
    因为当守卫执行时,组件实例还没被创建!
    

    beforeRouteEnter 守卫 不能 访问 this,因为守卫在导航确认前被调用,因此即将登场的新组件还没被创建。

    不过,你可以通过传一个回调给 next 来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数:

    beforeRouteEnter (to, from, next) {
      next(vm => {
        // 通过 `vm` 访问组件实例
      })
    }
    
  • beforeRouteUpdate

    在当前路由改变,但是该组件被复用时调用
    举例来说,对于一个带有动态参数的路径 `/users/:id`,在 `/users/1` 和 `/users/2` 之间跳转的时候,
    由于会渲染同样的组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    
  • beforeRouteLeave:在离开路由前执行

    在导航离开渲染该组件的对应路由时调用
    与 `beforeRouteUpdate` 一样,它可以访问组件实例 `this`
    
  1. Profile.vue中使用钩子函数

    <template>
    
      <!-- 注意这里所有元素必须在根节点下,这里根节点就是div -->
      <div>
        <h1>个人信息</h1>
        {{id}}
      </div>
    
    </template>
    
    <script>
    export default {
      props:['id'],
      name: "UserProfile",
      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);
          });
        }
      }
    }
    </script>
    
    <style scoped>
    
    </style>
    
    钩子函数参数说明
    to: 路由将要跳转的路径信息
    from:路径跳转前的路径信息
    next:路由的控制参数
    - next():跳入下一个页面
    - next('/path'):改变路由的跳转方向,使其跳到另一个路由
    - next(false):返回原来的页面
    - next(vm => {}):仅在beforeRouteEnter中也可用,vm是组件实例
    
  2. 安装axios、vue-axios

    npm install axios vue-axios --save
    
  3. index.js导入axios并使用

    import Vue from "vue";
    import Router from 'vue-router';
    
    import Main from "../views/Main";
    import Login from "../views/Login";
    import List from "../views/user/List";
    import Profile from "../views/user/Profile";
    import NoFound from "../views/NoFound";
    import Axios from "axios";
    import VueAxios from 'vue-axios'
    
    Vue.use(Router);
    Vue.use(VueAxios, Axios)
    
    export default new Router({
      mode:"history",
      routes:[
        {
          path:"/Login",
          component:Login
        },
        {
          path:"/Main/:name",
          props:true,
          component:Main,
          children:[
            {path:"/user/Profile/id",name:'UserProfile',component:Profile,props:true},
            {path:"/user/List",name:'UserList',component:List},
          ]
        },
        {
          path:'/goHome',
          redirect:'/main'
        },
        {
          path:'*',
          component:NoFound
        }
      ]
    })
    
  4. 准备数据 static下新建目录mock,并创建文件data.json

    {
      "name": "狂神说Java",
      "url": "https://www.baidu.com",
      "page": 1,
      "isNonProfit": true,
      "address": {
        "street": "含光门",
        "city": "陕西西安",
        "country": "中国"
      },
      "links": [
        {
          "name": "bilibili",
          "url": "https://space.bilibili.com/95256449"
        },
        {
          "name": "狂神说Java",
          "url": "https://blog.kuangstudy.com"
        },
        {
          "name": "百度",
          "url": "https://www.baidu.com/"
        }
      ]
    }
    

    说明: 只有我们的 static 目录下的文件是可以直接被访问到的,所以我们就把静态文件放入该目录下

  5. Profile.vue中的beforeRouteEnter进行异步请求

    <template>
    
      <!-- 注意这里所有元素必须在根节点下,这里根节点就是div -->
      <div>
        <h1>个人信息</h1>
        {{id}}
      </div>
    
    </template>
    
    <script>
    export default {
      props:['id'],
      name: "UserProfile",
      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);
          });
        }
      }
    }
    </script>
    
    <style scoped>
    
    </style>
    
  6. 测试

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Genius-Sue

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

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

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

打赏作者

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

抵扣说明:

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

余额充值