狂神Vue笔记

1. 前端核心分析

1.1 Vue 概述

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

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

1.2 前端三要素

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

Native 原生JS开发
  原生JS开发,也就是让我们按照【ECMAScript】标准的开发方式,简称ES,特点是所有浏览器都支持。截至到当前,ES标准以发布如下版本:

  • ES3
  • ES4(内部,未正式发布)
  • ES5(全浏览器支持)
  • ES6(常用,当前主流版本:webpack打包成为ES5支持)
  • ES7
  • ES8
  • ES9(草案阶段)

区别就是逐步增加新特性。

TypeScript 微软的标准
  TypeScript是一种由微软开发的自由和开源的编程语言。它是JavaScript的一个超集, 而且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程。由安德斯·海尔斯伯格(C#、Delphi、TypeScript之父; .NET创立者) 主导。该语言的特点就是除了具备ES的特性之外还纳入了许多不在标准范围内的新特性,所以会导致很多浏览器不能直接支持TypeScript语法, 需要编译后(编译成JS) 才能被浏览器正确执行。

JavaScript框架

  • jQuery: 大家熟知的JavaScript框架,优点是简化了DOM操作,缺点是DOM操作太频繁,影响前端性能;在前端眼里使用它仅仅是为了兼容IE6、7、8;

  • Angular: Google收购的前端框架,由一群Java程序员开发,其特点是将后台的MVC模式搬到了前端并增加了模块化开发的理念,与微软合作,采用TypeScript语法开发;对后台程序员友好,对前端程序员不太友好;最大的缺点是版本迭代不合理(如: 1代-> 2代,除了名字,基本就是两个东西;截止发表博客时已推出了Angular6)

  • React: Facebook出品,一款高性能的JS前端框架;特点是提出了新概念[虚拟DOM]用于减少真实DOM操作,在内存中模拟DOM操作,有效的提升了前端渲染效率;缺点是使用复杂,因为需要额外学习一门[JSX] 语言;

  • Vue:一款渐进式JavaScript框架,所谓渐进式就是逐步实现新特性的意思,如实现模块化开发、路由、状态管理等新特性。其特点是综合了Angular (模块化)和React (虚拟DOM)的优点;

  • Axios :前端通信框架;因为Vue 的边界很明确,就是为了处理DOM,所以并不具备通信能力,此时就需要额外使用一个通信框架与服务器交互;当然也可以直接选择使用jQuery提供的AJAX通信功能;

前端三大框架:Angular、React、Vue

UI框架
  Ant-Design:阿里巴巴出品,基于React的UI框架
  ElementUI、iview、ice:饿了么出品,基于Vue的UI框架
  BootStrap:Teitter推出的一个用于前端开发的开源工具包
  AmazeUI:又叫“妹子UI”,一款HTML5跨屏前端框架

JavaScript构建工具
  Babel:JS编译工具,主要用于浏览器不支持的ES新特性,比如用于编译TypeScript
  WebPack:模块打包器,主要作用就是打包、压缩、合并及按序加载

1.3 后端技术

前端人员为了方便开发也需要掌握一定的后端技术但我们Java后台人员知道后台知识体系极其庞大复杂,所以为了方便前端人员开发后台应用,就出现了Node JS这样的技术。Node JS的作者已经声称放弃Node JS(说是架构做的不好再加上笨重的node modules,可能让作者不爽了吧)开始开发全新架构的Deno

既然是后端技术,那肯定也需要框架和项目管理工具, Node JS框架及项目管理工具如下:

Express:Node JS框架
Koa:Express简化版
NPM:项目综合管理工具,类似于Maven
YARN:NPM的替代方案,类似于Maven和Gradle的关系

2. MVVM

2.1 什么是MVVM

MVVM (Model-View-ViewModel) 是一种软件架构设计模式,由微软WPF (用于替代WinForm,以前就是用这个技术开发桌面应用程序的)和Silverlight (类似于Java Applet,简单点说就是在浏览器上运行的WPF)的架构师Ken Cooper和Ted Peters 开发,是一种简化用户界面的事件驱动编程方式。由John Gossman (同样也是WPF和Silverlight的架构师)于2005年在他的博客上发表。

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

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

在这里插入图片描述

2.2 为什么要使用MVVM

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

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

2.3 Vue 是 MVVM 模式的实现者

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n9t7FtSN-1595254922262)(D:\我\MyBlog\狂神说 VUE 笔记.assets\image-20200717181433248.png)]

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

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

  • ViewModel : 连接视图和数据的中间件,Vue.js就是MVVM中的ViewModel层的实现者在MVVM架构中,是不允许数据和视图直接通信的,只能通过ViewModel来通信,而ViewModel就是定义了一个Observer观察者。View Model所封装出来的数据模型包括视图的状态和行为两部分, 而Model层的数据模型是只包含状态的。

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

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

至此,我们就明白了,Vue.js 就是一个MVVM的实现者,他的核心就是实现了DOM监听数据绑定

3. 第一个Vue程序

3.1 下载地址

开发版本
  包含完整的警告和调试模式:https://yuejs.org/js/vue.js
  删除了警告, 30.96KBmin+gzip:https://vuejs.org/js/vue.min.js

Vue在线cdn:

<script src=“https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js”></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>

3.2 代码编写

  • 创建一个HTML文件

  • 引入Vue.js

  • 创建一个Vue实例

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <!-- 1.导入vue.js -->
  <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>

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

