Vue

vue官网:https://cn.vuejs.org/

一、Vue概述

1. Vue简介

 Vue是一个渐进式(真正用到才引用)的JavaScript框架与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。

Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,与现代化的工具以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。

2. SPA介绍

Vue.js属于SPA一员。

英文全称:Single Page Web Application ,SPA。

中文全称:单页Web应用。

整个应用就一个页面,客户端页面通过与服务端的交互动态更新页面中内容。

2.1 优点

符合前后端分离工作模式:单页面应用可以结合Restful,符合前后端分离开发。

良好的用户体验:应用没有页面跳转,全是局部刷新,整体页面更流畅。

减轻服务器端压力:由于都是局部刷新对服务器压力更小。

多平台共享:无论是移动端、电脑端都可以共享服务端接口。

2.2 缺点

首页渲染耗时长首页需要一次加载多个请求,渲染时间可能会比较长。

3. MVVM介绍

MVVM (Model-View-ViewModel)是一种软件架构设计模式,Vue是基于Mvvm设计的前端框架;

MVVM分为M、V、VM:

  • M(Model) 也就是页面中单独数据。

  • V (View)是页面中HTML结构。

  • VM(View-Model) 当V需要调用M中数据时,由VM做中间处理。

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

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

  • 向下与Model层通过接口请求进行数据交互、

Vue 是 MVVM 模式的实现者

  1. m model

    • 数据层 Vue 中 数据层 都放在 data 里面

  2. v view 视图

    • Vue 中 view 即 我们的HTML页面

  3. vm (view-model) 控制器 将数据和视图层建立联系

    • vm 即 Vue 的实例 就是 vm

二、Vue模板语法

Vue.js 使用了基于 HTML 的模板语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。

所有 Vue.js 的模板都是合法的 HTML,所以能被遵循规范的浏览器和 HTML 解析器解析。

在底层的实现上,Vue 将模板编译成虚拟 DOM 渲染函数。

结合响应系统,Vue 能够智能地计算出最少需要重新渲染多少组件,并把 DOM 操作次数减到最少。

1. 基础指令

1.1 Vue插值表达式

{{}}是Vue的模板语法中的插值表达式,可以直接读取vm实例中的数据,并且支持js的运算表达式。

 

复制代码
<div id="app">
    {{ 2*3 + message + '你好 vue'}}
</div>
<script>
    Vue.config.productionTip = false;
    var app = new Vue({
        el: '#app',
        data: {
            message: 'Hello Vue!'
        }
    })
</script>
复制代码

1.2 v-cloak 指令

为防止插值表达式出现闪烁问题,可以使用v-cloak指令解决。

复制代码
    <style>
        /* 定义 v-cloak 的样式,使元素隐藏 
           通过给 <div> 元素添加 v-cloak 属性,并定义对应的 CSS 样式,
           可以确保在 Vue 实例加载完成之前,该元素的内容不会显示在页面上。
        */
        [v-cloak]{
            display: none;
        }
    </style>
</head>
<body>
<!-- 添加 v-cloak 属性 -->
<div id="app" v-cloak>
    {{ 2*3 + message + '你好 vue'}}
</div>
复制代码

1.3 v-text 指令

v-text指令用于将数据填充到标签中,作用于插值表达式类似,但是没有闪动问题;如果数据中有HTML标签会将html标签直接输出。

复制代码
<div id="app">
    <p v-text="age"></p>
</div>
<script>
    Vue.config.productionTip = false;
    var app = new Vue({
        el: '#app',
        data: {
            age: 18
        }
    })
</script>
复制代码

1.4 v-html 指令

用法和v-text 相似,但是它可以将HTML片段填充到标签中。

它与v-text区别在于v-text输出的是纯文本,浏览器不会对其再进行html解析,v-html会将html标签解析后输出。

复制代码
<div id="app">
    <p v-html="name"></p>
</div>
<script>
    Vue.config.productionTip = false;
    var app = new Vue({
        el: '#app',
        data: {
            name: '<b>Arvin</b>'
        }
    })
</script>
复制代码

1.5 v-pre 指令

显示原始信息跳过编译过程,跳过这个元素和它的子元素的编译过程。

复制代码
<div id="app" v-pre>
    <!-- 直接输出{{message}} -->
    {{message}}
    <!-- 不输出 -->
    <p v-text="age"></p>
    <!-- 不输出 -->
    <p v-html="name"></p>
    <!-- 输出 -->
    <p>你好啊</p>
</div>
<script>
    Vue.config.productionTip = false;
    var app = new Vue({
        el: '#app',
        data: {
            message: 'Hello Vue!',
            age: 18,
            name: '<b>Arvin</b>'
        }
    })
</script>
复制代码

1.5 v-once 指令

执行一次性的插值,当数据改变时,插值处的内容不会继续更新。

复制代码
<div id="app">
    <!-- 页面加载后只渲染一次,即使message数据改变也不会重新渲染-->
    <p v-once>{{message}}</p>
</div>
<script>
    Vue.config.productionTip = false;
    var app = new Vue({
        el: '#app',
        data: {
            message: 'Hello Vue!'
        }
    })
</script>
复制代码

2. Vue的双向绑定指令

什么是双向绑定?

  • input中的v-model绑定了message,所以会实时将输入的内容传递给message,message发生改变。

  • message发生改变时,将message的值插入到DOM中,所以DOM会发生响应的改变。

注意:v-model是双向绑定指令,只能使用在 <input>、<select>、<textarea>等表单组件中使用。

3. Vue的事件指令

3.1 v-on 指令

v-on用来绑定事件的,v-on:事件名 可以缩写为 @事件名。注意:事件名去掉on(onclick-->click)。

例如:v-on:click 可以缩写为 @click。

复制代码
<div id="app">
    <!-- 方法名() | 方法名 -->
    <button v-on:click="fun1">点击</button>
    <button @click="fun2">清零</button>
    <p>您点击了 {{count}} 次</p>
</div>
<script>
    Vue.config.productionTip = false;
    var app = new Vue({
        el: '#app',
        data: {
            count: 0
        },
        methods: {
            fun1(){
                ++this.count;
            },
            fun2(){
                if (confirm("是否归零")){
                    this.count = 0;
                }
            }
        }
    })
</script>
复制代码

3.2 v-on 传入参数

  1. @click="方法名" 或 v-on:click="方法名":默认传递事件对象作为参数。

  2. @click="方法名()" 或 v-on:click="方法名()":不会传递事件对象作为参数,若要传递需要写一个名为$event的参数

  3. @click="方法名(参数1, 参数2, $event)" 或 v-on:click="方法名(参数1, 参数2, $event)":传递多个参数,事件对象建议放在最后,事件对象名称必须是$event。

复制代码
<div id="app">
    <button @click="fun1">按钮1</button>
    <button @click="fun2($event,2)">按钮2</button>
    <button @click="fun3(1, $event)">按钮3</button>
</div>
<script>
    Vue.config.productionTip = false;
    var app = new Vue({
        el: '#app',
        data: {
            count: 1
        },
        methods: {
            fun1(e){
                console.log(e);
            },
            fun2(e){
                console.log(e);
            },
            fun3(i, e){
                console.log(i, e);
            }
        }
    })
</script>
复制代码

3.4 事件修饰符

1. stop

@click.stop 或 v-on:click.stop:防止事件冒泡。

事件冒泡是指当一个DOM元素上的事件被触发时,它会先运行该元素的处理程序,然后再逐级向上运行该元素的父元素的处理程序。

