Vue笔记

1、VUE概述

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

  • 核心:数据驱动、组件化;
  • 遵循SoC关注度分离原则,Vue就是纯粹的视图框架,并不包含,比如Ajax之类的通信功能,为了解决通信问题,需要使用Axios框架做异步通信;
  • Vue开发都是基于NodeJS,实际开发中采用vue-cli脚手架开发,vue-router路由、vuex做状态管理;Vue UI界面一般使用ElementUI或者ICE来快速搭建前端项目;

2、前端知识体系

2.1 前端三要素

● HTML (结构) :超文本标记语言(Hyper Text Markup Language) ,决定网页的结构和内容

● CSS (表现) :层叠样式表(Cascading Style sheets) ,设定网页的表现样式。不具备任何语法知识,没有变量和合理的样式处理。

CSS有缺陷,所以引入CSS预处理器:(写代码,输出为css样式

  1. CSS预处理器定义了一种新的语言,其基本思想是,用一种专门的编程语言,为CSS增加了一些编程的特性,将CSS作为目标生成文件,然后开发者就只要使用这种语言进行CSS的编码工作。
  2. 转化成通俗易懂的话来说就是“用一种专门的编程语言,进行Web页面样式设计,再通过编译器转化为正常的CSS文件,以供项目使用”
  3. 常用的CSS预处理器有哪些
    • SASS:基于Ruby,通过服务端处理,功能强大。解析效率高。需要学习Ruby语言,上手难度高于LESS。
    • LESS:基于NodeJS,通过客户端处理,使用简单。功能比SASS简单,解析效率也低于SASS,但在实际开发中足够了,所以我们后台人员如果需要的话,建议使用LESS。

● JavaScript (行为) :是一种弱类型脚本语言,其源代码不需经过编译,而是由浏览器解释运行,用于控制网页的行为

2.2 JavaScript框架

  1. jQuery:大家熟知的JavaScript框架,优点是简化了DOM操作,缺点是DOM操作太频繁,影响前端性能;在前端眼里使用它仅仅是为了兼容IE6、7、8;
  2. Angular:Google收购的前端框架,由一群Java程序员开发,其特点是将后台的MVC模式搬到了前端并增加了模块化开发的理念,与微软合作,采用TypeScript语法开发对后台程序员友好,对前端程序员不太友好;最大的缺点是版本迭代不合理(如: 1代-> 2代,除了名字,基本就是两个东西;截止发表博客时已推出了Angular6)
  3. React: Facebook出品,一款高性能的JS前端框架;
    • 特点是提出了新概念[虚拟DOM:利用内存]用于减少真实DOM操作,在内存中模拟DOM操作,有效的提升了前端渲染效率;
    • 缺点是使用复杂,因为需要额外学习一门[JSX] 语言。
  4. Vue:一款渐进式JavaScript框架,所谓渐进式就是逐步实现新特性的意思,如实现模块化开发、路由、状态管理等新特性。
    • 其特点是综合了Angular (模块化)和React (虚拟DOM)的优点;
  5. Axios :前端通信框架。(SoC关注度分布原则)
    1. 因为Vue 的边界很明确,就是为了处理DOM,所以并不具备通信能力,此时就需要额外使用一个通信框架与服务器交互
    2. 当然也可以直接选择使用jQuery提供的AJAX通信功能;

前端三大框架:AngularReactVue

3、前后端分离

3.1 后端为主的MVC时代

为了降低开发的复杂度, 以后端为出发点, 比如:Struts、Spring MVC等框架的使用, 就是后端的MVC时代;
在这里插入图片描述

  • 优点
    MVC是一个非常好的协作模式, 能够有效降低代码的耦合度从架构上能够让开发者明白代码应该写在哪里。为了让View更纯粹, 还可以使用Thyme leaf、Frree marker等模板引擎, 使模板里无法写入Java代码, 让前后端分工更加清晰。
    缺点
  • 前端开发重度依赖开发环境,开发效率低,这种架构下,前后端协作有两种模式:
    • 第一种是前端写DEMO, 写好后, 让后端去套模板。好处是DEMO可以本地开发, 很高效。不足是还需要后端套模板,有可能套错,套完后还需要前端确定,来回沟通调整的成本比较大;
    • 另一种协作模式是前端负责浏览器端的所有开发和服务器端的View层模板开发。好处是UI相关的代码都是前端去写就好,后端不用太关注,不足就是前端开发重度绑定后端环境,环境成为影响前端开发效率的重要因素。
  • 前后端职责纠缠不清:模板引擎功能强大,依旧可以通过拿到的上下文变量来实现各种业务逻辑。这样,只要前端弱势一点,往往就会被后端要求在模板层写出不少业务代码,还有一个很大的灰色地带是Controller, 页面路由等功能本应该是前端最关注的, 但却是由后端来实现。Controller本身与Model往往也会纠缠不清,看了让人咬牙的业务代码经常会出现在Controller层。这些问题不能全归结于程序员的素养, 否则JSP就够了。
  • 对前端发挥的局限性:性能优化如果只在前端做空间非常有限,于是我们经常需要后端合作,但由于后端框架限制,我们很难使用[Comet】、【Big Pipe】等技术方案来优化性能。

3.2 基于AJAX带来的SPA时代

在这里插入图片描述

优点:

  • 这种模式下, **前后端的分工非常清晰, 前后端的关键协作点是AJAX接口。**看起来是如此美妙, 但回过头来看看的话, 这与JSP时代区别不大。复杂度从服务端的JSP里移到了浏览器的JavaScript,浏览器端变得很复杂。类似Spring MVC, 这个时代开始出现浏览器端的分层架构
    在这里插入图片描述

缺点:

  • 前后端接口的约定:如果后端的接口一塌糊涂,如果后端的业务模型不够稳定,那么前端开发会很痛苦;不少团队也有类似尝试,通过接口规则、接口平台等方式来做。有了和后端一起沉淀的接口规则,还可以用来模拟数据,使得前后端可以在约定接口后实现高效并行开发。
  • 前端开发的复杂度控制:SPA应用大多以功能交互型为主,JavaScript代码过十万行很正常。大量JS代码的组织,与View层的绑定等,都不是容易的事情

3.3 前端为主的MV*时代

大前端时代

  • MVC(同步通信为主):Model、View、Controller
    • 同步会阻塞,异步非阻塞
  • MVP(异步通信为主):Model、View、Presenter
  • MVVM(异步通信为主):Model、View、ViewModel

MVVM 为了降低前端开发复杂度,涌现了大量的前端框架,比如:Angular JSReactVue.jsEmber JS等, 这些框架总的原则是先按类型分层, 比如Templates、Controllers、Models, 然后再在层内做切分,如下图:
在这里插入图片描述

优点

  • 前后端职责很清晰:前端工作在浏览器端,后端工作在服务端。清晰的分工,可以让开发并行,测试数据的模拟不难, 前端可以本地开发。后端则可以专注于业务逻辑的处理, 输出RESTful等接口。
  • 前端开发的复杂度可控:前端代码很重,但合理的分层,让前端代码能各司其职。这一块蛮有意思的,简单如模板特性的选择,就有很多很多讲究。并非越强大越好,限制什么,留下哪些自由,代码应该如何组织,所有这一切设计,得花一本书的厚度去说明。
  • 部署相对独立:可以快速改进产品体验缺点。

缺点:

  • 代码不能复用。比如后端依旧需要对数据做各种校验,校验逻辑无法复用浏览器端的代码。如果可以复用,那么后端的数据校验可以相对简单化。
  • 全异步, 对SEO不利。往往还需要服务端做同步渲染的降级方案。
  • 性能并非最佳,特别是移动互联网环境下。
  • SPA不能满足所有需求, 依旧存在大量多页面应用。URL Design需要后端配合, 前端无法完全掌控。

3.4 NodeJS带来的全栈时代

前端为主的MV*模式解决了很多很多问题, 但如上所述, 依旧存在不少不足之处。随着Node JS的兴起, JavaScript开始有能力运行在服务端。这意味着可以有一种新的研发模式:
在这里插入图片描述

在这种研发模式下,前后端的职责很清晰。对前端来说,两个UI层各司其职:

  • Front-end Ul layer处理浏览器层的展现逻辑。通过CSS渲染样式, 通过JavaScript添加交互功能, HTML的生成也可以放在这层, 具体看应用场景。
  • Back-end Ul layer处理路由、模板、数据获取、Cookie等。通过路由, 前端终于可以自主把控URL Design, 这样无论是单页面应用还是多页面应用, 前端都可以自由调控。后端也终于可以摆脱对展现的强关注,转而可以专心于业务逻辑层的开发。
    通过Node, WebServer层也是JavaScript代码, 这意味着部分代码可前后复用, 需要SEO的场景可以在服务端同步渲染,由于异步请求太多导致的性能问题也可以通过服务端来缓解。前一种模式的不足,通过这种模式几乎都能完美解决掉。
    与JSP模式相比, 全栈模式看起来是一种回归, 也的确是一种向原始开发模式的回归, 不过是一种螺旋上升式的回归。
    基于Node JS的全栈模式, 依旧面临很多挑战:
  • 需要前端对服务端编程有更进一步的认识。比如TCP/IP等网络知识的掌握。
  • Node JS层与Java层的高效通信。Node JS模式下, 都在服务器端, RESTful HTTP通信未必高效, 通过SOAP等方式通信更高效。一切需要在验证中前行。
  • 对部著、运维层面的熟练了解,需要更多知识点和实操经验。

3.5 总结

前后端分离的开发思想主要是基于SoC(关注度分离原则),上述的几种模式,都是让前后端的职责更加清晰,分工更合理高效。

4、第一个Vue程序

4.1 MVVM模式

​ MVVM(Model-View-ViewModel)是一种软件构架模式,由微软WPF和Silverlight,是一种简化用户界面的事件驱动编程方式。由John Gossman于2005年在其博客上发表。

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

  • 该层向上与视图层进行双向数据绑定;

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

  • MVVM已经相当成熟,主要运用但不仅仅在网络应用程序开发中,当下流行的MVVM框架有Vue.js、AngularJS等。

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

  1. 低耦合:视图可以独立于Model变化和修改,一个ViewModel可以绑定到不同的view上,当view变化的时候Model可以不变,当Model变化的时候View也可以不变。
  2. 可复用:可以把一些视图逻辑放在一个ViewModel里,让多个View重用这段视图逻辑。
  3. 独立开发:开发人员专注于业务逻辑和数据的开发(ViewModel),涉及人员可以专注于页面设计。
  4. 可测试:可以针对ViewModel进行测试

组成

Vue是MVVM的实现,其核心是实现了DOM监听和数据绑定。
在这里插入图片描述

  • Model:模型层,这里表示JavaScript;
  • View:视图层,表示DOM(HTML操作的元素);
  • ViewModel:连接视图和数据的中间件,Vue.js就是MVVM中的ViewModel层的实现。

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

  • ViewModel跟前端进行绑定;
  • ViewModel监听Model,Model变化了View也要跟着变化;原来的情况需要刷新前端,但是使用ViewModel后不需要刷新,改变Model后View直接发生变化。
  • ViewModel能够观察到数据的变化,并对视图对应的内容进行更新;
  • ViewModel能够监听到视图的变化,并能够通知数据发生变化。
  • ViewModel所封装出来的数据模型包括视图的状态和行为两部分,而Model层的数据模型只包含状态的。

4.2 Vue程序

1、创建一个empty project

2、导入Vue.js插件

3、编写代码:

  • 绑定标签。一个vue对象绑定一个标签
  • 创建vue对象并放一个数据
  • 在标签中取出数据
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--取出数据 -->
<div id="div01">
    <!--模板 -->
    {{message}}
</div>
    
<!--1. 导入CDN Vue.js-->
<script src="https://lib.baomitu.com/vue/2.6.12/vue.min.js"></script>
<script>
	//创建vue对象并放入数据
    var vm = new Vue({
        el:"#div01",
        //Model层:数据
        data:{
            message:"hello,vue.js"
        }
    });
</script>
</body>
</html>

5、Vue基本语法

5.1 基础语法

v-xxx:表示指令。

1、v-bind:鼠标悬停几秒钟查看此处动态绑定的提示信息,可简写为 :

<span v-bind: title="message">
    显示绑定的信息
</span>
<!-- v-bind:title 将这个元素节点的title特性和Vue实例的message属性保持一致
v-bind <==> {{}} -->

2、判断、循环

判断:

  • v-if
  • v-else-if
  • v-else
<div id="div01">
    <span v-if ="isOk">Yes</span>
    <span v-else>No</span>
</div>
	
    data:{
        isOk: false
    }

循环

  • v-for
<li v-for= "item in items"> {{item.message}} </li>

data: {
	items: [
		message: "A",
		message: "B"
	]
}

3、Vue绑定事件

  • 可以用 v-on 指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码。可简写为@
  • 然而许多事件处理逻辑会更为复杂,所以直接把 JavaScript 代码写在 v-on 指令中是不可行的。因此 v-on 还可以接收一个需要调用的方法名称。
<div id="app">
    <button v-on:click="sayHello">Click Me</button>
</div>

<script>
    var vm = new Vue({
        el: "#app",
        data: {
            message: "Hello, Vue.js"
        },
        methods: {
            sayHello: function (event) {
                //this表示当前对象,即当前的vue对象vm
                alert(this.message)
            }
        }
    });
</script>
  • 事件:https://www.w3school.com.cn/jquery/jquery_ref_events.asp

5.2 Vue的七大对象

  1. el属性:用来指示vue编译器从什么地方开始解析 vue的语法,可以说是一个占位

  2. data属性:用来组织从view中抽象出来的属性,可以说将视图的数据抽象出来存放在data中。

  3. methods属性:方法必须定义在Vue的methods对象中。放置页面中的业务逻辑,js方法一般都放置在methods中

  4. template属性:用来设置模板,会替换页面元素,包括占位符。

  5. render属性:创建真正的Virtual Dom

  6. computed属性:用来计算

  7. watch 属性

    • watch:function(new,old){ }

    • 监听data中数据的变化

    • 两个参数,一个返回新值,一个返回旧值,

5.3 Vue双向绑定

什么是双向数据绑定

​ Vue.js是一个MVVM框架,即数据双向绑定,即当数据发生变化的时候,视图也就发生变化;当视图发生变化的时候,数据也会跟着同步变化。

​ 数据的双向绑定一定是对于UI控件来说的,非UI控件不会涉及到数据双向绑定。单向数据绑定是使用状态管理工具的前提。如果使用vuex,数据流也是单向的,这时候会和双向数据绑定有冲突。

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

​ 可以使用v-model指令在表单<input><textarea>select元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。

  • v-model负责监听用户的输入事件以及更新数据,并对一些极端场景进行特殊处理;
  • v-model会忽略所有表单元素的value、checked、selected特性的初始值而总是将Vue实例的数据作为数据来源。可以通过JavaScript在组件的data选项中声明初始值。
<div id="app">
    <input type="text" v-model="message"/>{{message}}
</div>
<script src="https://lib.baomitu.com/vue/2.6.12/vue.min.js"></script>
<script>
    var vm = new Vue({
        el: "#app",
        data: {
            message: "123"
        }
    });
</script>

5.4 Vue组件

组件是可复用的 Vue 实例,且带有一个名字 。

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

使用Vue.component()方法注册组件,格式如下: Vue.component(tagName, options)

<script type="text/javascript">
    //先注册组件
    //参数1:名称
    //参数2:模板
    Vue.component("my-component-li", {
        //接收参数
        props: 
        templates: '<li>Hello li</li>'
    });
//component不能直接访问vue实例,需要标签进行绑定,然后通过props传递给templates
    var vm = new Vue({
            el: "#app",
            data: {
                message: "123"
            }
        });
  • 注意确保在初始化根实例之前注册组件,即以上顺序是正确的,如果Vue.component()在new Vue()的下面,则是错误的
  • prop 是子组件用来接受父组件传递过来的数据的一个自定义属性。
<div id="app">
    <my-component-name v-for="item in items" v-bind:ts="item"></my-component-name>
    <!--  v-bind:its中的绑定的its与下面创建的组件中的props选项一致,通过props才能将值传递到templates中 -->
</div>

<script src="https://lib.baomitu.com/vue/2.6.12/vue.min.js"></script>
<script>
    //创建一个组件
    Vue.component("myComponentName",{
        props: ['ts'],
        template: '<h3>{{ts}}</h3>'
    });

    var vm =new Vue({
        el: "#app",
        data: {
            items: ["java", "c++", "linux", "vue"]
        }
    });
</script>

5.5 Axios异步属性

1. Axios介绍

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。

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

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

2. Vue的生命周期

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

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

3. Axios程序

  1. 导入axios命名空间(axios cdn)

    <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
    //或者
    <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.js"></script>
    
  2. 开发的接口大部分是采用JSON格式,所以在程序中模拟一段JSON数据;

    {
      "name": "mike",
      "age": 17,
      "hobby": {
        "sport": "basketball",
        "book": "Java编程语言",
        "movie": "《霸王别姬》"
      },
      "brother": [
        {
          "name": "john",
          "age": 19
        },
        {
          "name": "kite",
          "age": 16
        }
      ]
    }
    
  3. 测试

    <body>
        <div id="app">
            <li>{{info.name}}</li>
            <li>{{info.age}}</li>
            <li>{{info.hobby.sport}}</li>
            <li>{{info.hobby.book}}</li>
            <li>{{info.hobby.movie}}</li>
            <a v-bind:href="info.url">click me</a>
        </div>
    
    
        <script src="https://lib.baomitu.com/vue/2.6.12/vue.min.js"></script>
        <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
        <script type="text/javascript">
            var vm =new Vue({
                el: "#app",
    
                data() {
                  return {
                      info: {
                          name: null,
                          age: null,
                          hobby: {
                              sport: null,
                              book: null,
                              movie: null
                          },
                          url: null
                      }
                  }
                },
                //创建一个钩子函数
                mounted() {
                    axios.get('data.json').then(response => (this.info = response.data))
                }
            });
    
        </script>
    </body>
    

    【注意事项】

    • 在这里使用了 v-bind 将 a:href 的属性值与 Vue 实例中的数据info.url进行绑定;
    • 使用 axios 框架的 get 方法请求 AJAX 并自动将数据封装进了 Vue 实例的数据对象中;
    • data.json中的数据结构必须要和Ajax响应回来的数据格式匹配。

解决闪烁问题

v-clock :未加载之前显示白屏

<style>
    [v-clock]{
        display: none;  
    }
</style>

5.6 计算属性

计算是一个函数:能够将计算结果保存缓存起来的属性(将行为转化成静态的属性),即是将不经常变化的计算结果进行缓存,节约系统开销。

计算属性computed和methods方法的区别:

  • methods:定义方法,调用方法使用methodName(),需要带括号;
  • computed:定义计算属性,调用使用computedName,不需要带括号;
  • computed相当于一个缓存,每次调用只需要结果跟上次一样,如果computed中有其它数据,那么在修改数据之后,缓存就会被刷新。
<div id="app">
    methods: <p>{{currentTime1()}}</p>
    computed: <p>{{currentTime2}}</p>
</div>

<!--导入CDN Vue.js-->
<script src="https://lib.baomitu.com/vue/2.6.12/vue.min.js"></script>
<script>
    var vm = new Vue({
        el: "#app",
        data: {
            message: "hello, vue!"
        },
        //声明一个方法
        methods: {
            currentTime1: function () {
                return Date.now();
            }
        },
        //定义一个属性
        computed: {
            currentTime2: function () {
                this.message;
                return Date.now();
            }
        }
    });

</script>

缺点:

  1. 在异步中无法监听数据 ;
  2. 调用computed方法时,每次都需要进行计算,有计算就会产生系统开销。

5.7 插槽slot

在vue.js中使用<slot>元素作为承载分发内容的出口,称为插槽。(复用)

插槽(Slot)是Vue提出来的一个概念,正如名字一样,**插槽用于决定将所携带的内容,插入到指定的某个位置,从而使模板分块,具有模块化的特质和更大的重用性。**插槽显不显示、怎样显示是由父组件来控制的,而插槽在哪里显示就由子组件来进行控制。

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

<script src="https://lib.baomitu.com/vue/2.6.12/vue.min.js"></script>
<script>
    //定义一个插槽slot
    // <slot></slot>  插槽
    Vue.component("firstSlot",{
        template: '<div>\
                      <slot name="slot-title"></slot>\
                   <ul>\
                        <slot name="slot-item"></slot>\
                    </ul>\
                   </div>\
            '
    });

    //向上述插槽中传递数据,一个插槽对应一个component
    Vue.component("slot-title",{
        props: ['title'],
        template: '<div>{{title}}</div>'
    });
    Vue.component("slot-item",{
        props: ['item'],
        template: '<li>{{item}}</li>'
    })
    var vm = new Vue({
        el:"#app",
        //需要向插槽中传递的数据
        data: {
            title: "编程语言",
            items: [
                "Java",
                "Linux",
                "C++"
            ]
        }
    });

</script>

在这里插入图片描述

在这里插入图片描述

5.8 自定义事件内容分发

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

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

var vm = new Vue({
    el: '#app',
    data: {
        title: "课程",
        todoItems: ['狂神说Java', '狂神说Linux', '狂神说前端']
    },
    methods: {
        // 该方法可以被模板中自定义事件触发
        removeTodoItems: function (index) {
            console.log("删除 " + this.todoItems[index] + " 成功");
            // splice() 方法向/从数组中添加/删除项目,然后返回被删除的项目,其中 index 为添加/删除项目的位置,1 表示删除的数量
            this.todoItems.splice(index, 1);
        }
    }
});

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

Vue.component('slot-items', {
    props: ['item', 'index'],
    template: '<li>{{index + 1}}. {{item}}  <button @click="remove_component">删除</button></li>',
    methods: {
        remove_component: function (index) {
            // 这里的 remove 是自定义事件的名称,需要在 HTML 中使用 v-on:remove 的方式指派
            this.$emit('remove', index);
        }
    }
});

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

<!--增加了 v-on:remove="removeTodoItems(index)" 自定义事件,该事件会调用 Vue 实例中定义的名为 removeTodoItems 的方法-->
<todo-items slot="slot-items" v-for="(item, index) in items"
            v-bind:item="item" v-bind:index="index" :key="index"
            v-on:remove="removeTodoItems(index)"></todo-items>

6、Vue

6.1 vue-cli项目

1、什么是vue-cli

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

主要的功能:

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

2、需要的环境

  • Node.js:https://nodejs.org/zh-cn/download/
  • Git:https://git-scm.com/downloads
#查看对应的版本
node -v
v14.15.5
npm -v
6.14.11
#npm是一个软件包管理器

3、解决npm过慢的问题

#1. 安装Node.js淘宝加速器cnpm
npm install cnpm -g

#2. 在每次安装软件包时使用如下语句
npm install --registry=https://registry.npm.taobao.org

4、安装vue-cli

#在命令台输入
cnpm install vue-cli -g
#查看是否安装成功
vue list

5、创建vue-cli程序

  • 创建一个空文件夹

  • 以管理员的身份使用如下命令创建项目

    vue init webpack projectName
    #projectName 是创建的项目名称
    

    【注意】创建的项目名称不能包括大写
    在这里插入图片描述

  • 安创建时一路选择no
    在这里插入图片描述

    • npm install:安装依赖环境
    • npm run dev:启动当前项目
  • 启动项目
    在这里插入图片描述

6.2 Webpack

中文文档:https://webpack.docschina.org/concepts/

本质上,webpack 是一个用于现代 JavaScript 应用程序的_静态模块打包工具_。当 webpack 处理应用程序时,它会在内部构建一个 依赖图(dependency graph),此依赖图对应映射到项目所需的每个模块,并生成一个或多个 bundle

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

1、安装

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

2、测试是否安装成功

webpack -v
webpack-cli -v

3、配置

  • entry:入口文件,指定WebPack用于哪个文件作为项目的入口;
  • output:输出,指定WebPack把处理完成的文件放置到指定路径;
  • module:模块,用于处理各种类型的文件;
  • plugins:插件,如:热部署、代码重用等;
  • resolve:设置路径指向;
  • watch:监听,用于设置文件改动后直接打包。

如何使用:

  1. 创建一个vue-cli项目(创建一个文件夹),然后使用idea打开该项目。

  2. 新建一个modules文件夹,里面存放js文件

    //hello.js中
    /*exports:暴露一个方法*/
    exports.sayHello = function() {
      document.write("<h1>hello</h1>");  
    };
    
    //main.js中:程序的主入口
    /*
        require:接收一个方法
        ./hello:引入的是hello.js
    */
    var hello = require("./hello");
    hello.sayHello();
    
  3. webpack打包 webpack.config.js,然后在控制台中输入webpack打包命令。

    module.exports = {
        entry: './modules/main.js’,
        output: {
    		filename: "./js/bundle.js"
    	}
    };
    
  4. 创建一个html展示页面index.html

    <!--导入刚刚打包的js文件 -->
    <script src="dist/js/bundle.js"></script>
    

6.3 vue-router 路由

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

Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。包含的功能有:

  • 嵌套的路由/视图表
  • 模块化的、基于组件的路由配置
  • 路由参数、查询、通配符
  • 基于 Vue.js 过渡系统的视图过渡效果
  • 细粒度的导航控制
  • 带有自动激活的 CSS class 的链接
  • HTML5 历史模式或 hash 模式,在 IE9 中自动降级
  • 自定义的滚动条行为

1、安装vue-router

npm install vue-router --save-dev

2、导入vue-router

//vue-router位于node_modules下
import VueRouter from 'vue-router'

//需要显示的声明使用VueRouter
Vue.use(VueRouter);

3、测试

  • components:存放我们自定义的组件
    在这里插入图片描述

  • 创建一个Context.vue组件表示内容页面

    <template>
      <div>
        <h2>这是内容页面</h2>
      </div>
    </template>
    
    <script>
        export default {
            name: "Context"
        }
    </script>
    
    <style scoped>
    </style>
    
    • scoped:作用域,表示该style只对当前组件有效
  • 创建一个Main.vue表示首页

    <template>
        <div>
          <h2>这是首页</h2>
        </div>
    </template>
    
    <script>
        export default {
            name: "Main"
        }
    </script>
    
    <style scoped>
    
    </style>
    
  • 安装路由,在src目录下,新建一个文件夹:router,专门存放路由,配置路由index.js,如下

    //导入vue
    import Vue from 'vue'
    //导入路由插件
    import VueRouter from 'vue-router'
    
    //导入自定义的组件。   ../ =>>表示上一级目录
    import Context from '../components/Context'
    import Main from '../components/Main'
    
    //安装路由
    Vue.use(VueRouter);
    //配置路由
    export default new VueRouter({
      routes: [
        {
          //路由路径
          path: '/main',
          name: 'main',
          //跳转到哪个组件
          component: Main
        },
        {
          path: '/context',
          name: 'context',
          component: Context
        }
      ]
    })
    
  • 在main.js中配置路由

    //导入router目录中的路由
    //import router from './router/index'
    //可以不用写index,这条语句会自动扫描index.js中的路由配置
    import router from './router'
    
    Vue.config.productionTip = false
    /* eslint-disable no-new */
    new Vue({
      el: '#app',
      router,
      components: { App },
      template: '<App/>'
    })
    
  • 在App.vue中使用

    <template>
      <div id="app">
        <h2>Vue-router使用</h2>
        <router-link to="main">首页</router-link>
        <router-link to="context">内容页</router-link>
        <!--下面这条语句是展示页面,没有这条语句不会展示 -->
        <router-view></router-view>
      </div>
    </template>
    
  • 启动服务

    npm install  	#安装依赖环境
    npm run dev		#启动当前项目
    #Ctrl+c:终止服务
    

在这里插入图片描述

6.4 vue+elementUI

安装依赖,我们需要安装 vue-routerelement-uisass-loadernode-sass 四个插件

# 安装 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

6.5 路由嵌套

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

  1. 在一个属性中嵌套一个路由children

    export default new Router({
       routes: [
           {
               path: '/main',
               component: Main,
               //嵌套路由
               children: [
                   {path: '/use/profile/:id', component: UserProfile},
                   // :id绑定id
                   {path: '/use/list', component: UserList}
               ]
           }
       ] 
    });
    
  2. 使用路由。在Main.vue中使用

    <router-link to="/user/list">用户列表</router-link>
    <router-link to="/user/profile">个人信息</router-link>
    
    <!--显示 -->
    <el-main>
        <router-view />
    </el-main>
    

6.6 参数传递及重定向

参数传递

方法一: 取代与 $route 的耦合

  1. 配置路由

    routes: [
        {
            path: '/main',
            component: Main,
            //嵌套路由
            children: [
                {
                    path: '/use/list/:id', // :id绑定id
                    name: UserList,
                 	component: UserList
                },
            ]
        }
    ]
    
  2. 对link进行配置。name:'UserList'其中的值为routes中定义的值

    <router-link v-bind:to="{name:'UserList',params:{id: 1}">用户列表</router-link>
    <!-- name传递组件名; params表示传递的参数, 需要对象。使用v-bind绑定 -->
    
  3. 在页面中取出参数(接收响应)

    <!-- <template>
    		<h2>主页</h2>
    		{{ $route.params.id }}
    	</template> 
    <!-- {{ $route.params.id }} 需要嵌套在标签中,不然会报错-->
    <template>
    	<div>
        	<h2>主页</h2>
            {{ $route.params.id }}
        </div>
    </template>
    

方法二: 通过 props 解耦

  • 这样你便可以在任何地方使用该组件,使得该组件更易于重用和测试
<template>
	<h2>用户信息</h2>
	{{ id }}
</template>

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

配置路由

export default new Router({
	routes: [
        {
            path: '/main',
            component: Main,
            //嵌套路由
            children: [
                {
                    path: '/use/list/:id', // :id绑定id
                    name: UserList,
                    component: UserList,
                    props=true
                },
            ]
        }
    ]
});

重定向

重定向也是通过 routes 配置来完成, 从 /a 重定向到 /b

 routes: [
    { path: '/a', redirect: '/b' }
  ]

6.7 404和路由钩子

路由模式

路由模式有两种:

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

vue-router 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。

如果不想要很丑的 hash,我们可以用路由的 history 模式,这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。

const router = new VueRouter({
  mode: 'history',
  routes: [...]
})

当你使用 history 模式时,URL 就像正常的 url,例如 http://yoursite.com/user/id,也好看!

不过这种模式要玩好,还需要后台配置支持。因为我们的应用是个单页客户端应用,如果后台没有正确的配置,当用户在浏览器直接访问 http://oursite.com/user/id 就会返回 404,这就不好看了。

所以呢,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。

路由钩子与异步请求

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

1、在Profile.vue中加入

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

参数说明:

  • to:路由将要跳转的路径信息

  • from:路径跳转前的路径信息

  • next:路由的控制参数

    • next() :跳入下一个页面

    • next(’/path’):改变路由的跳转方向,使其跳到另一个路由

    • next(false):返回原来的页面

    • next((vm)=>{}) :仅在 beforeRouteEnter 中可用,vm 是组件实例

在钩子中使用异步请求

  1. 安装Axios

    cnpm install --save vue-axios
    
  2. main.js中导入Axios,查看官网

    import axios from 'axios'
    import VueAxios from 'vue-axios'
    Vue.use(VueAxios, axios)
    
  3. 准备数据 : 只有我们的 static 目录下的文件是可以被访问到的,所以我们就把静态文件放入该目录下。

    // 静态数据存放的位置
    static/mock/data.json
    
  4. 在 beforeRouteEnter 中进行异步请求Profile.vue:

    <script>
        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)
              })
            }
          }
        }
    </script>
    
  • beforeRouteEnter:位于Profile.vue中,进入该profile页面前执行;
    s

    cnpm install --save vue-axios
    
  1. main.js中导入Axios,查看官网

    import axios from 'axios'
    import VueAxios from 'vue-axios'
    Vue.use(VueAxios, axios)
    
  2. 准备数据 : 只有我们的 static 目录下的文件是可以被访问到的,所以我们就把静态文件放入该目录下。

    // 静态数据存放的位置
    static/mock/data.json
    
  3. 在 beforeRouteEnter 中进行异步请求Profile.vue:

    <script>
        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)
              })
            }
          }
        }
    </script>
    
  • beforeRouteEnter:位于Profile.vue中,进入该profile页面前执行;
  • beforeRouteLeave:离开该profile页面之后执行。

【资料来源】

  1. [B站-狂神说Java]:https://www.bilibili.com/video/BV18E411a7mC
  2. 官方文档:
    • vue:http://www.axios-js.com/zh-cn/docs/vue-axios.html
    • vue-router:https://router.vuejs.org/zh/
    • vue-axios:http://www.axios-js.com/zh-cn/docs/index.html
    • webpack:https://webpack.docschina.org/concepts/
    • Element:https://element.eleme.cn/#/zh-CN
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值