<script>
  var vm = new Vue({
    el: "#app",
    // model :  数据
    data:{
      message:"hello Vue"
    }
  });
</script>
</body>
</html>

说明:

(1)el: ‘#vue’:绑定元素的ID
  (2)data:{message:‘Hello Vue!’}:数据对象中有一个名为message的属性,并设置了初始值 Hello Vue

4. Vue基本语法

4.1 v-bind

现在数据和DOM已经被建立了关联,所有的东西都是响应式的。我们在控制台操作对象的属性,界面可以实时更新。我们可以使用v-bind来绑定元素属性!你看到的v-bind等被称为指令指令带有前缀v以表示它们是Vue提供的特殊特性。可能你已经猜到了, 它们会在渲染的DOM上应用特殊的响应式行为在这里,该指令的意思是:“将这个元素节点的title特性和Vue实例的message属性保持一致”。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<p>狂神说Java</p>

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

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

4.2 v-if v-else v-if-else

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <title>Title</title>
</head>
<body>
<p>狂神说Java</p>

<!--view层 模板-->
<div id="app">
   <!-- ===三个等号在JS中表示绝对等于(就是数据与类型都要相等)-->
   <h1 v-if="type==='A'">A</h1>
   <h1 v-else-if="type==='B'">B</h1>
   <h1 v-else>C</h1>
</div>
</body>

<!--导入js-->
<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"
       }
   })
</script>
</html>

4.3 v-for

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<p>狂神说Java</p>

<!--view层 模板-->
<div id="app">
    <!--items是数组,item是数组元素迭代的别名-->
    <li v-for="item in items">
        姓名:{{item.name}},年龄:{{item.age}}
    </li>
</div>
</body>

<!--导入js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
    var vm = new Vue({
        el: "#app",
        data: {
            items: [
                {name: "zhangsan", age: 12},
                {name: "lisi", age: 10},
                {name: "wangwu", age: 16}
            ]
        }
    })
</script>
</html>

4.4 v-on 事件绑定

事件有Vue的事件、和前端页面本身的一些事件!我们这里的click是vue的事件, 可以绑定到Vue中的methods中的方法事件!

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<p>狂神说Java</p>

<!--view层 模板-->
<div id="app">
    <button v-on:click="sayHi">Click Me</button>
</div>
</body>

<!--导入js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
    var vm = new Vue({
        el: "#app",
        data: {
            message: "你点我干嘛?"
        },
        methods: {
            //方法必须绑定在Vue的Methods对象中,v-on:事件
            sayHi: (function (event) {
                alert(this.message)
            })
        }
    })
</script>
</html>

4.5 v-model

  1. 什么是双向绑定

Vue.js是一个MVVM框架,即数据双向绑定,即当数据发生变化的时候,视图也就发生变化,当视图发生变化的时候,数据也会跟着同步变化。这也算是Vue.js的精髓之处了。

值得注意的是,我们所说的数据双向绑定,一定是对于UI控件来说的,非UI控件不会涉及到数据双向绑定。单向数据绑定是使用状态管理工具的前提。如果我们使用vuex,那么数据流也是单项的,这时就会和双向数据绑定有冲突。

  1. 为什么要实现数据的双向绑定

在Vue.js 中,如果使用vuex ,实际上数据还是单向的,之所以说是数据双向绑定,这是用的UI控件来说,对于我们处理表单,Vue.js的双向数据绑定用起来就特别舒服了。即两者并不互斥,在全局性数据流使用单项,方便跟踪;局部性数据流使用双向,简单易操作。

  1. 在表单中使用双向数据绑定

你可以用v-model指令在表单 <input>、<textarea><select> 元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但v-model本质上不过是语法糖。它负责监听户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。

注意:v-model会忽略所有元素的value、checked、selected特性的初始值而总是将Vue实例的数据作为数据来源,你应该通过JavaScript在组件的data选项中声明。

单行数据

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <!-- 1.导入vue.js -->
  <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>

</head>
<body>
<!-- view 层 模板 -->
  <div id="app">
    输入的文本:<input name="txt" v-model="message" type="text">{{message}}    
  </div>


<script>
  var vm =  new Vue({
    el: "#app",
    data: {
      message: '123'
    },
    methods: { //方法必须定义在Vue 的Metgods对象中,v-on:事件
     
    }
  });
</script>
</body>
</html>

image-20230412101247929

多行数据

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <!-- 1.导入vue.js -->
  <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>

</head>
<body>
<!-- view 层 模板 -->
  <div id="app">
    输入的文本:<textarea v-model="message" name="msg" rows="20" cols="20"></textarea>
    {{message}}    
  </div>


<script>
  var vm =  new Vue({
    el: "#app",
    data: {
      message: '123'
    },
    methods: { //方法必须定义在Vue 的Metgods对象中,v-on:事件
     
    }
  });
</script>
</body>
</html>

image-20230412101305528

单选

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <!-- 1.导入vue.js -->
  <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>

</head>
<body>
<!-- view 层 模板 -->
  <div id="app">
    <input type="radio" name="sex" value="男" v-model="xy">男
    <input type="radio" name="sex" value="女" v-model="xy">女
    <p>选中了谁:{{xy}}</p>
  </div>


<script>
  var vm =  new Vue({
    el: "#app",
    data: {
      message: '123',
      xy: ''
    },
    methods: { //方法必须定义在Vue 的Metgods对象中,v-on:事件
     
    }
  });