复制代码
<div id="app">
    <div @click="fun1"  style="border: 1px solid black">
        <button @click.stop="fun2">按钮</button>
    </div>
</div>
<script>
    Vue.config.productionTip = false;
    var app = new Vue({
        el: '#app',
        data: {
            count: 1
        },
        methods: {
            fun1(){
                console.log("fun1");
            },
            fun2(){
                console.log("fun2");
            }
        }
    })
</script>
复制代码

2. self

@click.self或v-on:click.self 只当事件在该元素本身触发时。

复制代码
<div id="app">
    <div @click.self="fun1" style="border: 1px solid black">
        <button @click="fun2">按钮</button>
    </div>
</div>
<script>
    Vue.config.productionTip = false;
    var app = new Vue({
        el: '#app',
        data: {
            count: 1
        },
        methods: {
            fun1(){
                console.log("fun1");
            },
            fun2(){
                console.log("fun2");
            }
        }
    })
</script>
复制代码

3. prevent

@click.prevent或v-on:click.self阻止事件的默认行为。

例如:超链接跳转,表单submit按钮提交等。

复制代码
<div id="app">
    <a href="http://www.baidu.com" @click.prevent>百度</a>
    <a href="http://www.baidu.com" @click.prevent="fun1">百度</a>
</div>
<script>
    Vue.config.productionTip = false;
    var app = new Vue({
        el: '#app',
        methods: {
            fun1(){
                console.log("fun1");
            }
        }
    })
</script>
复制代码

4. once

@click.once 或v-on:click.once 事件只触发一次。

复制代码
<div id="app">
    <div>
        <button @click.once="fun1">按钮</button>
    </div>
</div>
<script>
    Vue.config.productionTip = false;
    var app = new Vue({
        el: '#app',
        data: {
            count: 1
        },
        methods: {
            fun1(){
                console.log("fun1");
            }
        }
    })
</script>
复制代码

3.5 按键修饰符

在监听键盘事件时,我们经常需要检查详细的按键。Vue 允许为 v-on 在监听键盘事件时添加按键修饰符。
.enter .tab .delete (“删除”和“退格”键) .esc .space .up .down .left .right

.其它按键 https://www.cnblogs.com/LinkinPark/p/5233127.html

复制代码
<!-- keyup键盘抬起,keydown键盘按下 -->
<div id="app">
    <input type="submit" @keyup.enter="fun1">
    <button id="btn" @keyup.right="fun2">按钮</button>
</div>
<script>
    Vue.config.productionTip = false;
    var app = new Vue({
        el: '#app',
        data: {
            count: 0
        },
        methods: {
            fun1(){
                console.log("提交");
            },
            fun2(e) {
                e.srcElement.style.marginLeft = (this.count+=10) +"px";
            }
        }
    })
</script>
复制代码

3.6 系统修饰键

可以用如下修饰符来实现仅在按下相应按键时才触发鼠标或键盘事件的监听器。

  • .ctrl

  • .alt

  • .shift

<!-- Alt + C -->
<input @keyup.alt.67="clear">

<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>

4. Vue 属性绑定指令

4.1 v-bind 基本使用

v-bind 指令被用来响应地更新 HTML 属性。

例如:v-bind:href 可以缩写为 :href;

复制代码
<div id="app">
    <img :src="path">
</div>
<script>
    Vue.config.productionTip = false;
    var app = new Vue({
        el: '#app',
        data: {
            path: '4.png'
        }
    })
</script>
复制代码

4.2 v-bind 绑定对象

给v-bind:class 一个对象,以动态地切换class。

注意:v-bind:class指令可以与普通的class特性共存。

复制代码
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
    <style>
        .a{
            height: 100px;
        }
        .b{
            width: 100px;
        }
    </style>
</head>
<body>
<div id="app">
    <img :src="path" :class="{a:h,b:w}">
</div>
<script>
    Vue.config.productionTip = false;
    var app = new Vue({
        el: '#app',
        data: {
            path: '4.png',
            h: true,
            w: true
        }
    })
</script>
</body>
复制代码

4.3 v-bind 绑定数组

v-bind可以绑定数组,数组元素是data的数据。

复制代码
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
    <style>
        .a{
            height: 100px;
        }
        .b{
            width: 100px;
        }
    </style>
</head>
<body>
<div id="app">
    <img :src="path" :class="[h,w]">
</div>
<script>
    Vue.config.productionTip = false;
    var app = new Vue({
        el: '#app',
        data: {
            path: '4.png',
            h: 'a',
            w: 'b'
        }
    })
</script>
</body>
复制代码

注意:绑定对象和绑定数组的区别

  • 绑定对象的时候 对象的属性 即要渲染的类名 对象的属性值对应的是 data 中的数据。

  • 绑定数组的时候数组里面存的是data 中的数据。

4.4 绑定style

v-bind可以直接绑定style,style的内容可以是对象,可以是数组。

复制代码
<div id="app">
    <span :style="{border:br, fontSize:fz}">span1</span>
    <span :style="[style1, style2]">span2</span>
</div>
<script>
    Vue.config.productionTip = false;
    var app = new Vue({
        el: '#app',
        data: {
            br: '1px solid black',
            fz: "30px",
            style1: {
                color: "red"
            },
            style2:{
                fontSize: '20px'
            }
        }
    })
</script>
复制代码

四、分支结构

1. 分支结构

1.1 v-if

示例1:

复制代码
<div id="app">
    <span v-if="name != null">{{name}}</span>
</div>
<script>
    Vue.config.productionTip = false;
    var app = new Vue({
        el: '#app',
        data: {
            name: "zs"
        }
    })
</script>
复制代码

示例2:

复制代码
<div id="app">
    <span v-if="name == 'zs'">aa</span>
    <span v-else-if="name == 'ls'">bb</span>
    <span v-else>cc</span>
</div>
<script>
    Vue.config.productionTip = false;
    var app = new Vue({
        el: '#app',
        data: {
            name: "ls"
        }
    })
</script>
复制代码

1.2 v-show

v-show 可以判断标签隐藏或显示。

复制代码
<div id="app">
    <button v-show="flag">按钮</button>
</div>
<script>
    Vue.config.productionTip = false;
    var app = new Vue({
        el: '#app',
        data: {
            flag: true
        }
    })
</script>
复制代码

1.3 v-if 与 v-show 的区别

  • v-show本质就是标签display设置为none,控制隐藏

    • v-show只编译一次,后面其实就是控制css,而v-if不停的销毁和创建,故v-show性能更好一点。

  • v-if是动态的向DOM树内添加或者删除DOM元素

    • v-if切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件

2. 循环结构

v-for 可以遍历数组也可以遍历对象。

示例,遍历数组:

复制代码
<div id="app">
    <p :key="str" v-for="(str, i) in strs">
        {{str}}
    </p>
</div>
<script>
    Vue.config.productionTip = false;
    var app = new Vue({
        el: '#app',
        data: {
            strs:[
                "aa","bb","cc"
            ]
        }
    })
</script>
复制代码

v-for="(value,index) in arr"

  • strs:遍历的数组名

  • str:遍历出的每个元素

  • i:遍历出的每个元素索引

:key 的作用:

  • key来给每个节点做一个唯一标识

  • key的作用主要是为了高效的更新虚拟DOM

示例,遍历对象:

复制代码
<div id="app">
    <p :key="i" v-for="(v, k, i) in user">
        {{k + " : " +v}}
    </p>
</div>
<script>
    Vue.config.productionTip = false;
    var app = new Vue({
        el: '#app',
        data: {
            user: {
                id: 1,
                name: '二麻子',
                age: 18
            }
        }
    })