</script>
</body>
</html>

image-20230412101329775

复选

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

<div id="app">
    多复选框:
    <input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
    &nbsp;&nbsp;
    <label for="jack">Jack1号</label>
    <input type="checkbox" id="join" value="Join" v-model="checkedNames">
    &nbsp;&nbsp;
    <label for="join">Jack2号</label>
    <input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
    &nbsp;&nbsp;
    <label for="mike">Mike</label>
    <span>选中的值:{{checkedNames}}</span>
</div>

<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",
        data:{
            checkedNames:[]
        }
    });
</script>
</body>
</html>

在这里插入图片描述

下拉选择

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<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="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script type="text/javascript">
    var vm = new Vue({
        el:"#app",
        data:{
            pan:"A"
        }
    });
</script>
</body>
</html>


image-20230412101552466

注意:v-model表达式的初始值未能匹配任何选项,元系将被渲染为“未选中”状态。 在iOS中, 这会使用户无法选择第一个选项,因为这样的情况下,iOS不会触发change事件。因此,更推荐像上面这样提供一个值为空的禁用选项

5. Vue组件

组件是可复用的Vue实例,说白了就是一组可以重复使用的模板,跟JSTL的自定义标签、Thymeleaf的th:fragment 等框架有着异曲同工之妙。通常一个应用会以一棵嵌套的组件树的形式来组织

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oSJ7c1GT-1595254922264)(D:\我\MyBlog\狂神说 VUE 笔记.assets\image-20200718095216872.png)]

例如,你可能会有页头侧边栏内容区等组件,每个组件又包含了其它的像导航链接、博文之类的组件。

5.1 第一个Vue组件

注意:在实际开发中,我们并不会用以下方式开发组件,而是采用vue-cli创建,vue模板文件的方式开发,以下方法只是为了让大家理解什么是组件, 使用Vue.component()方法注册组件,格式如下:

<div id="app">
  <xy></xy>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script type="text/javascript">
    //先注册组件
    Vue.component("xy",{
        
        template:'<li>Hello Vue</li>'

    });

    var vm = new Vue({
        el:"#app",
    });
</script>

说明:

  • Vue.component():注册组件
  • pan:自定义组件的名字
  • template:组件的模板

5.2 使用props属性传递参数

像上面那样用组件没有任何意义,所以我们是需要传递参数到组件的,此时就需要使用props属性了!
注意:默认规则下props属性里的值不能为大写

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <!-- 组件:传递给组件中的值;props -->
    <xy v-for="item in items" v-bind:qin="item"></xy>
    
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script type="text/javascript">
    //定义Vue组件
    Vue.component("xy",{
        props: ['qin'],
        template: '<li>{{qin}}</li>'

    });

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

说明:

  • v-for="item in items":遍历Vue实例中定义的名为items的数组,并创建同等数量的组件

  • v-bind:qin="item":将遍历的item项绑定到组件中props定义名为item属性上;= 号左边的qin为props定义的属性名,右边的为item in items 中遍历的item项的值

6. Axios异步通信

6.1 什么是Axios

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

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

GitHub:https://github.com/axios/axios

中文文档:http://www.axios-js.com/

6.2 为什么要使用Axios

由于Vue.js是一个视图层框架且作者(尤雨溪) 严格准守SoC (关注度分离原则),所以Vue.js并不包含Ajax的通信功能,为了解决通信问题,作者单独开发了一个名为vue-resource的插件,不过在进入2.0 版本以后停止了对该插件的维护并推荐了Axios 框架。少用jQuery,因为它操作Dom太频繁 !

6.3 第一个Axios应用程序

咱们开发的接口大部分都是采用JSON格式, 可以先在项目里模拟一段JSON数据, 数据内容如下:创建一个名为data.json的文件并填入上面的内容, 放在项目的根目录下。

模拟Json数据:

{
  "name": "闲言博客",
  "url": "https://blog.csdn.net/qq_42025798",
  "page": 1,
  "isNonProfit": true,
  "address": {
    "street": "含光门",
    "city": "陕西西安",
    "country": "中国"
  },
  "links": [
    {
      "name": "bilibili",
      "url": "https://space.bilibili.com/95256449"
    },
    {
      "name": "闲言杂货簿",
      "url": "https://blog.csdn.net/qq_42025798"
    },
    {
      "name": "闲言小店",
      "url": "https://blog.csdn.net/qq_42025798"
    }
  ]
}

测试代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <div>{{info.name}}</div>
    <div>{{info.address.street}}</div>
    <a v-bind:href="info.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 type="text/javascript">
   
    var vm = new Vue({
        el:"#app",
        data(){
            return{
                //请求的返回参数格式,必须和JSON字符串一样
            info: {
                name: null,
                url: null,
                address: {
                    street: null,
                    city: null,
                    country: null
                }
            }
            }
        },
        mounted(){
           //勾子函数 链式编程 ES6新特性
           axios.get('data.json').then(response =>(this.info = response.data));
       } 
    });
</script>
</body>
</html>

image-20230412151853129

说明:

  • 在这里使用了v-bind将a:href的属性值与Vue实例中的数据进行绑定
  • 使用axios框架的get方法请求AJAX并自动将数据封装进了Vue实例的数据对象中
  • 我们在data中的数据结构必须和Ajax响应回来的数据格式匹配!
{
  "name": "weg",
  "age": "18",
  "sex": "男",
  "url":"https://www.baidu.com",
  "address": {
    "street": "文苑路",
    "city": "南京",
    "country": "中国"
  },
  "links": [
    {
      "name": "bilibili",
      "url": "https://www.bilibili.com"
    },
    {
      "name": "baidu",
      "url": "https://www.baidu.com"
    },
    {
      "name": "cqh video",
      "url": "https://www.4399.com"
    }
  ]
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--view层 模板-->
<div id="vue">
    <div>{{info.name}}</div>
    <a v-bind:href="info.url">点我进入</a>
</div>
</body>

<!--1.导入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--导入axios-->
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.19.2/axios.min.js"></script>
<script>

    var vm = new Vue({
        el: "#vue",
        data: {
            items: ['Java','Python','Php']
        },
        //data:vm的属性
        //data():vm方法
        data(){
            return{
                //请求的返回参数,必须和json字符串一样
               info:{
                   name: null,
                   age: null,
                   sex: null,
                   url: null,
                   address: {
                       street: null,
                       city: null,
                       country: null
                   }
               }
            }
        },
        //钩子函数,链式编程,ES6新特性
        mounted(){
            axios.get("../data.json").then(res => (this.info=res.data))
        }
    })
</script>
</html>

7. Vue的生命周期

官方文档:https://cn.vuejs.org/v2/guide/instance.html

  • Vue实例有一个完整的生命周期,也就是从开始创建初使化数据、编译模板、挂载DOM、渲染一更新一渲染、卸载等一系列过程,我们称这是Vue的生命周期。通俗说就是Vue实例从创建到销毁的过程,就是生命周期。

  • 在Vue的整个生命周期中,它提供了一系列的事件,可以让我们在事件触发时注册JS方法,可以让我们用自己注册的JS方法控制整个大局,在这些事件响应方法中的this直接指向的是Vue的实例。
    在这里插入图片描述

8. Vue计算属性

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

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

<!--view层 模板-->
<div id="app">
    <div>currentTime1: {{currentTime1()}}</div>
    <div>currentTime2: {{currentTime2}}</div>
</div>
</body>

<!--导入js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
    var vm = new Vue({
        el: "#app",
        data: {
            message: "hello,world!"
        },
        methods: {
            currentTime1: function () {
                return Date.now(); // 返回一个时间戳
            }
        },
        computed: {
            //计算属性:methods,computed 方法名不能重名,重名字后,只会调用methods的方法
            currentTime2: function () {
                this.message;
                // 返回一个时间戳
                return Date.now();
            }
        }
    })
</script>
</html>

image-20230412153350027

注意:methods和computed里的东西不能重名

说明:

  • methods:定义方法, 调用方法使用currentTime1(), 需要带括号
  • computed:定义计算属性, 调用属性使用currentTime2, 不需要带括号:this.message是为了能够让currentTime2观察到数据变化而变化
  • 如果在方法中的值发生了变化,则缓存就会刷新!可以在控制台使用vm.message=”x in yan", 改变下数据的值,再次测试观察效果!

结论:
 调用方法时,每次都需要进行计算,既然有计算过程则必定产生系统开销,那如果这个结果是不经常变化的呢?此时就可以考虑将这个结果缓存起来,采用计算属性可以很方便的做到这一点,计算属性的主要特性就是为了将不经常变化的计算结果进行缓存,以节约我们的系统开销;

9. 内容分发 slot

在Vue.js中我们使用<slot>元素作为承载分发内容的出口,作者称其为插槽,可以应用在组合组件的场景中;

测试
  比如准备制作一个待办事项组件(todo) , 该组件由待办标题(todo-title) 和待办内容(todo-items)组成,但这三个组件又是相互独立的,该如何操作呢?

第一步定义一个待办事项的组件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--view层,模板-->
<div id="app">

</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script type="text/javascript">
    Vue.component('todo',{
        template:'<div>\
                <slot name="todo-title"></slot>\
                <ul>\
                    <slot name="todo-items"></slot>\
                </ul>\
            </div>'
    });
</script>
</body>
</html>

第二步 我们需要让待办事项的标题和值实现动态绑定,怎么做呢?我们可以留一个插槽!

1-将上面的代码留出一个插槽,即slot

    Vue.component('todo',{
        template:'<div>\
                <slot name="todo-title"></slot>\
                <ul>\
                    <slot name="todo-items"></slot>\
                </ul>\
            </div>'
    });

2-定义一个名为todo-title的待办标题组件 和 todo-items的待办内容组件

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

    Vue.component("todo-items",{
        props:["item"],
        template:"<li>{{item}}</li>"
    });

3-实例化Vue并初始化数据

var vm = new Vue({
        el:"#app",
        data:{
            title:"闲言",
            todoItems:['Java','Php','C#']
        }
    });

4-将这些值,通过插槽插入

<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>

说明:我们的todo-titletodo-items组件分别被分发到了todo组件的todo-title和todo-items插槽中

完整代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>
<div id="app">
    <todo>
        <todo-title slot="todo-title" v-bind:name="title"></todo-title>
        <todo-items slot="todo-items" v-for="item in todoItems" v-bind:item="item"></todo-items>
    </todo>
</div>

<!--1.导入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: ['name'],
        template: '<div>{{name}}</div>'
    });
    Vue.component("todo-items", {
        props: ['item'],
        template: '<li>{{item}}</li>'
    });
    var vm = new Vue({
        el: "#app",
        data: {
            //标题
            title: "图书馆系列图书",
            //列表
            todoItems: ['三国演义', '红楼梦', '西游记', '水浒传']
        }
    });