</script>
复制代码

v-for="(v,k,i) in user"

  • user:遍历的对象名

  • v:遍历对象的value

  • k:遍历对象的key

  • i:遍历对象的索引

key 的作用

  • key来给每个节点做一个唯一标识

  • key的作用主要是为了高效的更新虚拟DOM

五、Vue 表单操作

1. 表单基本操作

可以通过v-model双向绑定操作表单

复制代码
<div id="app">
    <form action="http://psjj.top/java">
        <div>
            姓名:<input type="text" id="username" v-model="username"/>
        </div>
        <div>
            性别:
            <label for="male"></label>
            <input type="radio" id="male" v-model="gender" name="gender" value="男"/>
            <label for="female"></label>
            <input type="radio" id="female" v-model="gender" name="gender" value="女"/>
        </div>
        <div>
            爱好:
            <label for="chouyan">抽烟</label>
            <input type="checkbox" id="chouyan" v-model="hobby" name="hobby" value="抽烟" checked/>
            <label for="hejiu">喝酒</label>
            <input type="checkbox" id="hejiu" v-model="hobby" name="hobby" value="喝酒"/>
            <label for="code">写代码</label>
            <input type="checkbox" id="code" v-model="hobby" name="hobby" value="写代码"/>
        </div>
        <div>
            地址:
            <select v-model="address">
                <option value="0">请选择</option>
                <option value="北京">北京</option>
                <option value="上海">上海</option>
                <option value="广州">广州</option>
            </select>
        </div>
        <div>
            个人简介:<textarea v-model="desc"></textarea>
        </div>
        <div>
            <input type="submit" value="提交" @click.prevent='login'>
        </div>
    </form>
</div>
<script>
    Vue.config.productionTip = false;
    var app = new Vue({
        el: "#app",
        data: {
            username: '',
            /* 设置单选框默认值 */
            gender: '',
            /* 设置复选框默认值 */
            hobby: ['抽烟'],
            /* 设置下拉列表默认值 */
            address: 0,
            desc: ''
        },
        methods: {
            login() {
                console.log(this.username);
                console.log(this.gender);
                console.log(this.hobby);
                console.log(this.address);
                console.log(this.desc);
            }
        }
    });
</script>
操作表单
复制代码

2. 表单修饰符

v-model还支持表单修饰符,功能如下:

  • .number 转换为数值。

  • .trim 自动过滤用户输入的首尾空白字符。

  • .lazy 将input事件切换成change事件,在失去焦点 或者 按下回车键时才更新。

六、Vue自定义指令

当内置指令不能满足我们特殊的需求时,Vue允许我们自定义指令;自定义指令分为:

  1. 全局自定义指令。

  2. 局部自定义指令。

1. 全局自定义指令

Vue.directive 可以注册全局指令。

自定义全局指令:

  • inserted:被绑定元素插入父节点时调用。

复制代码
<div id="app">
    <input type="text" v-myfocus>
</div>
<script>
    Vue.config.productionTip = false;
    Vue.directive('myfocus', {
        inserted: function (val) {
            console.log(val);
            /* 元素获得焦点 */
            val.focus();
        }
    });
    var app = new Vue({
        el: "#app"
    });
</script>
</body>
复制代码
  • bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。

复制代码
<div id="app">
    <button v-mycolor="color">按钮</button>
</div>
<script>
    Vue.config.productionTip = false;
    Vue.directive('mycolor', {
        bind: function (val, binding) {
            console.log(val);
            console.log(binding);
            /* 修改背景颜色, binding对象中的value属性为v-mycolor的属性值 */
            val.style.backgroundColor = binding.value;
        }
    });
    var app = new Vue({
        el: "#app",
        data:{
            color: 'green'
        }
    });
</script>
复制代码

注意:使用时要在前面加上 v-

2. 局部自定义指令

  • 局部指令,需要定义在 directives 的选项用法和全局用法一样 。

  • 局部指令只能在当前组件里面使用。

  • 当全局指令和局部指令冲突时局部指令优先级高。

复制代码
<body>
    <div id="app">
        <button v-mycolor="color">按钮</button>
    </div>
</body>
    <script>
        Vue.config.productionTip = false;
        var vm = new Vue({
            el: '#app',
            data:{
               color: 'red'
            },
            directives:{
                mycolor:{
                    bind: function(el,binding){
                        el.style.backgroundColor = binding.value;
                    }
                }
            }
        })
    </script>
复制代码

七、Vue计算属性 监听器 过滤器

1. 计算属性 computed

模板中放入太多的逻辑会让模板过重且难以维护使用计算属性可以让模板更加的简洁。

计算属性是基于它们的响应式依赖进行缓存。

复制代码
<div id="app">
    <!-- 插值表达时中允许直接调用方法。-->
    <!-- 调用methods中的方法时必须为方法名(),()不能省略)  -->
    <p>{{fun1()}}</p>
    <hr>
    <!-- 调用computed中的方法时必须为方法名,不能添加() -->
    <p>{{fun2}}</p>
</div>
<script>
    Vue.config.productionTip = false;
    var app = new Vue({
        el: "#app",
        methods: {
            fun1(){
                return Math.random();
            }
        },
        computed: {
            fun2(){
                return Math.random();
            }
        }
    });
</script>
复制代码

2. 监听器 watch

使用watch来响应数据的变化,一般用于异步或者开销较大的操作。

watch 中的属性 一定是data 中 已经存在的数据。

复制代码
<div id="app">
    用户名:<input type="text" v-model="name">
    <p>
        <span>{{name}}</span>
    </p>
</div>
<script>
    Vue.config.productionTip = false;
    var app = new Vue({
        el: "#app",
        data: {
            name: 'zs'
        },
        watch: {
            name: function (val) {
                console.log(val);
            }
        }
    });
</script>
复制代码

3. 过滤器 filter/filters

  • Vue.js允许自定义过滤器,可被用于一些常见的文本格式化。

  • 过滤器可以用在两个地方:双花括号插值和v-bind表达式。

  • 过滤器应该被添加在JavaScript表达式的尾部,由“管道”符号指示。

  • 过滤器不是真的修改data,而只是改变渲染的结果,并返回过滤后的版本。

  • 全局注册时是filter,没有s的。而局部过滤器是filters,是有s的。

复制代码
<div id="app">
    <p>
        {{name | myfilter1}}
    </p>
    <p>
        {{msg | myfilter2}}
    </p>
</div>
<script>
<!-- 全局过滤器-->
    Vue.filter('myfilter1', function (val) {
        console.log(val);
        return val.toUpperCase();
    });
    var app = new Vue({
        el: "#app",
        data: {
            name: 'zs',
            msg: 'Hello Vue'
        },
<!-- 局部过滤器-->
        filters: {
            myfilter2: function (val) {
                return val.toLowerCase();
            }
        }
    });
</script>
复制代码

过滤器传递参数:

复制代码
<div id="app">
    <p>
        {{name | myfilter1(1)}}
    </p>
    <p>
        {{msg | myfilter2(2)}}
    </p>
</div>
<script>
<!-- val是过滤的data,len是传入的参数-->
    Vue.filter('myfilter1', function (val, len) {
        console.log(val);
        return val.substr(0, len);
    });
    var app = new Vue({
        el: "#app",
        data: {
            name: 'zs',
            msg: 'Hello Vue'
        },
        filters: {
            myfilter2: function (val, len) {
                return val.substr(0, len);
            }
        }
    });
</script>
传递参数
复制代码

八、Vue生命周期

1. 生命周期