</script>
</body>
</html>

10. 自定义事件内容分发

通过以上代码不难发现,数据项在Vue的实例中,但删除操作要在组件中完成,那么组件如何才能删除Vue实例中的数据呢?此时就涉及到参数传递与事件分发了,Vue为我们提供了自定义事件的功能很好的帮助我们解决了这个问题;

使用this.$emit (‘自定义事件名’,参数)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nYOsg3HY-1595254922312)(D:\我\MyBlog\狂神说 VUE 笔记.assets\image-20200718165535075.png)]

1-在vue的实例中增加了methods对象并定义了一个名为removeItems的方法

    var vm = new Vue({
        el:"#app",
        data:{
            title:"闲言",
            todoItems:['Java','Php','C#']
        },
        methods:{
            removeItems: function(index){
                this.todoItems.splice(index,1);
            }
        }
    });

2-修改todo-items待办内容组件的代码,增加一个删除按钮,并且绑定事件

    Vue.component("todo-items",{
        props:['item','index'],
        //只能绑定绑定当前组件的方法
        template:'<li>{{index}}--{{item}}<button @click="remove">删除</button></li>',
        methods:{
            remove: function(index){
                //this.$emit()自定义事件分发
                this.$emit('remove',index);
            }
        }
    });

3-修改todo-items待办内容组件的HTML代码,增加一个自定义事件,比如叫remove,可以和组件的方法绑定,然后绑定到vue的方法

<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" v-bind:index="index" v-on:remove="removeItems(index)"></todo-items>
    </todo>
</div>

对上一个代码进行修改,实现删除功能

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>
<div id="app">
    <todo>
        <todo-title slot="todo-title" v-bind:name="title"></todo-title>
        <todo-items slot="todo-items" v-for="(item,index) in todoItems" v-bind:item="item"
                    v-bind:index="index" v-on:remove="removeItems(index)"></todo-items>
    </todo>
</div>

<!--1.导入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: ['name'],
        template: '<div>{{name}}</div>'
    });
    Vue.component("todo-items", {
        props: ['item','index'],
        template: '<li>{{index}}---{{item}} <button @click="remove">删除</button></li>',
        methods: {
            remove: function (index) {
                // this.$emit 自定义事件分发
                this.$emit('remove',index)
            }
        }
    });
    let vm = new Vue({
        el: "#app",
        data: {
            //标题
            title: "图书馆系列图书",
            //列表
            todoItems: ['三国演义', '红楼梦', '西游记', '水浒传']
        },
        methods: {
            removeItems: function (index) {
                console.log("删除了"+this.todoItems[index]+"OK");
                this.todoItems.splice(index,1);
            }
        }
    });
</script>
</body>
</html>

11. 第一个vue-cli项目

Vue的开发都是要基于NodeJS,实际开发采用Vue-cli脚手架开发,vue-router路由,vuex做状态管理;Vue UI,界面我们一般使用ElementUI(饿了么出品),或者ICE(阿里巴巴出品)来快速搭建前端项目~~

官网:

https://element.eleme.cn/#/zh-CN

https://ice.work/

11.1 什么是vue-cli

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

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

主要功能:

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

11.2 需要的环境

确认nodejs安装成功:

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

这个npm,就是一个软件包管理工具,就和linux下的apt软件安装差不多!

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

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

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

# 若安装失败,则将源npm源换成淘宝镜像
# 因为npm安装插件是从国外服务器下载,受网络影响大
npm config set registry https://registry.npm.taobao.org

# 然后再执行
npm install cnpm -g

//安装的位置:C:\Users\Administrator\AppData\Roaming\npm

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

安装的过程可能有点慢~,耐心等待!虽然安装了cnpm,但是尽量少用!

11.3 安装vue-cli

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

11.4 第一个 vue-cli 应用程序

  • 创建一个Vue项目,我们随便建立一个空的文件夹在电脑上。

  • 我这里在D盘下新建一个目录D:\Project\vue-study;

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

# 这里的 myvue 是项目名称,可以根据自己的需求起名
vue init webpack myvue

#一路都选择no即可;

在这里插入图片描述

在这里插入图片描述

说明:

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

初始化并运行

cd myvue
npm install

在这里插入图片描述

在这里插入图片描述

完整完成后多了很多依赖

在这里插入图片描述

运行

npm run dev

在这里插入图片描述
访问

http://localhost:8080/

在这里插入图片描述

这就是 Node.js的服务,跟tomcat 差不多。
Node.js它是一个服务,它可以运行一些东西。

12. Webpack