每个 Vue 实例在被创建时都要经过一系列的初始化过程 :创建实例,装载模板,渲染模板等等。

Vue 为生命周期中的每个状态都设置了钩子函数(监听函数),每当 Vue 实例处于不同的生命周期时,对应的函数就会被触发调用。

2. 钩子函数

在Vue.js中,钩子函数是一种特殊函数,它们在组件的生命周期中被调用。

这些函数在组件被创建、更新和销毁时执行,可以在这些关键时刻执行特定的任务。

  • beforeCreated:我们在用 Vue 时都要进行实例化,因此,该函数就是在 Vue 实例化时调用,也可以将他理解为初始化函数比较方便一点,在 Vue1.0 时,这个函数的名字就是init。

  • created:在创建实例之后进行调用。

  • beforeMount:页面加载完成,没有渲染。如:此时页面还是{{name}}

  • mounted:我们可以将他理解为原生 js 中的 window.onload=function({.,.}),或许大家也在用 jquery,所以也可以理解为 jquery 中的$(document).ready(function(){….}),它的功能就是: 在 dom 文档渲染完毕之后将要执行的函数, 该函数在 Vue1.0 版本中名字为compiled。 此时页面中的{{name}}已被渲染成张三

  • beforeDestroy: 在实例销毁之前调用,包括解绑事件和清理所有计时器。

  • destroyed: 在实例销毁后调用,此时可以进行一些清理工作。

  • beforeUpdate: 在实例更新之前调用,包括重新计算属性、观察属性和调用子组件的beforeUpdate。
  • updated: 在实例更新完成后调用,此时实例已经重新渲染。

九、Vue 数组内容渲染

在 Vue 中,直接修改数组属性的值无法触发响应式:数组中的数据改了,但是页面内容并没有改变。

这是因为Vue通过对象的引用来检测数组的变化,而不是检测数组的内容。

1. 数组变异方法

数组变异方法是一组用于修改数组中元素的方法。

这些方法可以直接在数组上调用,用于添加、删除或修改数组中的元素。

方法描述
push() 往数组最后面添加一个元素,成功返回当前数组的长度
pop() 删除数组的最后一个元素,成功返回删除元素的值
shift() 删除数组的第一个元素,成功返回删除元素的值
unshift() 往数组最前面添加一个元素,成功返回当前数组的长度
splice() 参数1:想要删除的元素的下标 参数2:删除的元素个数 参数3:删除位置添加的新元素
sort() sort() 使数组按照字符编码默认从小到大排序,成功返回排序后的数组
reverse() reverse() 将数组倒序,成功返回倒序后的数组
复制代码
<div id="app">
    <p>{{strs}}</p>
    <p>
        <button @click="fun1">按钮1</button>
    </p>
</div>
<script>
    let app = new Vue({
        el: "#app",
        data: {
            strs: [
                "bb", "aa", 'cc'
            ]
        },
        methods:{
            fun1(){
                var number = this.strs.push("dd");
                console.log(number);
            }
        }
    });
</script>
复制代码

2. 操作数组

  • 不会改变原数组,返回值为新数组。

  • 回调有三个参数:

    item:遍历的数组内容 

    index:对应的数组索引 

    arr:数组本身

方法描述
forEach() 数组遍历
filter() 过滤数组中元素
some() 当有一个元素满足条件时,some方法返回true,否则返回false
concat() 数组拼接
slice() 数组中元素截取
复制代码
<div id="app">
    <p>{{strs}}</p>
    <p>
        <button @click="fun1">按钮1</button>
        <button @click="fun2">按钮2</button>
    </p>
</div>
<script>
    var app = new Vue({
        el: "#app",
        data: {
            strs: [
                "bb", "aa", 'cc'
            ]
        },
        methods:{
            fun1(){
               var a = this.strs.filter(function (v) {
                   console.log(v);
                   if (v == 'bb' || v == 'cc') return v;
               });
               console.log(a);
            },
            fun2() {
                var b = this.strs.filter(v => {
                    if (v == 'bb' || v == 'cc') return v;
                });
                console.log(b);
            }
        }
    });
</script>
复制代码

十、组件

组件系统是 Vue 的一个重要概念,允许使用小型、独立和可复用的组件构建大型应用。

通常一个应用会以一棵嵌套的组件树的形式来组织。

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

1. 非单文件组件

组件的开发步骤:

1. 定义组件(创建组件)
2. 注册组件(局部组件组要手动注册)
3. 使用组件(写组件标签)

- 组件分为全局组件和局部组件

1.1 全局组件

①创建组件

全局组件创建后会自动注册。

语法格式:

Vue.component('自定义组件名', { 组件内容 })
复制代码
 Vue.component("my-component", {
        //不可以写el,最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器

        //组件中的html代码及数据
        template: '<button @click="fun1">{{name}}点击了{{count}}</button>',
        //避免组件被复用时,数据存在引用关系
        data() {
            return {
                count: 0,
                name: '按钮'
            }
        }
复制代码

命名规范:

  1. 一个单词组成(不推荐:

    • 第一种写法(首字母小写):school

    • 第二种写法(首字母大写):School

  2. 多个单词组成:

    • 第一种写法(kebab-case命名):my-school

    • 第二种写法(CamelCase命名):MySchool (需要Vue脚手架支持)

  3. 注意事项:

    1. 组件名尽可能回避HTML中已有的元素名称,例如:h2、H2都不行。

    2. 当使用 kebab-case (短横线分隔命名) 定义一个组件时,必须在引用时使用 kebab-case,例如 <my-component-name>

    3. 当使用 PascalCase (首字母大写命名) 定义一个组件时,你在引用这个自定义元素时两种命名法都可以使用。也就是说 <my-component-name><MyComponentName> 都是可接受的。尽管如此,直接在 DOM中使用时只有 kebab-case 是有效的,html只能解析 kebab-case(短横线分隔符)。

②使用

全局组件创建后自动注册,所有vue实例都可以使用

1.2 局部组件

  • 使用了全局注册组件意味着即便已经不再使用一个组件了,它仍然会被包含在最终的构建结果中。

  • 局部组件注册后,只用引用了局部组件的vue实例可以用。

①创建组件

语法格式:

const 组件名 = { 组件内容 }
vue对象中使用components属性注册局部组件
复制代码
// 方式一:
    /* 创建局部组件 */
    const MyComponent1 = {
        data () {
            return {
                name: '按钮1'
            }
        },
        template: '<button>{{name}}</button>'
    };

// 方式二:
    /* 创建局部组件 */
    const MyComponent2 = Vue.extend({
        data() {
            return {
                name: '按钮2'
            }
        },
        template: '<button>{{name}}</button>'
    });
复制代码

②注册组件

 const app = new Vue ({
        el: '#app',
        /* 注册局部组件 */
        components: {
            MyComponent1,
            MyComponent2
        }
    });

③使用

只有注册了局部组件的vue实例才能使用该局部组件

1.3 组件的嵌套

复制代码
 //定义student组件
    const student = Vue.extend({
        template: `
                <div>
                    <h2>学生名称:{{name}}</h2>
                    <h2>学生年龄:{{age}}</h2>
                </div>
            `,
    });

    //定义school组件
    const school = Vue.extend({
        template: `
                <div>
                    <h2>学校名称:{{name}}</h2>
                    <h2>学校地址:{{address}}</h2>
                    <student></student>
                </div>
            `,
        /* 注册student组件 */
        components: {
            student
        },
复制代码

2. 单文件组件

2.1 .vue格式文件

.vue文件是Vue.js框架中用于组件开发的核心文件类型。

它是Vue.js框架中的核心文件格式,用于定义网页的结构、样式和行为。

它将组件的结构、样式和行为组织在一个文件中,提供了一种模块化和可维护的开发方式,同时也支持Vue的特性和工具,帮助开发者构建高性能、可扩展的Web应用程序。

一个典型的.vue文件包含三个部分:模板(template)、样式(style)和脚本(script)

2.2 mian.js

以vue2语法为例

复制代码
import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
    el:'#app',
    // 简写形式
    render: h => h(App),
    // 完整形式
    // render(createElement){
    //     return createElement(App)
    // }
})
复制代码

vue.js 与 vue.runtime.xxx.js的区别:

 

  vue.js 是完整版的 Vue,包含:核心功能+模板解析器。

 

  vue.runtime.xxx.js 是运行版的 Vue,只包含核心功能,没有模板解析器。

  因为 vue.runtime.xxx.js 没有模板解析器,所以不能使用 template 配置项,需要使用 render函数接收到的createElement 函数去指定具体内容。

使用vue-cli构建的vue项目使用的就是vue.runtime.xxx.js

十一、组件的操作

1. scoped样式

作用:

  • 让样式在局部生效,防止冲突。

  • scoped样式一般不会在App.vue中使用。

2. props配置项

2.1 介绍

为了提高组件的复用性,在封装 vue 组件时需要遵守如下的原则:

  1. 组件的 DOM 结构、Style 样式要尽量复用。

  2. 组件中要展示的数据,尽量由组件的使用者提供。

为了方便使用者为组件提供要展示的数据,vue 组件提供了 props 的概念。

props 是组件的自定义属性,组件的使用者可以通过 props 把数据传递到子组件内部,供子组件内部进行使用。

由于 props 是单向数据流的,它是只能从父组件传递到子组件的,而子组件是无法更改 props 的值的,只能由父组件来修改。这样就保证了组件的数据传递不会出现混乱和错乱的情况。

2.2 使用

子组件:

添加props选项(多种写法)

复制代码
props: ["mymsg", "mylist"],
        /* 接收的同时对数据进行类型限制 */
props:{
       mymsg: String,
       mylist: Object
     },

/* 接收的同时对数据进行类型限制 + 指定默认值 + 限制必要性 */
props:{
       mymsg:{
           type: String,
           default: "默认值"
         },
       mylist:{
            type: Array,
            equired: true
            }
     }, 
复制代码

父组件:

    <组件名 :mymsg="父组件中的数据" />

3. 自定义事件

由于 props 是单向数据流的,它是只能从父组件传递到子组件的,而子组件是无法更改 props 的值的。

要想通过子组件向父组件传递数据,可以自定义事件

3.1 介绍

组件的自定义事件:

  1. 一种组件间通信的方式,适用于:子组件 与 父组件。

  2. 使用场景:A是父组件,B是子组件,B想给A传数据,那么就要在A中给B绑定自定义事件(事件的回调在A中)。

  • 触发自定义事件:this.$emit('自定义事件名',数据)

3.2 使用

子组件:

复制代码
<template>
    <div class='Demo'>
        <h2>学校名称:{{name}}</h2>
        <h2>学校地址:{{address}}</h2>
        <button @click="send">点击按钮向父组件传递数据</button>
    </div>
</template>

<script>
    /* 创建并导出组件 */
    export default {
        name: 'MySchool',
        data() {
            return {
                name: '北大',
                address: '北京'
            }
        },
        methods: {
            send() {
                /*
                    参数1:驱动自定义事件 getSchoolName 执行
                    参数2:传递的参数
                */
                this.$emit("getSchoolName", this.name);
            }
        }
    }
</script>
复制代码

父组件:

复制代码
<template>
    <!-- 使用组件 -->
    <div>
        <!-- 子组件给父组件传值:借助于自定义事件 getSchoolName -->
        <my-school @getSchoolName="showName"/>
    </div>
</template>

<script>
    /* 导入组件 */
    import MySchool from './components/MySchool.vue'
    /* 创建并导出组件 */
    export default {
        name: 'App',
        /* 父组件中的数据 */
        data() {
            return {
                msg: 'app父组件中的数据',
            }
        },
        methods: {
            showName(name){
                console.log("父组件中数据:", name);
            }
        },
        /* 注册组件 */
        components: {
            MySchool
        }
    }
</script>
复制代码

4. 全局事件总线

全局事件总线是一种可以在任意组件间通信的方式,本质上就是一个对象。

它必须满足以下条件:

 

  • 所有的组件对象都必须能使用它。

 

  • 这个对象必须能够使用$on$emit$off方法去绑定、触发和解绑事件。

①安装全局事件总线(vue2)

复制代码
import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
    el:'#app',
    render: h => h(App),
    beforeCreate() {
        Vue.prototype.$bus = this //安装全局事件总线
    }
})
复制代码

②子组件1(提供数据的组件)

复制代码
<template>
    <div class='Demo'>
        <h2>学校名称:{{name}}</h2>
        <h2>学校地址:{{address}}</h2>
        <button @click="send1">点击按钮向兄弟组件传递数据</button>

    </div>
</template>

<script>
    /* 创建并导出组件 */
    export default {
        name: 'MySchool',
        data() {
            return {
                name: '北大',
                address: '北京'
            }
        },
        methods: {
            send1() {
                console.log("MySchool组件中数据:", this.address);
                this.$bus.$emit("getSchoolAddress", this.address);
            }
        }
    }
</script>
复制代码

③子组件2(获取数据的组件)

复制代码
<template>
    <div class="Demo">
    </div>
</template>

<script>
    /* 创建并导出组件 */
    export default {
        name:'MyStudent',
        methods: {
            getSchoolAddress(addr){
                console.log("MyStudent中接收的数据:", addr);
            }
        },
        mounted() {
            this.$bus.$on('getSchoolAddress',this.getSchoolAddress)
        }
    }
</script>
复制代码

5. mixin混入

作用:

将组件的公共逻辑或者配置提取出来,哪个组件需要用到时,直接将提取的这部分混入到组件内部即可。这样既可以减少代码冗余度,也可以让后期维护起来更加容易。

5.1 创建js文件

  • 存储公共逻辑,配置等。

  • 创建 src/index.js

复制代码
export const mixin = {
    methods: {
        //自定义的方法
        show() {
            console.log("哪个组件调用了该方法this为哪个组件对象", this);
        }
    },
    data() {
        return {
            msg: '混入对象中的数据'
        }
    },
    created() {
        console.log("我是mixin中的created生命周期函数", "mixin被创建了");
    },
    mounted() {
        console.log("我是mixin中的mounted生命周期函数", "dom中元素完成了渲染");
    }
};
复制代码

5.2 局部混入

  • 在组件中导入并注册混入对象的可以使用混入中内容。

复制代码
<template>
    <div id='Demo'>
        <!-- 局部混入第3步:获取混入中数据 -->
        <h2>混入中的数据:{{msg}}</h2>
        <!-- 调用混入对象中方法 -->
        <button @click="show">按钮</button>
    </div>
</template>

<script>
    /* 局部混入第1步:导入混入对象 */
    import {mixin} from '../index.js'

    /* 创建并导出导出组件 */
    export default {
        name:'MySchool',
        /* 局部混入第2步:注册混入对象 */
        mixins: [mixin]
    }
</script>
复制代码

5.3 全局混入

在main.js导入并注册混入,所有组件就可以使用混入

复制代码
import Vue from 'vue'
import App from './App.vue'
/* 引入index.js */
import {mixin} from './index'

Vue.config.productionTip = false;

/* 设置混入对象 */
Vue.mixin(mixin);

new Vue({
    el:"#app",
    render: h => h(App)
});
复制代码

6. WebStorage

6.1 介绍

存储内容大小一般支持5MB左右(不同浏览器可能还不一样)。

浏览器端通过window.sessionStoragewindow.localStorage属性来实现本地存储机制。

复制代码
<script>
    export default {
        name: "WebStorageComponent",
        methods: {
            //保存数据
            saveData() {
                sessionStorage.setItem("uname", "zs");
                sessionStorage.setItem("pwd", "123");
            },
            //读取数据
            readData() {
                var uname = sessionStorage.getItem("uname");
                var pwd = sessionStorage.getItem("pwd");
                console.log(uname, pwd);
            },
            //删除数据
            deleteData() {
                sessionStorage.removeItem("uname");
            },
            //清空数据
            deleteAllData() {
                sessionStorage.clear();
            }
        }
    }
</script>
复制代码

十二、前后端交互

1. axios

axios是一个基于promise的HTTP客户端,可以用在浏览器和Node.js环境中。它提供了一个简单的API,可以轻松地发送HTTP请求和处理响应。

它支持浏览器和Node.js中的一系列HTTP方法,包括GET、POST、PUT、DELETE等,并且可以在请求中添加自定义的headers和参数

在服务端axios使用原生的nodejs的http模块,在客户端浏览器中使用XmlHttpRequest,本质是对XHR的封装。

特点:

  • 从浏览器创建 XMLHttpRequests

  • 自动转换 JSON 数据

  • 转换请求和响应数据

  • 拦截请求和响应

  • 取消请求

  • 超时处理

2. 安装依赖

cnpm install --save axios

3. 传统请求

前后端分离项目,后端要注意允许跨越访问

前端要导入axios

    //导入axios对象
    import axios from 'axios'

3.1 Get请求

复制代码
fun1() {
                //发送get请求
                axios.get("http://127.0.0.1:8888/queryById?id=1")
                    //成功回调的函数,参数为响应对象
                    .then(res => {
                        console.log(res.data);
                    })
                    //失败回调的函数,参数为异常对象
                    .catch(ex => {
                        console.log(ex);
                    })
            },
            fun2() {
                //发送get请求
                axios.get("http://127.0.0.1:8888/queryById", {
                    params: {
                        id: 1
                    }
                })
                    //成功回调的函数,参数为响应对象
                    .then(res => {
                        console.log(res.data);
                    })
                    //失败回调的函数,参数为异常对象
                    .catch(ex => {
                        console.log(ex);
                    })
            }
复制代码

3.2 Post请求

复制代码
fun1() {
                //发送post请求,请求内容类型 Content-Type: application/json
                axios.post("http://127.0.0.1:8888/add", {
                        id: 3,
                        sname: 'ww',
                        age: 25
                }).then(res => {
                        console.log(res.data);
                   })
                    .catch(ex => {
                        console.log(ex);
                    })
            }
复制代码

这里要注意由于axios发送请求默认的ContentType为 application/json,

所以后端接收数据需要使用@RequestBody注解,而且必须为引用类型(包装类不可以)

@RequestBody是spring提供的注解,用于将接收到的json格式数据转换为List、javaBean、List、Map等

4. Restful请求

复制代码
        methods: {
            fun1() {
                axios.get("http://127.0.0.1:8888/clazz/1")
                    .then(res => {
                        console.log(res.data);
                    })
            },
            fun2() {
                axios.delete("http://127.0.0.1:8888/clazz/1")
                    .then(res => {
                        console.log(res.data);
                    })
            },
            fun3(){
                axios.post("http://127.0.0.1:8888/clazz", {
                  id: 1,
                  cname: "Vue 班"
                }).then(res => {
                        console.log(res.data);
                    })
            },
            fun4(){
                axios.put("http://127.0.0.1:8888/clazz", {
                    id: 2,
                    cname: "Ajax 班"
                }).then(res => {
                    console.log(res.data);
                })
            }
        }
复制代码

5. axios全局配置

main.js

复制代码
import Vue from 'vue'
import App from './App.vue'

import axios from 'axios'
// 配置公共的请求基础路径
axios.defaults.baseURL = 'http://127.0.0.1:8888';
// 配置 超时时间
axios.defaults.timeout = 2500;
// 配置公共的请求头
axios.defaults.headers['uname'] = 'zs';
// 配置公共的 post 的 Content-Type
//axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';

Vue.config.productionTip = false;
new Vue({
  render: h => h(App),
}).$mount('#app');
复制代码

十三、slot插槽

让父组件可以向子组件指定位置插入html结构,也是一种组件间通信的方式。

1. 默认插槽

也叫匿名插槽

<slot>插槽1</slot>

使用:

<CategoryComponent> 
     插入的内容
</CategoryComponent>

注意:当没有插入内容时,会显示<slot>标签的内容

2. 具名插槽

<slot name="body">插槽2</slot>

比默认插槽多了个name属性

可以根据name插入到指定的插槽中

<CategoryComponent >
   <h5 slot="footer">插入内容</h5>
</CategoryComponent>

3. 作用域组件

作用域组件可以将子组件中的数据传递给调用者

复制代码
<slot :games="suiyi">我是一些默认值,当使用者没有传递具体结构时,我会出现</slot>

//...省略
data() {
            return {
                games:[
                    '植物大战僵尸','红色警戒','LOL','吃鸡'
                ],
            }
        }
复制代码

使用

        <CategoryComponent>
            <!-- 获取属性名及属性绑定的值存储在data作用域中 -->
            <template scope="suiyi">
              {{suiyi.games}}
            </template>
        </CategoryComponent>

十四、Vue路由

1.  vue-router介绍

vue路由为vue 的一个插件库,专门用来实现SPA 应用。

  1. 什么是路由?

    1. 一个路由就是一组映射关系(key - value)。

    2. key 为路径,value 为 componen。

  2. 执行原理

    1. 当浏览器的请求路径改变时,对应的组件就会显示。

    2. 通过切换,“隐藏”了的路由组件,默认是被销毁掉的,需要的时候再去挂载。

2. 安装

注意:选择vue2的版本

  1. vue2对应的vue-router版本是 vue-router3.x

    • cnpm install vue-router@3.6.5 --save

  2. vue3对应的vue-router版本是 vue-router4.x

    • cnpm install vue-router 默认安装vue-router4.x不适配vue2

3. 基本路由

被路由的组件通常放在 src/pages下

组件1:

复制代码
<template>
    <h5>First 组件</h2>
</template>

<script>
    export default {
        name: "FirstComponent"
    }
</script>
</script>
复制代码

组件2:

复制代码
<template>
    <h5>Second 组件</h2>
</template>

<script>
    export default {
        name: "SecondComponent"
    }
</script>
复制代码

新建 src/router/index.js(路由的配置)

复制代码
//导入Vue
import Vue from 'vue'
//导入路由
import VueRouter from 'vue-router'

//导入组件
import FirstComponent from "@/pages/FirstComponent";
import SecondComponent from "@/pages/SecondComponent";

//使用路由
Vue.use(VueRouter);

//创建并导出一个路由
export default new VueRouter({
    routes: [
        {
            path: '/first',
            component: FirstComponent
        },
        {
            path: '/second',
            component: SecondComponent
        }
    ]
});
复制代码

修改main.js(全局的配置)

复制代码
import Vue from 'vue'
import App from './App.vue'

//导入路由对象
import router from './router'

Vue.config.productionTip = false;

new Vue({
    //注册路由对象
    router,
    render: h => h(App),
}).$mount('#app');
复制代码

App.vue使用路由组件

复制代码
<template>
    <div id="app">
        <h2>主页面</h2>
        <!-- Vue中借助router-link标签实现路由的切换 -->
        <p>
            <router-link  to="/first">First</router-link>&nbsp;&nbsp;
            <router-link  to="/second">Second</router-link>
        </p>
        <hr>
        <!-- 被路由的组件展示位置 -->
        <router-view></router-view>
    </div>
</template>

<script>
    export default {
        name: 'App'
    }
</script>
复制代码

4. 多级路由

多级路由就是一级路由下又有多个子路由,子路由下也可以有子路由

例如在一级路由中添加子路由

一级路由:

复制代码
<template>
    <div>
        <h5>Second 组件</h5>
        <!-- 子路由中使用的路径必须 /父路由路径/子路由路径 -->
        <ul type="none">
            <li>
                <router-link to="/second/news">News</router-link>
            </li>
            <li>
                <router-link  to="/second/message">Message</router-link>
            </li>
        </ul>
        <p>
            <!-- 被路由的组件展示位置 -->
            <router-view></router-view>
        </p>
    </div>
</template>

<script>
    export default {
        name: "SecondComponent"
    }
</script>
复制代码

修改index.js

复制代码
 routes: [
        {
            path: '/first',
            component: FirstComponent
        },
        {
            path: '/second',
            component: SecondComponent,
            //配置子路由。子路由中的路径不能以/开头
            children: [
                {
                    path:'news', //不能以/开头
                    component: NewsComponent
                },
                {
                    path:'message', //不能以/开头
                    component: MessageComponent
                }
            ]
        }
    ]
复制代码

5. url中的#

vue开发单页面应用,在切换不同页面时,可以发现html永远只有一个,这也正是称之为单页面的原因。而vue-router默认为hash模式,使用URL的hash来模拟一个完整的URL,于是当URL改变时,页面不会重新加载。因为对于正常的页面来说,更换url一定是会导致页面更换的,而只有更换url中的查询字符串和hash值的时候才不会重新加载页面。

什么是hash值?—— #及其后面的内容就是hash值

hash值不会包含在 HTTP 请求中,即:hash值不会带给服务器

  1. hash模式(默认):

    1. 地址中永远带着#号,不美观。

    2. 若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法。

    3. 兼容性较好。

  2. history模式:

    • new VueRouter({})中,通过mode='history' 可以切换为history模式。

    1. 地址干净,美观。

    2. 兼容性和hash模式相比略差。

    3. 应用部署上线时需要后端人员支持,解决刷新页面服务端404的问题。

6. 命名路由

作用:给路由命名,简化路由跳转(名字代替路由的路径)

6.1 使用

修改index.js

复制代码
 routes: [
        {
            path: '/second',
            component: SecondComponent,
            //配置子路由。子路由中的路径不能以/开头
            children: [
                {
                    name: "new", //即使指定了路由名,也必须指定path
                    path:'news', //不能以/开头
                    component: NewsComponent
                },
            ]
        }
    ]
复制代码

使用路由:

<!-- 使用属性绑定,根据路由名进行路由 -->
<router-link :to="{name: 'new'}">News</router-link>

7. 路由传递参数

两种传参方式:query、params

7.1 query参数

①传递参数

<router-link 
    :to="{ path: '/xxx' 或者 name: 'xxx', query: { 参数名: 值 } }">xxx</router-link>

②接收参数

$route.query.参数名

注意是$route 而不是$router

在 Vue-router 中,有两个常用的实例变量:$router 和 $route。

  • $router 是一个指向 Vue-router 实例的引用。它允许在 Vue 实例中访问路由器配置和路由对象。可以使用 $router 来访问当前路由对象,以及获取路由器配置对象中的路由参数和锚点。
  • $route 是一个指向当前路由对象的引用。它是通过使用 router.currentRoute() 方法获取的。您可以使用 $route 来访问当前路由对象的属性,例如 path、name、params、anchor 等。

总的来说,$router 是一个指向 Vue-router 实例的引用,而 $route 是指向当前路由对象的引用。它们都用于访问与路由相关的信息,但用途略有不同。

7.2 params参数

①传递参数

<router-link 
    :to="{
        path: '/xxx' 或 name:'xxx',
        params:{
           参数名: 值
        }
    }"