12.1 什么是Webpack

  • 本质上,webpack是一个现代JavaScript应用程序的静态模块打包器(module bundler)。当webpack处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个bundle.
  • Webpack是当下最热门的前端资源模块化管理和打包工具,它可以将许多松散耦合的模块按照依赖和规则打包成符合生产环境部署的前端资源。还可以将按需加载的模块进行代码分离,等到实际需要时再异步加载。通过loader转换,任何形式的资源都可以当做模块,比如CommonsJS、AMD、ES6、 CSS、JSON、CoffeeScript、LESS等;
  • 伴随着移动互联网的大潮,当今越来越多的网站已经从网页模式进化到了WebApp模式。它们运行在现代浏览器里,使用HTML5、CSS3、ES6 等新的技术来开发丰富的功能,网页已经不仅仅是完成浏览器的基本需求; WebApp通常是一个SPA (单页面应用) ,每一个视图通过异步的方式加载,这导致页面初始化和使用过程中会加载越来越多的JS代码,这给前端的开发流程和资源组织带来了巨大挑战。
  • 前端开发和其他开发工作的主要区别,首先是前端基于多语言、多层次的编码和组织工作,其次前端产品的交付是基于浏览器的,这些资源是通过增量加载的方式运行到浏览器端,如何在开发环境组织好这些碎片化的代码和资源,并且保证他们在浏览器端快速、优雅的加载和更新,就需要一个模块化系统,这个理想中的模块化系统是前端工程师多年来一直探索的难题。

12.2 模块化的演进

Script标签

<script src = "module1.js"></script>
<script src = "module2.js"></script>
<script src = "module3.js"></script>

这是最原始的JavaScript文件加载方式,如果把每一个文件看做是一个模块,那么他们的接口通常是暴露在全局作用域下,也就是定义在window对象中,不同模块的调用都是一个作用域。

这种原始的加载方式暴露了一些显而易见的弊端:

  1. 全局作用域下容易造成变量冲突
  2. 文件只能按照<script>的书写顺序进行加载
  3. 开发人员必须主观解决模块和代码库的依赖关系
  4. 在大型项目中各种资源难以管理,长期积累的问题导致代码库混乱不堪

12.3 CommonsJS

服务器端的NodeJS遵循CommonsJS规范,该规范核心思想是允许模块通过require方法来同步加载所需依赖的其它模块,然后通过exports或module.exports来导出需要暴露的接口。

require("module");
require("../module.js");
export.doStuff = function(){};
module.exports = someValue;

优点:

  • 服务器端模块便于重用
  • NPM中已经有超过45万个可以使用的模块包
  • 简单易用

缺点:

同步的模块加载方式不适合在浏览器环境中,同步意味着阻塞加载,浏览器资源是异步加载的不能非阻塞的并行加载多个模块

实现:

  • 服务端的NodeJS
  • Browserify,浏览器端的CommonsJS实现,可以使用NPM的模块,但是编译打包后的文件体积较大
  • modules-webmake,类似Browserify,但不如Browserify灵活
  • wreq,Browserify的前身

12.4 ES6模块

EcmaScript 6标准增加了JavaScript语言层面的模块体系定义。ES 6模块的设计思想, 是尽量静态化, 使编译时就能确定模块的依赖关系, 以及输入和输出的变量。Commons JS和AMD模块,都只能在运行时确定这些东西。

import "jquery"
export function doStuff(){}
module "localModule"{}

优点

  • 容易进行静态分析
  • 面向未来的Ecma Script标准

缺点

  • 原生浏览器端还没有实现该标准
  • 全新的命令,新版的Node JS才支持

12.5 安装Webpack

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

安装:

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

在这里插入图片描述

测试安装成功

webpack -v
webpack-cli -v

在这里插入图片描述

配置

创建 webpack.config.js配置文件

  • entry:入口文件, 指定Web Pack用哪个文件作为项目的入口
  • output:输出, 指定WebPack把处理完成的文件放置到指定路径
  • module:模块, 用于处理各种类型的文件
  • plugins:插件, 如:热更新、代码重用等
  • resolve:设置路径指向
  • watch:监听, 用于设置文件改动后直接打包
module.exports = {
	entry:"",
	output:{
		path:"",
		filename:""
	},
	module:{
		loaders:[
			{test:/\.js$/,;\loade:""}
		]
	},
	plugins:{},
	resolve:{},
	watch:true
}

直接运行webpack命令打包

12.6 使用Webpack

  1. 先创建一个包 交由idea打开 会生成一个.idea文件 那么就说明该文件就交由idea负责
  2. 在idea中创建modules包,用于放置JS模块等资源文件
  3. 在modules下创建模块文件hello.js,用于编写JS模块相关代码,hello.js 暴露接口,相当于Java中的类
//暴露一个方法
exports.sayHi = function () {
    document.write("<h1>狂神说ES6</h1>>")
}
  1. 在modules下创建一个名为main.js的入口文件,用于打包时设置entry属性require 导入一个模块,就可以调用这个模块中的方法了 , main.js 请求hello.js 调用sayHi()方法
var hello = require("./hello");
hello.sayHi()
  1. 在主目录创建webpack-config.js , webpack-config.js 这个相当于webpack的配置文件

enrty请求main.js的文件

output是输出的位置和名字

module.exports = {
    entry: './modules/main.js',
    output: {
        filename: './js/bundle.js'
    }
}
  1. 在idea命令台输入webpack命令(idea要设置管理员启动)

  2. 完成上述操作之后会在主目录生成一个dist文件 生成的js文件夹路径为/ dist/js/bundle.js

  3. 在主目录创建index.html 导入bundle.js

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="dist/js/bundle.js"></script>
</head>
<body>
</body>
</html>
  1. 运行HTML看效果

  2. 项目结构

image-20230407112307907

webpack就是一个打包工具,打包,从哪个地方选择一个入口,自动帮你把这个入口里面它所需要的所有东西全部通过它的方式打包起来,运行。

13. vue-router路由

Vue Router是Vue.js官方的路由管理器(路径跳转)。它和Vue.js的核心深度集成,让构建单页面应用变得易如反掌。包含的功能有:
  • 嵌套的路由/视图表

  • 模块化的、基于组件的路由配置

  • 路由参数、查询、通配符

  • 基于Vue.js过渡系统的视图过渡效果

  • 细粒度的导航控制

  • 带有自动激活的CSS class的链接

  • HTML5历史模式或hash模式,在IE9中自动降级

  • 自定义的滚动条行为

13.1 安装

  • 基于第一个vue-cli进行测试学习;先查看node_modules中是否存在 vue-router
  • vue-router 是一个插件包,所以我们还是需要用 npm/cnpm 来进行安装的。打开命令行工具,进入你的项目目录,输入下面命令。
npm install vue-router --save-dev
  • 安装完之后去node_modules路径看看是否有vue-router信息 有的话则表明安装成功。

13.2 测试

  • 将之前案例由vue-cli生成的案例用idea打开
  • 先删除没有用的东西,清理不用的东西 assert下的logo图片 component定义的helloworld组件 我们用自己定义的组件
  • components 目录下存放我们自己编写的组件,定义一个Content.vue 的组件

Content.vue:

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

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

<style scoped>

</style>

main.vue组件

<template>
  <h1>主页</h1>
</template>

<script>
export default {

}
</script>

<style>

</style>
  • 安装路由,在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: [
    {
      //路由路径
      path: '/content',
      name: 'content',
      //跳转的组件
      component: Content
    },
    {
      //路由路径
      path: '/main',
      name: 'main',
      //跳转的组件
      component: Main
    }
  ]
})
  • 在main.js中配置路由

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/>'
})

  • 在App.vue中使用路由

App.vue:

<template>
  <div id="app">
    <img src="./assets/logo.png">
    <h1>狂神</h1>
	<!-- link 控制跳转 -->
    <router-link to="/main">首页</router-link>
    <router-link to="/content">内容页</router-link>
      <!-- view 是为了展示template模板 -->
    <router-view></router-view>

  </div>
</template>

<script>

export default {
  name: 'App',
  components: {
  }
}
</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>

  • 启动测试一下 : npm run dev
  • 项目结构图&运行效果图

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

解决“export ‘default‘ (imported as ‘VueRouter‘) was not found in ‘vue-router‘问题

  • 查看package.json vue-router版本号

  • 如果是版本4.0+ 可能会出现上述问题

  • IDEA终端执行 npm i vue-router@3.1.3

14. vue + ElementUI

根据之前创建vue-cli项目一样再来创建一个新项目

  • 创建一个名为 hello-vue 的工程
vue init webpack hello-vue
  • 安装依赖,我们需要安装 vue-routerelement-uisass-loadernode-sass 四个插件
# 进入工程目录
cd hello-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	

Npm命令解释

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

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

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

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

  • 创建成功后用idea打开,并删除净东西 创建views和router文件夹用来存放视图和路由

在源码目录中创建如下结构:

  1. assets:用于存放资源文件
  2. components:用于存放Vue功能组件
  3. views:用于存放Vue视图组件
  4. router:用于存放vue-router配置

在这里插入图片描述

  • 创建首页视图,在views创建Main.vue
<template>
  <h1>首页</h1>
</template>
<script>
    export default {
        name: "Main"
    }
</script>
<style scoped>
</style>

  • 创建登录页视图,在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: {
      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 路由配置文件
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: '/main',
      component: Main
    },
    {
      path: '/login',
      component: Login
    }
  ]
});
  • 在main.js中配置相关

main.js是index.html调用的 所以前面注册的组件要在这里导入

一定不要忘记扫描路由配置并将其用到new Vue中

main.js:

import Vue from 'vue'
import App from './App'
//扫描路由配置
import router from './router'
//导入elementUI
import ElementUI from "element-ui"
//导入element css
import 'element-ui/lib/theme-chalk/index.css'

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

new Vue({
  el: '#app',
  router,
  render: h => h(App),//ElementUI规定这样使用
})
  • 在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>
  • 测试运行

npm run dev

在这里插入图片描述

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

15. Element UI图形化创建

Element UI 是一套基于 Vue 的桌面端组件库,封装好了很多常用的 UI 组件,开发者可以使用 ElementUI 快速搭建一个网站。

官网:https://element.eleme.cn/

官网中有各个组件使用的详细教程,非常全面,楠哥写这篇教程的目的是帮助大家快速上手 Element UI 的使用,大家在实际开发中可以结合官网文档来完成具体业务代码的开发。

15.1 Element UI 安装

要使用 Element UI,首先确保你的电脑上已经成功安装了 Vue,这里不再介绍 Vue 的安装步骤,没有安装 Vue 的小伙伴可以自行查找教程进行安装。

1、创建 Vue 工程,命令如下。

vue ui

2、选择“创建”,设置工程存放路径,点击下方的“在此创建新项目”按钮。

1f861c61c9b5f4b456d2afd127b0e861.png

3、输入工程名,点击下方的“下一步”按钮。

30223ff3ece2c83292b58cced1c4a4b2.png

4、选择“手动配置项目”,点击“下一步”按钮。

4f907e338b5dd00566a2c88ed3a4e883.png

5、打开 Router、Vuex 选项,关闭 Linter / Formatter 选项,点击“下一步”按钮。