>xxx</router-link>

②接收参数

$route.params.参数名

③动态路由(可选)

{
    name: 'mse',
    path:'message/:msgs', //使用占位符声明接收params参数名(动态路由,解决刷新页面不能获取数据的问题),不能以/开头
    component: MessageComponent
}

动态路由可以解决使用params传递参数时,刷新页面就获取不到数据的问题,使用这种方式时其实就是将参数拼接到url中了。

7.2.1 props配置

params可以配合props使用

①index.js配置props

复制代码
routes: [
            {
    name:'xxx',
    path:'/xxx',
    component: xxx,
    //props的第一种写法,值为对象,该对象中的所有key-value都会以props的形式传递
    // props:{a:1,b:'hello'}

    //props的第二种写法,值为布尔值,若布尔值为真,就会把该路由组件收到的所有params参数,以props的形式传递,属性名为params中的参数名
    // props:true

    //props的第三种写法,值为函数,以props的形式传递
    props($route){
        return {
            自定义属性名: $route.params.参数名,
        }
    }
  }
]
复制代码

②接收数据

<script>
    export default {
        name:'xxx',
        props:['属性名']
    }
</script>

以第三种props的写法为例

复制代码
routes: [
        {
            path: '/second',
            component: SecondComponent,
            //配置子路由。子路由中的路径不能以/开头
            children: [
                {
                    name: 'mse',
                    path:'message', //不能以/开头
                    props($route){
                        return {
                            mymsgs: $route.params.msgs,
                        }
                    },
                    component: MessageComponent
                }
            ]
        }
    ]
复制代码

mymsgs: 自定义的参数名,接收时 自定义属性要使用该参数名进行接收。

$.route.params.msgs 组件中的参数,其值就是组件中 data属性中的msgs的参数的值。

7.3 总结

路由传参:

   query:

     1.将参数在url中拼接进行传递(类似于get请求处理请求参数)

     2.刷新页面也可以获取到数据

     3.根据path | name进行组件的切换时,都能传递数据

  params:

    1.默认不会在地址栏拼接参数进行传递

     2.刷新后获取不到数据

     3.只有通过name进行组件的切换时,才能传递数据

  params可以配合props使用: 将params中传递的数据添加到绑定的自定义属性中 注意:params的特点

动态路由:

   解决params刷新页面获取不到数据的问题。

   index.js中的path配置: '/first/:uname' -> 访问first资源时,路径会变为 /first/(uname对应的属性值)(类似于Resultful处理请求参数)

注意:

   传递对象类型,数组类型:

       1.传递时:将对象类型,数组类型转换为 JSON格式的字符串 JSON.stringify(对象|数组)

       2.接收时:将JSON格式字符串的对象类型,数组类型转转换为对象,数组 JSON.parse(JSON格式字符串)

8. 编程式导航

8.1 路由跳转

控制路由跳转时操作浏览器历史记录的模式。

浏览器的历史记录有两种写入方式:push和replace,其中push是追加历史记录(保留历史记录),replace是替换当前记录。

路由跳转时候默认为push方式

开启replace模式:<router-link replace ...>xxx</router-link>

例:

<router-link replace to="/second">Second</router-link>

8.2 前进、回退历史

//后退
this.$router.back()