93b141de9776fb6e07b67c4544b37f8c.png

6、打开 Use history mode for router 选项,点击“下一步”按钮。

d0e3a3dc8eb5cfe77debe901b213e67b.png

7、点击“创建项目,不保存预设”,然后耐心等待,创建完成之后会跳转到主页面。

f34fb17f7ae4fa37e0ba87c9526135d5.png

8、点击“添加插件”按钮。

7f1a621c39b7908d57f9f1f3211835e0.png

9、在搜索框输入“element”。

ecd54ad35f17782102f28f4ce639dd14.png

10、选中第一个,点击“安装 vue-cli-plugin-element”,耐心等待即可。

71ec2fb0b3dd304638d12a7083e72dd9.png

11、打开项目,在 App.vue 中添加如下代码。

默认按钮

运行项目,如果能看到如下效果图,则说明 Element UI 已安装成功。

image-20230305172616427

以上就是 Element UI 安装的全部步骤,下一篇教程楠哥将带领大家正式开始学习 Element UI 具体组件的使用,如果你觉得这篇教程对你有帮助,就帮楠哥点个赞吧,我们下期教程再见。

16. 路由嵌套

嵌套路由又称子路由,在实际应用中,通常由多层嵌套的组件组合而成。同样地,URL中各段动态路径也按某种结构对应嵌套的各层组件,例如:

在这里插入图片描述

16.1 实例

  1. 创建用户信息组件,在 views/user 目录下创建一个名为 Profile.vue 的视图组件;

Profile.vue

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

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

List.vue

<template>
  <h1>用户列表</h1>
</template>
<script>
  export default {
    name: "UserList"
  }
</script>
<style scoped>
</style>
  1. 修改首页视图,我们修改 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>
  1. 配置嵌套路由修改 router 目录下的 index.js 路由配置文件,使用children放入main中写入子模块,代码如下

index.js

import Vue from "vue";
import Router 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(Router);

export default new Router({
  routes: [
    {
      path: '/main',
      component: Main,
      //路由嵌套
      children: [
        {path: '/user/profile',component: UserProfile},
        {path: '/user/list',component: UserList}
      ]
    },
    {
      path: '/login',
      component: Login
    }
  ]
});
  1. 路由嵌套效果图

在这里插入图片描述

在这里插入图片描述

17. 参数传递

17.1 实例

  • 前端传递参数

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

<!--name:传组件名 params:传递参数,需要绑定对象:v-bind-->
<router-link v-bind:to="{name: 'UserProfile', params: {id: 1}}">个人信息</router-link>
  • 修改路由配置,增加props:true属性

主要是router下的index.js中的 path 属性中增加了 :id 这样的占位符

{
  path: '/user/profile/:id',
  name: 'UserProfile',
  component: UserProfile,
  props:true
}
  • 前端显示

在要展示的组件Profile.vue中接收参数

Profile.vue:

<template>
  <div>
   <!-- 所有的元素,必须不能直接在根节点下(需要用一个div标签套起来) -->
    个人信息
      <!--方法一:通过{{$route.params.xxx}} 直接获取-->
      {{$route.params.id}}
      <!--修改路由配置文件,开启props传递参数,在需要传参的路由中新增以下内容props:true。-->
    {{ id }}
  </div>
</template>
<script>
    export default {
      props: ['id'],
      name: "UserProfile"
    }
</script>
<style scoped>
</style>
export default new Router({
    routes:[
      {
        path: '/main',
        name: 'mian',
        component: Main,//嵌套路由
        children: [
          // 绑定变量id
          {path: '/user/profile/:id',name: 'UserProfile',component: UserProfile,props:true},
          {path: '/user/list',component: UserList}
      ]
      },
      {
        path: '/login',
        name: 'login',
        component: Login,
      }
    ]

});

在这里插入图片描述

18. 组件重定向

重定向的意思大家都明白,但 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>

19. 路由钩子与异步请求

19.1 路由模式与 404

路由模式有两种

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

404界面

  • 创建一个NotFound.vue视图组件
<template>
    <div>
      <h1>404,你的页面走丢了</h1>
    </div>
</template>
<script>
    export default {
        name: "NotFound"
    }
</script>
<style scoped>
</style>
  • 修改路由配置index.js
import NotFound from '../views/NotFound'
{
   path: '*',
   component: NotFound
}

19.2 路由钩子与异步请求

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 是组件实例

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

方法一

  • 安装 Axios
cnpm install -s axios vue-axios
  • main.js引用 Axios
import axios from 'axios'
import VueAxios from 'vue-axios'
Vue.use(VueAxios, axios)

方法二

  • 安装 Axios
npm install axios --save-dev
  • 查看是否安装成功
    package.json 中是否有 axios

image-20230412090651935

  • 在全局中引入axios

main.js 中写入代码
import axios from 'axios' 导入axios
Vue.prototype.$axios = axios 将axios挂载到原型链

image-20230412090749933

  • 在组件中使用

image-20230412090832729

  • 准备数据 : 只有我们的 static 目录下的文件是可以被访问到的,所以我们就把静态文件放入该目录下。数据和之前用的json数据一样 需要的去上述axios例子里
// 静态数据存放的位置
static/mock/data.json
//新版的存放在public目录下才能被访问
  • 在 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)
        })
      }
    }
  }

posted @ 2023-04-13 16:14  白衣卿巷  阅读(183)  评论(0)    收藏  举报