//前进       
this.$router.forward()

//前进或回退
this.$router.go(1)

十五、vuex

1. 介绍

vuex在 Vue 中实现集中式数据管理的一个 Vue 插件,对 vue 应用中多个组件的共享数据进行集中式的管理,也是一种组件间通信的方式,且适用于任意组件间通信。

2. 使用场景

3. 安装vuex

下载vuex`插件: ​   
  vue2版本:cnpm i vuex@3 ​   
  vue3版本:cnpm i vuex

4. vuex执行流程

  1. Actions:响应组件中用户的动作(处理业务逻辑)

  2. Mutations:修改state中的数据

  3. State对象:存储共享的数据

  4. 操作共享数据:

    • 组件中使用 $store.dispatch('Actions中的方法名',数据)

    • 若没有网络请求或其它业务逻辑,组件中也可以越过调用dispatch,直接调用commit

  5. 获取共享数据:

    • $store.state.sum

5. 使用vuex实现计数器

①安装vux

②创建vuex配置文件

src/store/index.js

复制代码
//引入Vue核心库
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex);

//准备actions对象 -》响应组件中用户的动作(处理业务逻辑)
const actions = {
    add(context, value) {
        console.log(context, value);
        context.commit("ADD", value);
    }
};

//准备mutations对象 -》修改state中的数据
const mutations = {
    ADD(state, value) {
        console.log(state, value);
        state.count += value;
    }
};

//准备state对象 -》保存具体的数据
const state = {
    count: 0
};

//创建并暴露store
export default new Vuex.Store({
    actions,
    mutations,
    state
})
复制代码

③修改main.js

复制代码
import Vue from 'vue'
import App from './App.vue'
//导入store
import store from './store'

Vue.config.productionTip = false

new Vue({
  //注册store  
  store,
  render: h => h(App),
}).$mount('#app');
复制代码

④创建组件测试

src/components/FirstComponent.vue

复制代码
<template>
    <div>
        <h3>组件一</h3>
        <button @click="fadd">+1</button>
        <p>{{$store.state.count}}</p>
    </div>
</template>

<script>
    export default {
        name: "FirstComponent",
        methods: {
            fadd() {
                //调用dispatch方法,驱动actions中add方法执行
                this.$store.dispatch('add',1);
            }
        }
    }
</script>
复制代码

src/components/SecondComponent.vue

复制代码
<template>
    <div>
        <h3>组件二</h3>
        <button @click="sadd">+1</button>
        <p>{{$store.state.count}}</p>
    </div>
</template>

<script>
    export default {
        name: "SecondComponent",
        methods: {
            sadd() {
                //调用dispatch方法,驱动actions中add方法执行
                this.$store.dispatch('add',1);
            }
        }
    }
</script>
复制代码

6. getter配置项

6.1 介绍

当 state中的数据需要加工后在使用时,可以使用getter加工

6.2 使用

①修改vuex配置文件

复制代码
//...


//创建getters配置项对象 -》对数据相关操作
const getters = {
    big() {
        return state.count * 10;
    }
};

//创建并暴露store
export default new Vuex.Store({
    actions,
    mutations,
    state,
    //注册getter
    getters
})
复制代码

②修改组件

复制代码
<template>
    <div>
        <h3>组件一</h3>
        <button @click="fadd">+1</button>
        <p>{{$store.state.count}}</p>
        <!--
            调用方式时只能使用方法名,不能添加方法的()
        -->
        <p>放大十倍:{{$store.getters.big}}</p>
    </div>
</template>

<script>
    export default {
        name: "FirstComponent",
        methods: {
            fadd() {
                this.$store.dispatch('add',1);
            }
        }
    }
</script>
复制代码
复制代码
<template>
    <div>
        <h3>组件二</h3>
        <button @click="sadd">+1</button>
        <p>{{$store.state.count}}</p>
        <!--
            调用方式时只能使用方法名,不能添加方法的()
        -->
        <p>放大十倍:{{$store.getters.big}}</p>
    </div>
</template>

<script>
    export default {
        name: "SecondComponent",
        methods: {
            sadd() {
                this.$store.dispatch('add',1);
            }
        }
    }
</script>

<style scoped>

</style>
复制代码

7. 四个map方法的使用

7.1 mapState | mapGetter

  1. mapState:简化获取state中的数据。

  2. mapGetters:简化调用getters中的方法。

复制代码
<template>
    <div>
        <p>{{count}}</p>
        <p>放大十倍:{{big}}</p>
    </div>
</template>
<script>

    //导入 mapState,mapGetters
    import {mapState,mapGetters} from 'vuex'
   //...省略
        computed: {
            //参数:state中的属性名
            ...mapState(['count']),
            //参数:getters中的方法名
            ...mapGetters(['big'])
        }
  //...省略
复制代码

7.2 mapAction | mapMutations

  1. mapActions:简化调用dispatch方法。既:简化了 this.$store.dispatch(xxx);

  2. mapMutations:简化调用commit方法。既:简化了 this.$store.commit(xxx);

    • 若没有网络请求或其它业务逻辑,组件中也可以越过调用dispatch,直接调用commit

复制代码
<template>
    <div>
        <!--
            指定传递的参数
        -->
        <button @click="fadd(1)">+1</button>
    </div>
</template>

<script>

    //导入 mapState,mapGetters,mapMutations,mapActions
    //import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'
    import {mapActions} from 'vuex'

    export default {
        name: "FirstComponent",
        methods: {
            fadd() {/*this.$store.dispatch('add',1);*/
            },
            //mapActions与mapMutations使用时,若需要传递参数,则需要在模板中绑定事件时传递好参数,否则参数是事件对象
            //调用actions中的add()方法。{事件中的方法名:'actions中的方法名'
            ...mapActions({fadd: 'add'})
        },
    }
</script>
复制代码

7.3.总结:

  1. mapState:简化获取state中的共享数据。

    1. 没有简化:$store.state.属性名

    2. 简化后:配置...mapState(['属性名']) 获取数据直接使用 属性名 获取

  2. mapGetters:简化获取数据加工后的结果

    1. 没有简化:$store.getters.方法名

    2. 简化后:配置...mapGetters(['方法名']) 获取加工后结果直接使用 方法名 获取

  3. mapActions:简化调用actions中的自定义方法 =》处理用户的数据变化的业务逻辑

    1. 没有简化:$store.dispatch('方法名')

    2. 简化后:直接使用...mapActions({事件中的方法名:方法名}) 调用

      • 注意事项:需要传递参数,必须在事件的方法中添加传递的参数

  4. mapMutations:简化调用mutaions中的自定义方法 =》改变数据

    1. 没有简化:$store.commit('方法名')

    2. 简化后:直接使用...mapMutations({事件中的方法名:方法名}) 调用

      • 注意事项:需要传递参数,必须在事件的方法中添加传递的参数

十七、Element UI

1. 介绍

Element UI是一个基于Vue.js的组件库,提供了一套丰富、美观、易用的UI组件,包括表单、弹窗、导航、布局、数据展示等各种常用组件。Element UI旨在帮助开发者快速构建高质量的Web应用程序,使得前端开发更加高效和便捷。

Element - 网站快速成型工具

2. 安装插件

npm i element-ui -S --legacy-peer-deps

3. 修改main.js

复制代码
import Vue from 'vue'

import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import App from './App.vue';

Vue.use(ElementUI);
Vue.config.productionTip = false

new Vue({
  render: h => h(App),
}).$mount('#app')
复制代码

 

posted @   ygdgg  阅读(38)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
点击右上角即可分享
微信分享提示