vue基础知识大全

知识清单

        • 初识vue
        • vue基本模版
        • 数据单向传递
        • chrome调试工具
        • 数据双向绑定
        • vue数据绑定的过程
      • 常用指令
        • v-once 让界面不要跟着数据变化, 只渲染一次
        • v-cloak 数据渲染之后自动显示元素
        • v-text 和 v-html对比
        • v-if
        • v-show以及与v-if的区别
        • v-for
        • v-for-key
        • v-bind 给元素的属性绑定数据
        • v-bind 绑定类名
        • v-bind 绑定样式
        • v-on
        • v-on 修饰符
        • v-on 注意点
        • v-on 按键修饰符
        • 自定义全局指令
        • 自定义指令参数
        • 自定义局部指令
        • 计算属性
        • 计算属性与函数的对比
        • 自定义全局过滤器
        • 自定义局部过滤器
        • 格式化时间的过滤器练习
        • 过渡动画
        • 自定义全局组件
        • 自定义局部组件
        • 组件中使用data的注意点(在自定义组件中使用data必须赋值一个函数, 然后通过函数的返回值来定义有哪些数据)
        • 组件中的data为什么是一个函数
        • 组件切换
        • 动态组件
        • 组件动画
        • 父子组件
        • 父子组件的数据传递
        • 父子组件的方法传递
        • 组件中的命名注意点
        • 数据和方法的多级传递
        • 匿名插槽
        • 具名插槽
        • v-slot指令
        • 作用域插槽
        • v-slot指令取代slot-scope
        • Vuex共享数据
        • 修改数据
        • Vuex里面的getters
        • Vue Router
        • VueRouter-参数传递
        • 嵌套路由
        • 命名视图
        • watch属性
        • 生命周期方法
        • ref属性
        • 组件的第二种渲染方式-render
        • Vue-CLI

初识vue

1.什么是Vue?
Vue.js 是一套构建用户界面的框架,它不仅易于上手,还可以与其它第三方库整合(Swiper、IScroll、…)。

2.框架和库的区别?
框架:是一套完整的解决方案;对项目的侵入性较大,项目如果需要更换框架,则需要重构整个项目。
库(插件):提供某一个小功能,对项目的侵入性较小,如果某个库无法完成某些需求,可以很容易切换到其它库实现需求。
例如: 从jQuery 切换到 Zepto, 无缝切换
从IScroll切换到ScrollMagic, 只需要将用到IScroll的代码替换成ScrollMagic代码即可

3.为什么要学习框架?
提升开发效率:在企业中,时间就是效率,效率就是金钱;
前端提高开发效率的发展历程:原生JS -> jQuery之类的类库 -> 前端模板引擎 -> Vue / React / Angular

4.框架有很多, 为什么要先学Vue
Vue、Angular、React一起,被称之为前端三大主流框架!
但是Angular、React是老外编写的, 所以所有的资料都是英文的
而Vue是国人编写的, 所以所有的资料都是中文的, 并且Vue中整合了Angular、React中的众多优点
所以为了降低我们的学习难度, 我们先学Vue, 学完之后再学习Angular和React

5.使用Vue有哪些优势?
5.1Vue的核心概念之一:
通过数据驱动界面更新, 无需操作DOM来更新界面
使用Vue我们只需要关心如何获取数据, 如何处理数据, 如何编写业务逻辑代码,
我们只需要将处理好的数据交给Vue, Vue就会自动将数据渲染到模板中(界面上)
5.2Vue的核心概念之二:
组件化开发,我们可以将网页拆分成一个个独立的组件来编写
将来再通过封装好的组件拼接成一个完整的网页
https://cn.vuejs.org/images/components.png

vue基本模版



<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>02-Vue基本模板title>
    
    <script src="js/vue.js">script>
head>
<body>
<div id="app">
    <p>{
    { name }}p>
div>
<script>
    // 2.创建一个Vue的实例对象
    let vue = new Vue({
      
        // 3.告诉Vue的实例对象, 将来需要控制界面上的哪个区域
        el: '#app',
        // 4.告诉Vue的实例对象, 被控制区域的数据是什么
        data: {
      
            name: "Andy"
        }
    });
script>
body>
html>


数据单向传递



<div id="app">
    <p>{
    { name }}p>
div>
<script>
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
            name: "Andy"
        }
    });
script>

chrome调试工具

1.Vue调试工具安装
如果你能打开谷歌插件商店, 直接在线安装即可
https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd?hl=zh-CN

由于国内无法打开谷歌国外插件商店, 所以可以离线安装
https://www.chromefor.com/vue-js-devtools_v5-3-0/

2.安装步骤:
2.1下载离线安装包
2.2打开谷歌插件界面
2.3直接将插件拖入
2.4报错 程序包无效: "CRX_HEADER_INVALID"
   可以将安装包修改为rar后缀, 解压之后再安装
2.5重启浏览器

数据双向绑定

数据双向绑定
默认情况下Vue只支持数据单向传递 M -> VM -> V
但是由于Vue是基于MVVM设计模式的, 所以也提供了双向传递的能力
在<input><textarea><select> 元素上可以用 v-model 指令创建双向数据绑定

注意点: v-model 会忽略所有表单元素的 value、checked、selected 特性的初始值
而总是将 Vue 实例的数据作为数据来源


<div id="app">
    <p>{
    { name }}p>
    <input type="text" v-model="msg">
div>
<script>
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
            name: "Andy",
            msg: "可可爱爱"
        }
    });
script>

vue数据绑定的过程

1.Vue数据绑定过程
1.1会先将未绑定数据的界面展示给用户
1.2然后再根据模型中的数据和控制的区域生成绑定数据之后的HTML代码
1.3最后再将绑定数据之后的HTML渲染到界面上

常用指令

v-once 让界面不要跟着数据变化, 只渲染一次




<div id="app">
    <p v-once>原始数据: {
    { name }}p>
    <p>当前数据: {
    { name }}p>
div>
<script>
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
            name: "Andy",
        }
    });
script>

v-cloak 数据渲染之后自动显示元素




<div id="app">
    <p v-cloak>{
    { name }}p>
div>

<script src="js/vue.js">script>
<script>
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
            name: "Andy ",
        }
    });
script>

v-text 和 v-html对比

1.什么是v-text指令
v-text就相当于过去学习的innerText

2.什么是v-html指令
v-html就相当于过去学习的innerHTML

<div id="app">
    
<p>++++{
    { name }}++++p>
    
<p>++++{
    { msg }}++++p>
    
<p v-text="name">++++++++p>
    
<p v-text="msg">++++++++p>
    
<p v-html="name">++++++++p>
    
<p v-html="msg">++++++++p>
div>
<script>
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
            name: "Andy",
            msg: "我是span"
        }
    });
script>

v-if

1.什么是v-if指令
条件渲染: 如果v-if取值是true就渲染元素, 如果不是就不渲染元素

2.v-if特点:
如果条件不满足根本就不会创建这个元素(重点)

3.v-if注意点
v-if可以从模型中获取数据
v-if也可以直接赋值一个表达式

4.v-else指令
v-else指令可以和v-if指令配合使用, 当v-if不满足条件时就执行v-else就显示v-else中的内容

5.v-else注意点
v-else不能单独出现
v-if和v-else中间不能出现其它内容

6.v-else-if指令
v-else-if可以和v-if指令配合使用, 当v-if不满足条件时就依次执行后续v-else-if, 哪个满足就显示哪个

7.v-else-if注意点
和v-else一样



<div id="app">











    <p v-if="score >= 80">优秀p>
    <p v-else-if="score >= 60">良好p>
    <p v-else>p>
div>
<script>
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
            show: true,
            hidden: false,
            age: 17,
            score: 50
        }
    });
script>

v-show以及与v-if的区别

1.什么是v-show指令
v-show和v-if的能够一样都是条件渲染, 取值为true就显示, 取值为false就不显示

2.v-if和v-show区别
v-if: 只要取值为false就不会创建元素
v-show: 哪怕取值为false也会创建元素, 只是如果取值是false会设置元素的display为none

3.v-if和v-show应用场景
由于取值为false时v-if不会创建元素, 所以如果需要切换元素的显示和隐藏, 每次v-if都会创建和删除元素
由于取值为false时v-show会创建元素并设置display为none, 所有如果需要切换元素的显示和隐藏,
不会反复创建和删除, 只是修改display的值
所以: 如果企业开发中需要频繁切换元素显示隐藏, 那么推荐使用v-show, 否则使用v-if

<div id="app">






    <p v-show="show">我是段落1p>
    <p v-show="hidden">我是段落2p>
div>
<script>
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
            show: true,
            hidden: false,
            age: 18
        }
    });
script>

v-for




<div id="app">
    <ul>



        <li v-for="(value, key) in obj">{
    {key}}---{
    {value}}li>
    ul>
div>
<script>
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
            list: ["张三", "李四", "王五", "赵六"],
            obj: {
      
                name: "lnj",
                age: 33,
                gender: "male",
                class: "web"
            }
        }
    });
script>

v-for-key

1.v-for注意点
1.1v-for为了提升性能, 在更新已渲染过的元素列表时,会采用“就地复用”策略。
也正是因为这个策略, 在某些时刻会导致我们的数据混乱
例如: 在列表前面新增了内容
1.2为了解决这个问题, 我们可以在渲染列表的时候给每一个元素加上一个独一无二的key
v-for在更新已经渲染过的元素列表时, 会先判断key是否相同, 如果相同则复用, 如果不同则重新创建

2.key属性注意点
不能使用index的作为key,因为当列表的内容新增或者删除时index都会发生变化


<div id="app">
    <form>
        <input type="text" v-model="name">
        <input type="submit" value="添加" @click.prevent="add">
    form>
    <ul>

        <li v-for="(person,index) in persons" :key="index">
            <input type="checkbox">
            <span>{
    {index}} --- {
    {person.name}}span>
        li>
    ul>
div>
<script>
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
            persons: [
                {
      name: "zs", id: 1},
                {
      name: "ls", id: 2},
                {
      name: "ww", id: 3}
                ],
            name: ""
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
            add(){
      
                let lastPerson = this.persons[this.persons.length - 1];
                let newPerson = {
      name: this.name, id: lastPerson.id + 1};
                // this.persons.push(newPerson);
                this.persons.unshift(newPerson);
                this.name = "";
            }
        },
        // 专门用于定义计算属性的
        computed: {
      
        }
    });
script>

v-bind 给元素的属性绑定数据

1.什么是v-bind指令
在企业开发中想要给"元素"绑定数据, 我们可以使用{
    {}}, v-text, v-html
但是如果想给"元素的属性"绑定数据, 就必须使用v-bind
所以v-bind的作用是专门用于给"元素的属性"绑定数据的

2.v-bind格式
v-bind:属性名称="绑定的数据"
:属性名称="绑定的数据"

3.v-bind特点
赋值的数据可以是任意一个合法的JS表达式
例如: :属性名称="age + 1"


<div id="app">



    

    



    <input type="text" :value="age + 1">
div>
<script>
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
            name: "Andy",
            age: 18
        }
    });
script>

v-bind 绑定类名



<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>12-常用指令-绑定类名title>
    <script src="js/vue.js">script>
    <style>
        *{
      
            margin: 0;
            padding: 0;
        }
        .size{
      
            font-size: 100px;
        }
        .color{
      
            color: red;
        }
        .active{
      
            background: skyblue;
        }
    style>
head>
<body>

1.v-bind指令的作用
v-bind指令给"任意标签"的"任意属性"绑定数据
对于大部分的属性而言我们只需要直接赋值即可, 例如:value="name"
但是对于class和style属性而言, 它的格式比较特殊

2.通过v-bind绑定类名格式
:class="['需要绑定类名', ...]"

3.注意点:
3.1直接赋值一个类名(没有放到数组中)默认回去Model中查找
:class="需要绑定类名"
2.2数组中的类名没有用引号括起来也会去Model中查找
:class="[需要绑定类名]"
2.3数组的每一个元素都可以是一个三目运算符按需导入
:class="[flag?'active':'']"
2.4可以使用对象来替代数组中的三目运算符按需导入
:class="[{'active': true}]"
2.5绑定的类名太多可以将类名封装到Model中
obj: {
    'color': true,
    'size': true,
    'active': false,
}

4.绑定类名企业应用场景
从服务器动态获取样式后通过v-bind动态绑定类名
这样就可以让服务端来控制前端样式
常见场景: 618 双11等



<div id="app">

    

    

    

    

    

    
    <p :class="obj">我是段落p>
div>
<script>
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
            flag: false,
            obj:{
      
                'size': false,
                'color': false,
                'active': true,
            }
        }
    });
script>
body>
html>

v-bind 绑定样式



1.如何通过v-bind给style属性绑定数据
1.1将数据放到对象中
:style="{color:'red','font-size':'50px'}"
1.2将数据放到Model对象中
obj: {
    color: 'red',
    'font-size': '80px',
}

2.注意点
2.1如果属性名称包含-, 那么必须用引号括起来
2.2如果需要绑定Model中的多个对象, 可以放到一个数组中赋值



<div id="app">

    

    

    


    
    <p :style="[obj1, obj2]">我是段落p>
div>
<script>
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
            obj1:{
      
                "color": "blue",
                "font-size": "100px"
            },
            obj2: {
      
                "background-color": "red"
            }
        }
    });
script>

v-on


1.什么是v-on指令?
v-on指令专门用于给元素绑定监听事件

2.v-on指令格式
v-on:事件名称="回调函数名称"
@事件名称="回调函数名称"

3.v-on注意点:
v-on绑定的事件被触发之后, 会去Vue实例对象的methods中查找对应的回调函数
-->


<div id="app">

    

    

    <button @click="myFn">我是按钮button>
div>
<script>
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
        },
        methods: {
      
            myFn(){
      
                alert('lnj')
            }
        }
    });
script>

v-on 修饰符

1.v-on修饰符
在事件中有很多东西需要我们处理, 例如事件冒泡,事件捕获, 阻止默认行为等
那么在Vue中如何处理以上内容呢, 我们可以通过v-on修饰符来处理

2.常见修饰符
.once    - 只触发一次回调。
.prevent - 调用 event.preventDefault()。
.stop    - 调用 event.stopPropagation()。
.self    - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
.capture - 添加事件侦听器时使用 capture 模式。



<div id="app">
    

    

    

    
    
    
    
    
    <div class="a" @click.capture="myFn1">
        <div class="b" @click.capture="myFn2">
            <div class="c" @click.capture="myFn3">div>
        div>
    div>
div>
<script>
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
            myFn(){
      
                alert('lnj');
            },
            myFn1(){
      
                console.log("爷爷");
            },
            myFn2(){
      
                console.log("爸爸");
            },
            myFn3(){
      
                console.log("儿子");
            }
        }
    });
script>

v-on 注意点

1.v-on注意点
1.1绑定回调函数名称的时候, 后面可以写()也可以不写
v-on:click="myFn"
v-on:click="myFn()"

1.2可以给绑定的回调函数传递参数
v-on:click="myFn('lnj', 33)"

1.3如果在绑定的函数中需要用到data中的数据必须加上this


<div id="app">
    <button @click="myFn('lnj', 33, $event)">我是按钮button>
div>
<script>
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
            gender: "man"
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
            myFn(name, age, e){
      
                // alert('lnj');
                // console.log(name, age, e);
                console.log(this.gender);
            }
        }
    });
script>

v-on 按键修饰符


1.什么是按键修饰符
我们可以通过按键修饰符监听特定按键触发的事件
例如: 可以监听当前事件是否是回车触发的, 可以监听当前事件是否是ESC触发的等

2.按键修饰符分类
2.1系统预定义修饰符
2.2自定义修饰符


<div id="app">

    <input type="text" @keyup.f2="myFn">
div>
<script>
    Vue.config.keyCodes.f2 = 113;
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
            myFn(){
      
                alert("lnj");
            }
        }
    });
script>

自定义全局指令

1.自定义全局指令
在Vue中除了可以使用Vue内置的一些指令以外, 我们还可以自定义指令

2.自定义全局指令语法
ue.directive(‘自定义指令名称’, {
生命周期名称: function (el) {
指令业务逻辑代码
}
});

3.指令生命周期方法
自定义指令时一定要明确指令的业务逻辑代码更适合在哪个阶段执行
例如: 指令业务逻辑代码中没有用到元素事件, 那么可以在bind阶段执行
例如: 指令业务逻辑代码中用到了元素事件, 那么就需要在inserted阶段执行

4.自定义指令注意点
使用时需要加上v-, 而在自定义时不需要加上v-


<div id="app">

    <input type="text" v-focus>
div>
<script>
    /*
    directive方法接收两个参数
    第一个参数: 指令的名称
    第二个参数: 对象
    注意点: 在自定义指令的时候, 在指定指令名称的时候, 不需要写v-
    注意点: 指令可以在不同的生命周期阶段执行
    bind: 指令被绑定到元素上的时候执行
    inserted: 绑定指令的元素被添加到父元素上的时候执行
    * */
    Vue.directive("color", {
      
        // 这里的el就是被绑定指令的那个元素
        bind: function (el) {
      
            el.style.color = "red";
        }
    });
    Vue.directive("focus", {
      
        // 这里的el就是被绑定指令的那个元素
        inserted: function (el) {
      
            el.focus();
        }
    });
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
        }
    });
script>

自定义指令参数

1.自定义指令参数
在使用官方指令的时候我们可以给指令传参
例如: v-model=“name”
在我们自定义的指令中我们也可以传递传递

2.获取自定义指令传递的参数
在执行自定义指令对应的方法的时候, 除了会传递el给我们, 还会传递一个对象给我们
这个对象中就保存了指令传递过来的参数


<div id="app">

    <p v-color="curColor">我是段落p>
div>
<script>
    Vue.directive("color", {
      
        // 这里的el就是被绑定指令的那个元素
        bind: function (el, obj) {
      
            // el.style.color = "red";
            el.style.color = obj.value;
        }
    });
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
            curColor: 'green'
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
        }
    });
script>

自定义局部指令

1.自定义全局指令的特点
在任何一个Vue实例控制的区域中都可以使用

2.自定义局部指令的特点
只能在自定义的那个Vue实例中使用

3.如何自定义一个局部指令
给创建Vue实例时传递的对象添加

directives: {
    // key: 指令名称
    // value: 对象
    'color': {
        bind: function (el, obj) {
            el.style.color = obj.value;
        }
    }
}

<div id="app1">
    <p v-color="'blue'">我是段落p>
div>
<div id="app2">
    <p v-color="'red'">我是段落p>
div>
<script>
    /*
    Vue.directive("color", {
        // 这里的el就是被绑定指令的那个元素
        bind: function (el, obj) {
            el.style.color = obj.value;
        }
    });
     */
    // 这里就是MVVM中的View Model
    let vue1 = new Vue({
      
        el: '#app1',
        // 这里就是MVVM中的Model
        data: {
      },
        // 专门用于存储监听事件回调函数
        methods: {
      }
    });
    // 这里就是MVVM中的View Model
    let vue2 = new Vue({
      
        el: '#app2',
        // 这里就是MVVM中的Model
        data: {
      },
        // 专门用于存储监听事件回调函数
        methods: {
      },
        // 专门用于定义局部指令的
        directives: {
      
            "color": {
      
                // 这里的el就是被绑定指令的那个元素
                bind: function (el, obj) {
      
                    el.style.color = obj.value;
                }
            }
        }
    });
script>

计算属性

1.插值语法特点
可以在{ {}}中编写合法的JavaScript表达式

2.在插值语法中编写JavaScript表达式缺点
2.1没有代码提示
2.2语句过于复杂不利于我们维护

3.如何解决?
对于任何复杂逻辑,你都应当使用计算属性


<div id="app">
    <p>{
    {name}}p>
    <p>{
    {age + 1}}p>
    <p>{
    {msg.split("").reverse().join("")}}p>
   
    注意点:
    虽然在定义计算属性的时候是通过一个函数返回的数据
    但是在使用计算属性的时候不能在计算属性名称后面加上()
    因为它是一个属性不是一个函数(方法)
   
    <p>{
    {msg2}}p>
div>
<script>
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
            name: "lnj",
            age: 18,
            msg: "abcdef"
        },
        // 专门用于存储监听事件回调函数
        methods: {
      },
        // 专门用于定义计算属性的
        computed: {
      
            msg2: function () {
      
                let res = "abcdef".split("").reverse().join("");
                return res;
            }
        }
    });
script>

计算属性与函数的对比

1.计算属性和函数
通过计算属性我们能拿到处理后的数据, 但是通过函数我们也能拿到处理后的数据
那么计算属性和函数有什么区别呢?
2.1函数"不会"将计算的结果缓存起来, 每一次访问都会重新求值
2.2计算属性"会"将计算的结果缓存起来, 只要数据没有发生变化, 就不会重新求值

2.计算属性应用场景
计算属性:比较适合用于计算不会频繁发生变化的的数据

自定义全局过滤器

1.什么是过滤器?
过滤器和函数和计算属性一样都是用来处理数据的
但是过滤器一般用于格式化插入的文本数据

2.如何自定义全局过滤器
Vue.filter(“过滤器名称”, 过滤器处理函数):

3.如何使用全局过滤器(只有这两种使用方式)
{ {msg | 过滤器名称}}
:value=“msg | 过滤器名称”

4.过滤器注意点
4.1只能在插值语法和v-bind中使用
4.2过滤器可以连续使用


<div id="app">
    
    <p>{
    {name | formartStr1 | formartStr2}}p>
div>
<script>
    /*
    如何自定义一个全局过滤器
    通过Vue.filter();
    filter方法接收两个参数
    第一个参数: 过滤器名称
    第二个参数: 处理数据的函数
    注意点: 默认情况下处理数据的函数接收一个参数, 就是当前要被处理的数据
    * */
    Vue.filter("formartStr1", function (value) {
      
        // console.log(value);
        value = value.replace(/学院/g, "大学");
        console.log(value);
        return value;
    });
    Vue.filter("formartStr2", function (value) {
      
        // console.log(value);
        value = value.replace(/大学/g, "幼儿园");
        console.log(value);
        return value;
    });
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
            name: "知播渔学院, 指趣学院, 前端学院, 区块链学院"
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
        },
        // 专门用于定义计算属性的
        computed: {
      
        }
    });
script>

自定义局部过滤器

1.自定义全局过滤器的特点
在任何一个Vue实例控制的区域中都可以使用

2.自定义局部过滤器的特点
只能在自定义的那个Vue实例中使用

3.如何自定义一个局部指令
给创建Vue实例时传递的对象添加

filters: {
    // key: 过滤器名称
    // value: 过滤器处理函数
    'formartStr': function (value) {}
}

<div id="app1">
    <p>{
    {name | formartStr}}p>
div>
<div id="app2">
    <p>{
    {name | formartStr}}p>
div>
<script>
    /*
    Vue.filter("formartStr", function (value) {
        // console.log(value);
        value = value.replace(/学院/g, "大学");
        // console.log(value);
        return value;
    });
    */
    // 这里就是MVVM中的View Model
    let vue1 = new Vue({
      
        el: '#app1',
        // 这里就是MVVM中的Model
        data: {
      
            name: "知播渔学院, 指趣学院, 前端学院, 区块链学院"
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
        },
        // 专门用于定义计算属性的
        computed: {
      
        }
    });
    // 这里就是MVVM中的View Model
    let vue2 = new Vue({
      
        el: '#app2',
        // 这里就是MVVM中的Model
        data: {
      
            name: "知播渔学院, 指趣学院, 前端学院, 区块链学院"
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
        },
        // 专门用于定义计算属性的
        computed: {
      
        },
        // 专门用于定义局部过滤器的
        filters: {
      
            "formartStr": function (value) {
      
                // console.log(value);
                value = value.replace(/学院/g, "大学");
                // console.log(value);
                return value;
            }
        }
    });
script>

格式化时间的过滤器练习



<div id="app">
    <p>{
    {time | dateFormart("yyyy-MM-dd")}}p>
div>
<script>
    /*
    注意点: 在使用过滤器的时候, 可以在过滤器名称后面加上()
            如果给过滤器的名称后面加上了(), 那么就可以给过滤器的函数传递参数
    * */
    Vue.filter("dateFormart", function (value, fmStr) {
      
        // console.log(fmStr);
        let date = new Date(value);
        let year = date.getFullYear();
        let month = date.getMonth() + 1 + "";
        let day = date.getDate() + "";
        let hour = date.getHours() + "";
        let minute = date.getMinutes() + "";
        let second = date.getSeconds() + "";
        if(fmStr && fmStr === "yyyy-MM-dd"){
      
            return `${
        year}-${
        month.padStart(2, "0")}-${
        day.padStart(2, "0")}`;
        }
        return `${
        year}-${
        month.padStart(2, "0")}-${
        day.padStart(2, "0")} ${
        hour.padStart(2, "0")}:${
        minute.padStart(2, "0")}:${
        second.padStart(2, "0")}`;
    });
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
            time: Date.now()
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
        },
        // 专门用于定义计算属性的
        computed: {
      
        }
    });
script>

过渡动画

1.如何给Vue控制的元素添加过渡动画
1.1将需要执行动画的元素放到transition组件中
1.2当transition组件中的元素显示时会自动查找.v-enter/.v-enter-active/.v-enter-to类名
当transition组件中的元素隐藏时会自动查找.v-leave/ .v-leave-active/.v-leave-to类名
1.3我们只需要在.v-enter和.v-leave-to中指定动画动画开始的状态
在.v-enter-active和.v-leave-active中指定动画执行的状态
即可完成过渡动画



<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>29-Vue-过渡动画title>
    <script src="js/vue.js">script>
    <style>
        *{
      
            margin: 0;
            padding: 0;
        }
        .box{
      
            width: 200px;
            height: 200px;
            background: red;
        }
        .one-enter{
      
            opacity: 0;
        }
        .one-enter-to{
      
            opacity: 1;
            margin-left: 500px;
        }
        .one-enter-active{
      
            transition: all 3s;
        }
        .two-enter{
      
            opacity: 0;
        }
        .two-enter-to{
      
            opacity: 1;
            margin-top: 500px;
        }
        .two-enter-active{
      
            transition: all 3s;
        }
    style>
head>
<body>

1.transition注意点:
transition中只能放一个元素, 多个元素无效
如果想给多个元素添加过渡动画, 那么就必须创建多个transition组件

2.初始动画设置
默认情况下第一次进入的时候没没有动画的
如果想一进来就有动画, 我们可以通过给transition添加appear属性的方式
告诉Vue第一次进入就需要显示动画

3.如何给多个不同的元素指定不同的动画
如果有多个不同的元素需要执行不同的过渡动画,那么我们可以通过给transition指定name的方式
来指定"进入之前/进入之后/进入过程中, 离开之前/离开之后/离开过程中"对应的类名
来实现不同的元素执行不同的过渡动画



<div id="app">
    <button @click="toggle">我是按钮button>
    <transition appear name="one">
        <div class="box" v-show="isShow">div>

    transition>
    <transition appear name="two">
        <div class="box" v-show="isShow">div>
    transition>
div>
<script>
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
            isShow: true
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
            toggle(){
      
                this.isShow = !this.isShow;
            }
        },
        // 专门用于定义计算属性的
        computed: {
      
        }
    });
script>
body>
html>

通过Vue提供的JS钩子来实现过渡动画



<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>30-Vue-过渡动画title>
    <script src="js/vue.js">script>
    <style>
        *{
      
            margin: 0;
            padding: 0;
        }
        .box{
      
            width: 200px;
            height: 200px;
            background: red;
        }
        .v-enter{
      
            opacity: 0;
        }
        .v-enter-to{
      
            opacity: 1;
            margin-left: 500px;
        }
        .v-enter-active{
      
            transition: all 3s;
        }
    style>
head>
<body>

1.当前过渡存在的问题
通过transition+类名的方式确实能够实现过渡效果
但是实现的过渡效果并不能保存动画之后的状态
因为Vue内部的实现是在过程中动态绑定类名, 过程完成之后删除类名
正式因为删除了类名, 所以不能保存最终的效果

2.在Vue中如何保存过渡最终的效果
通过Vue提供的JS钩子来实现过渡动画
v-on:before-enter="beforeEnter"  进入动画之前
v-on:enter="enter"  进入动画执行过程中
v-on:after-enter="afterEnter"  进入动画完成之后
v-on:enter-cancelled="enterCancelled"  进入动画被取消

v-on:before-leave="beforeLeave" 离开动画之前
v-on:leave="leave"  离开动画执行过程中
v-on:after-leave="afterLeave" 离开动画完成之后
v-on:leave-cancelled="leaveCancelled" 离开动画被取消

3.JS钩子实现过渡注意点
3.1在动画过程中必须写上el.offsetWidth或者el.offsetHeight
3.2在enter和leave方法中必须调用done方法, 否则after-enter和after-leave不会执行
3.3需要需要添加初始动画, 那么需要把done方法包裹到setTimeout方法中调用



<div id="app">
    <button @click="toggle">我是按钮button>
    
    <transition appear
                v-bind:css="false"
                v-on:before-enter="beforeEnter"
                v-on:enter="enter"
                v-on:after-enter="afterEnter">
        <div class="box" v-show="isShow">div>
    transition>
div>
<script>
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
            isShow: true
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
            toggle(){
      
                this.isShow = !this.isShow;
            },
            beforeEnter(el){
      
                // 进入动画开始之前
                console.log("beforeEnter");
                el.style.opacity = "0";
            },
            enter(el, done){
      
                // 进入动画执行过程中
                console.log("enter");
                /*
                注意点: 如果是通过JS钩子来实现过渡动画
                        那么必须在动画执行过程中的回调函数中写上
                        el.offsetWidth / el.offsetHeight
                * */
                // el.offsetWidth;
                el.offsetHeight;
                el.style.transition = "all 3s";
                /*
                注意点: 动画执行完毕之后一定要调用done回调函数
                        否则后续的afterEnter钩子函数不会被执行
                * */
                // done();
                /*
                注意点: 如果想让元素一进来就有动画, 那么最好延迟以下再调用done方法
                * */
                setTimeout(function () {
      
                    done();
                }, 0);
            },
            afterEnter(el){
      
                // 进入动画执行完毕之后
                console.log("afterEnter");
                el.style.opacity = "1";
                el.style.marginLeft = "500px";
            }
        },
        // 专门用于定义计算属性的
        computed: {
      
        }
    });
script>
body>
html>

配合Velocity实现过渡动画



<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>31-Vue-过渡动画title>
    <script src="js/vue.js">script>
    <style>
        *{
      
            margin: 0;
            padding: 0;
        }
        .box{
      
            width: 200px;
            height: 200px;
            background: red;
        }
    style>
head>
<body>

1.配合Velocity实现过渡动画
在Vue中我们除了可以自己实现过渡动画以外, 还可以结合第三方框架实现过渡动画

1.1导入Velocity库
1.2在动画执行过程钩子函数中编写Velocity动画


<div id="app">
    <button @click="toggle">我是按钮button>
    <transition appear
                v-bind:css="false"
                v-on:before-enter="beforeEnter"
                v-on:enter="enter"
                v-on:after-enter="afterEnter">
        <div class="box" v-show="isShow">div>
    transition>
div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js">script>
<script>
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
            isShow: true
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
            toggle(){
      
                this.isShow = !this.isShow;
            },
            beforeEnter(el){
      
            },
            enter(el, done){
      
                Velocity(el, {
      opacity: 1, marginLeft: "500px"}, 3000);
                done();
            },
            afterEnter(el){
      

            }
        },
        // 专门用于定义计算属性的
        computed: {
      
        }
    });
script>
body>
html>

自定义类名动画



<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>32-Vue-过渡动画title>
    <script src="js/vue.js">script>
    <style>
        *{
      
            margin: 0;
            padding: 0;
        }
        .box{
      
            width: 200px;
            height: 200px;
            background: red;
        }
        .a{
      
            opacity: 0;
        }
        .b{
      
            opacity: 1;
            margin-left: 500px;
        }
        .c{
      
            transition: all 3s;
        }
    style>
head>
<body>
1.自定义类名动画
在Vue中除了可以使用 默认类名(v-xxx)来指定过渡动画
       除了可以使用 自定义类名前缀(yyy-xx)来指定过渡动画(transition name="yyy")
       除了可以使用 JS钩子函数来指定过渡动画以外
还可以使用自定义类名的方式来指定过渡动画

enter-class  // 进入动画开始之前
enter-active-class // 进入动画执行过程中
enter-to-class // 进入动画执行完毕之后
leave-class  // 离开动画开始之前
leave-active-class // 离开动画执行过程中
leave-to-class // 离开动画执行完毕之后


<div id="app">
    <button @click="toggle">我是按钮button>
    <transition appear
                enter-class="a"
                enter-active-class="c"
                enter-to-class="b">
        <div class="box" v-show="isShow">div>
    transition>
div>
<script>
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
            isShow: true
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
            toggle(){
      
                this.isShow = !this.isShow;
            }
        },
        // 专门用于定义计算属性的
        computed: {
      
        }
    });
script>
body>
html>

配合Animate.css实现过渡动画



<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>33-Vue-过渡动画title>
    <script src="js/vue.js">script>
    <style>
        *{
      
            margin: 0;
            padding: 0;
        }
        .box{
      
            width: 200px;
            height: 200px;
            background: red;
        }
    style>
    <link href="https://cdn.jsdelivr.net/npm/[email protected]" rel="stylesheet" type="text/css">
head>
<body>



<div id="app">
    <button @click="toggle">我是按钮button>
    <transition appear
                enter-class=""
                enter-active-class="animated bounceInRight"
                enter-to-class="">
        <div class="box" v-show="isShow">div>
    transition>
div>
<script>
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
            isShow: true
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
            toggle(){
      
                this.isShow = !this.isShow;
            }
        },
        // 专门用于定义计算属性的
        computed: {
      
        }
    });
script>
body>
html>

同时给多个元素添加动画



<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>35-Vue-过渡动画title>
    <script src="js/vue.js">script>
    <style>
        *{
      
            margin: 0;
            padding: 0;
        }
        .v-enter{
      
            opacity: 0;
        }
        .v-enter-to{
      
            opacity: 1;
        }
        .v-enter-active{
      
            transition: all 3s;
        }
        .v-leave{
      
            opacity: 1;
        }
        .v-leave-to{
      
            opacity: 0;
        }
        .v-leave-active{
      
            transition: all 3s;
        }
    style>
head>
<body>


<div id="app">
    <form>
        <input type="text" v-model="name">
        <input type="submit" value="添加" @click.prevent="add">
    form>
    <ul>
        <transition-group appear>
        <li v-for="(person,index) in persons" :key="person.id" @click="del(index)">
            <input type="checkbox">
            <span>{
    {index}} --- {
    {person.name}}span>
        li>
        transition-group>
    ul>
div>
<script>
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
            persons: [
                {
      name: "zs", id: 1},
                {
      name: "ls", id: 2},
                {
      name: "ww", id: 3}
                ],
            name: ""
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
            add(){
      
                let lastPerson = this.persons[this.persons.length - 1];
                let newPerson = {
      name: this.name, id: lastPerson.id + 1};
                // this.persons.push(newPerson);
                this.persons.unshift(newPerson);
                this.name = "";
            },
            del(index){
      
                this.persons.splice(index, 1);
            }
        },
        // 专门用于定义计算属性的
        computed: {
      
        }
    });
script>
body>
html>

transition-group注意点以及动画混乱的原因



<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>36-Vue-过渡动画title>
    <script src="js/vue.js">script>
    <style>
        *{
      
            margin: 0;
            padding: 0;
        }
        .v-enter{
      
            opacity: 0;
        }
        .v-enter-to{
      
            opacity: 1;
        }
        .v-enter-active{
      
            transition: all 3s;
        }
        .v-leave{
      
            opacity: 1;
        }
        .v-leave-to{
      
            opacity: 0;
        }
        .v-leave-active{
      
            transition: all 3s;
        }
    style>
head>
<body>


<div id="app">
    <form>
        <input type="text" v-model="name">
        <input type="submit" value="添加" @click.prevent="add">
    form>

        <transition-group appear tag="ul">
        <li v-for="(person,index) in persons" :key="person.id" @click="del(index)">
            <input type="checkbox">
            <span>{
    {index}} --- {
    {person.name}}span>
        li>
        transition-group>

div>
<script>
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
            persons: [
                {
      name: "zs", id: 1},
                {
      name: "ls", id: 2},
                {
      name: "ww", id: 3}
                ],
            name: "",
            id: 3
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
            add(){
      
                this.id++;
                // let lastPerson = this.persons[this.persons.length - 1];
                let newPerson = {
      name: this.name, id: this.id};
                // this.persons.push(newPerson);
                this.persons.unshift(newPerson);
                this.name = "";
            },
            del(index){
      
                this.persons.splice(index, 1);
            }
        },
        // 专门用于定义计算属性的
        computed: {
      
        }
    });
script>
body>
html>

自定义全局组件



<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>37-Vue组件-自定义全局组件title>
    <script src="js/vue.js">script>
head>
<body>

Vue两大核心: 1.数据驱动界面改变 2.组件化
1.什么是组件? 什么是组件化?
1.1在前端开发中组件就是把一个很大的界面拆分为多个小的界面, 每一个小的界面就是一个组件
1.2将大界面拆分成小界面就是组件化

2.组件化的好处
2.1可以简化Vue实例的代码
2.2可以提高复用性

3.Vue中如何创建组件?
3.1创建组件构造器
3.2注册已经创建好的组件
3.3使用注册好的组件


<div id="app">
    
    <abc>abc>
div>
<script>
    // 3.1创建组件构造器
    let Profile = Vue.extend({
      
        // 注意点: 在创建组件指定组件的模板的时候, 模板只能有一个根元素
        template: `
           

我是描述信息

`
}); // 3.2注册已经创建好的组件 // 第一个参数: 指定注册的组件的名称 // 第二个参数: 传入已经创建好的组件构造器 Vue.component("abc", Profile ); // 这里就是MVVM中的View Model let vue = new Vue({ el: '#app', // 这里就是MVVM中的Model data: { }, // 专门用于存储监听事件回调函数 methods: { }, // 专门用于定义计算属性的 computed: { } });
script> body> html>

创建组件的其他方式



<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>38-Vue组件-自定义全局组件title>
    <script src="js/vue.js">script>
head>
<body>


<div id="app">
    
    <abc>abc>
div>

<template id="info">
    <div>
        <img src="images/fm.jpg"/>
        <p>我是描述信息p>
    div>
template>
<script>
    // 3.1创建组件构造器
    /*
    let Profile = Vue.extend({
        // 注意点: 在创建组件指定组件的模板的时候, 模板只能有一个根元素
        template: `
           

我是描述信息

` }); */
/* let obj = { // 注意点: 在创建组件指定组件的模板的时候, 模板只能有一个根元素 template: `

我是描述信息

` }; */
// 3.2注册已经创建好的组件 // 第一个参数: 指定注册的组件的名称 // 第二个参数: 传入已经创建好的组件构造器 // Vue.component("abc", Profile ); // Vue.component("abc", obj ); /* Vue.component("abc", { // 注意点: 在创建组件指定组件的模板的时候, 模板只能有一个根元素 template: `

我是描述信息

` }); */
Vue.component("abc", { // 注意点: 在创建组件指定组件的模板的时候, 模板只能有一个根元素 template: "#info" }); // 这里就是MVVM中的View Model let vue = new Vue({ el: '#app', // 这里就是MVVM中的Model data: { }, // 专门用于存储监听事件回调函数 methods: { }, // 专门用于定义计算属性的 computed: { } });
script> body> html>

自定义局部组件



<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>39-Vue组件-自定义局部组件title>
    <script src="js/vue.js">script>
head>
<body>

1.自定义全局组件特点
在任何一个Vue实例控制的区域中都可以使用

2.自定义局部组件特点
只能在自定义的那个Vue实例控制的区域中可以使用

3.如何自定义一个局部组件
在vue实例中新增components: {}
在{}中通过key/vue形式注册组件
components:{
   abc: {}
}


<div id="app1">
    <abc>abc>
div>
<div id="app2">
    <abc>abc>
div>
<template id="info">
    <div>
        <img src="images/fm.jpg"/>
        <p>我是描述信息p>
    div>
template>
<script>
    /*
    // 自定义全局组件
    Vue.component("abc", {
        // 注意点: 在创建组件指定组件的模板的时候, 模板只能有一个根元素
        template: "#info"
    });
     */
    // 这里就是MVVM中的View Model
    let vue1 = new Vue({
      
        el: '#app1',
        // 这里就是MVVM中的Model
        data: {
      
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
        },
        // 专门用于定义计算属性的
        computed: {
      
        }
    });
    // 这里就是MVVM中的View Model
    let vue2 = new Vue({
      
        el: '#app2',
        // 这里就是MVVM中的Model
        data: {
      
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
        },
        // 专门用于定义计算属性的
        computed: {
      
        },
        // 专门用于定义局部组件的
        components: {
      
            "abc": {
      
                // 注意点: 在创建组件指定组件的模板的时候, 模板只能有一个根元素
                template: "#info"
            }
        }
    });
script>
body>
html>

组件中使用data的注意点(在自定义组件中使用data必须赋值一个函数, 然后通过函数的返回值来定义有哪些数据)



<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>40-Vue组件-组件中的data和methodstitle>
    <script src="js/vue.js">script>
head>
<body>

1.自定义组件中的data和methods
Vue实例控制的区域相当于一个大的组件, 在大组件中我们可以使用data和methods
而我们自定义的组件也是一个组件, 所以在自定义的组件中也能使用data和methods

2.自定义组件中data注意点
在自定义组件中不能像在vue实例中一样直接使用data
而是必须通过返回函数的方式来使用data


<div id="app">
    
    <button @click="appFn">我是按钮button>
    
    <p>{
    {appMsg}}p>
    <abc>abc>
div>
<template id="info">
    <div>
        <img src="images/fm.jpg"/>
        
        <button @click="abcFn">我是按钮button>
        <p>{
    {abcMsg}}p>
    div>
template>
<script>
    // 自定义全局组件
    Vue.component("abc", {
      
        // 注意点: 在创建组件指定组件的模板的时候, 模板只能有一个根元素
        template: "#info",
        methods: {
      
            abcFn(){
      
                alert("abcFn");
            }
        },
        // data: {
      
        //     abcMsg: "学院"
        // }
        // 注意点: 虽然在自定义的组件中也可以使用data, 但是在使用的时候, 使用的方式和Vue实例中不太一样
        在自定义组件中使用data必须赋值一个函数, 然后通过函数的返回值来定义有哪些数据
        data: function () {
      
            return {
      
                abcMsg: "学院"
            }
        }
    });
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
            appMsg:"知播渔"
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
            appFn(){
      
                alert("appFn");
            }
        },
        // 专门用于定义计算属性的
        computed: {
      
        }
    });
script>
body>
html>

组件中的data为什么是一个函数

自定义组件中的datadata为什么是一个函数?
因为自定义组件可以复用, 为了保证复用时每个组件的数据都是独立的, 所以必须是一个函数



<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>41-Vue组件-组件中的data为什么是一个函数title>
    <script src="js/vue.js">script>
head>
<body>


<div id="app">
    <abc>abc>
    <abc>abc>
    <abc>abc>
div>
<template id="info">
    <div>
        <button @click="add">累加button>
        <p>{
    {number}}p>
    div>
template>
<script>
    // 自定义全局组件
    Vue.component("abc", {
      
        template: "#info",
        /*
        组件中的data如果不是通过函数返回的, 那么多个组件就会公用一份数据, 就会导致数据混乱
        如果组件中的data是通过函数返回的, 那么每创建一个新的组件, 都会调用一次这个方法
        将这个方法返回的数据和当前创建的组件绑定在一起, 这样就有效的避免了数据混乱
        * */
        data: function () {
      
            return {
      
                number: 0
            }
        },
        methods: {
      
            add(){
      
                this.number++;
            }
        }
    });
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
        },
        // 专门用于定义计算属性的
        computed: {
      
        }
    });
script>
body>
html>

组件切换

组件切换
对于普通的元素我们可以通过v-if来实现切换
对于组件我们也可以通过v-if来实现切换
因为组件的本质就是一个自定义元素

动态组件



<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>43-Vue组件-动态组件title>
    <script src="js/vue.js">script>
head>
<body>


<div id="app">
    <button @click="toggle">切换button>
    
    
    <keep-alive>
        <component v-bind:is="name">component>
    keep-alive>

div>
<template id="home">
    <div>
        <p>我是首页p>
        <input type="checkbox">
    div>
template>
<template id="photo">
    <div>
        <img src="images/fm.jpg" alt="">
    div>
template>
<script>
    // 自定义全局组件
    Vue.component("home", {
      
        template: "#home",
    });
    Vue.component("photo", {
      
        template: "#photo",
    });
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
            isShow: true,
            name: "home"
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
            toggle(){
      
                this.isShow = !this.isShow;
                this.name = this.name === "home" ? "photo" : "home";
            }
        },
        // 专门用于定义计算属性的
        computed: {
      
        }
    });
script>
body>
html>

组件动画

1.如何给组件添加动画?
给组件添加动画和过去给元素添加动画一样
如果是单个组件就使用transition
如果是多个组件就使用transition-group

2.过渡动画注意点
默认情况下进入动画和离开动画是同时执行的, 如果想一个做完之后再做另一个, 需要指定动画模式

父子组件

1.什么是父子组件?
在一个组件中又定义了其它组件就是父子组件
其实局部组件就是最简单的父子组件, 因为我们说过可以把Vue实例看做是一个大组件
我们在Vue实例中定义了局部组件, 就相当于在大组件里面定义了小组件, 所以实局部组件就是最简单的父子组件

2.如何定义其它的父子组件
前面我们说过, 自定义组件中可以使用data, 可以使用methods. 当然自定义组件中也可以使用components
所以我们也可以在自定义组件中再定义其它组件

父子组件的数据传递

1.父子组件数据传递?
在Vue中子组件是不能访问父组件的数据的,
如果子组件想要访问父组件的数据, 必须通过父组件传递

2.如何传递数据
2.1在父组件中通过v-bind传递数据
传递格式 v-bind:自定义接收名称 = “要传递数据”
2.2在子组件中通过props接收数据
接收格式 props: [“自定义接收名称”]

父子组件的方法传递

1.父子组件方法传递?
在Vue中子组件是不能访问父组件的方法的,
如果子组件想要访问父组件的方法, 必须通过父组件传递

2.如何传递方法
2.1在父组件中通过v-on传递方法
传递格式 v-on:自定义接收名称 = “要传递方法”
2.2在子组件中自定义一个方法
2.3在自定义方法中通过 this.$emit(‘自定义接收名称’);触发传递过来的方法

注意点: 和传递数据不同, 如果传递的是方法, 那么在子组件中不需要接收
如果传递的是方法, 那么需要在子组件中自定义一个方法
如果传递的是方法, 那么在子组件中直接使用自定义的方法即可
如果传递的是方法, 那么需要在子组件自定义的方法中通过
this.$emit(“自定义接收的名称”)的方法来触发父组件传递过来的方法



<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>49-Vue组件-子组件传递数据给父组件title>
    <script src="js/vue.js">script>
head>
<body>

1.如何将子组件数据传递给父组件
既然我们可以将父组件的方法传递给子组件
既然我们可以在子组件中调用父组件中的方法,
那么我们就可以在调用方法的时候给方法传递参数
传递的参数, 就是我们需要传递的数据


<div id="app">
    <father>father>
div>
<template id="father">
    <div>
        <button @click="say">我是按钮button>
        
        <son @parentsay="say">son>
    div>
template>
<template id="son">
    <div>
        <button @click="sonFn">我是按钮button>
    div>
template>
<script>
    // 父组件
    Vue.component("father", {
      
        template: "#father",
        methods: {
      
            say(data){
      
                // alert("www.it666.com");
                console.log(data);
            }
        },
        // 子组件
        components: {
      
            "son": {
      
                template: "#son",
                methods: {
      
                    sonFn(){
      
                        // 第一个参数: 需要调用的函数名称
                        // 后续的参数: 给调用的函数传递的参数
                        this.$emit("parentsay", "知播渔");
                    }
                }
            }
        }
    });
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
        },
        // 专门用于定义计算属性的
        computed: {
      
        },
        // 专门用于定义局部组件的
        components: {
      
        }
    });
script>
body>
html>

组件中的命名注意点

1.组件中的命名注意点
1.1注册组件的时候使用了"驼峰命名", 那么在使用时需要转换成"短横线分隔命名"
例如: 注册时: myFather -> 使用时: my-father
1.2在传递参数的时候如果想使用"驼峰名称", 那么就必须写"短横线分隔命名"
例如: 传递时: parent-name=“name” -> 接收时: props: [“parentName”]
1.3在传递方法的时候不能使用"驼峰命名", 只能用"短横线分隔命名"
@parent-say=“say” -> this.$emit(“parent-say”);

数据和方法的多级传递

1.数据和方法的多级传递
在Vue中如果儿子想使用爷爷的数据, 必须一层一层往下传递
在Vue中如果儿子想使用爷爷的方法, 必须一层一层往下传递



<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>51-Vue组件-数据和方法的多级传递title>
    <script src="js/vue.js">script>
head>
<body>


<div id="app">
    <grandfather>grandfather>
div>
<template id="grandfather">
    <div>
        <p>{
    {name}}p>
        <button @click="say">我是按钮button>
        <father :gfname="name" @gfsay="say">father>
    div>
template>
<template id="father">
    <div>
        <p>{
    {gfname}}p>
        <button @click="fatherFn">我是按钮button>
        <son :fname="gfname" @fsay="fatherFn">son>
    div>
template>
<template id="son">
    <div>
        <p>{
    {fname}}p>
        <button @click="sonFn">我是按钮button>
    div>
template>
<script>
    // 爷爷组件
    Vue.component("grandfather", {
      
        template: "#grandfather",
        data: function(){
      
            return {
      
                name: "lnj"
            }
        },
        methods: {
      
            say(){
      
                console.log("我是爷爷的方法");
            }
        },
        // 爸爸组件
        components: {
      
            "father": {
      
                template: "#father",
                props: ["gfname"],
                methods:{
      
                    fatherFn(){
      
                        this.$emit("gfsay");
                    }
                },
                // 儿子组件
                components: {
      
                    "son": {
      
                        template: "#son",
                        props: ["fname"],
                        methods: {
      
                            sonFn(){
      
                                this.$emit("fsay");
                            }
                        },
                    }
                }
            }
        }
    });
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
        },
        // 专门用于定义计算属性的
        computed: {
      
        },
        // 专门用于定义局部组件的
        components: {
      
        }
    });
script>
body>
html>

匿名插槽

1.什么是插槽?
默认情况下使用子组件时在子组件中编写的元素是不会被渲染的
如果子组件中有部分内容是使用时才确定的, 那么我们就可以使用插槽
插槽就是在子组件中放一个"坑", 以后由父组件来"填"

1.什么是匿名插槽
没有名字的插槽, 会利用使用时指定的能容替换整个插槽
注意点: 如果有多个匿名插槽, 每一个匿名插槽都会被指定的内容替换
虽然写多个匿名插槽不会报错, 但是在企业开发中推荐只能有一个匿名插槽



<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>52-Vue组件-匿名插槽title>
    <script src="js/vue.js">script>
head>
<body>


<div id="app">
    <father>father>
div>
<template id="father">
    <div>
        
        <son>
            
            <div>我是追加的内容1div>
            <div>我是追加的内容2div>
            <div>我是追加的内容3div>
        son>
    div>
template>
<template id="son">
    <div>
        <div>我是头部div>
        
        
        
        
        <slot>我是默认数据slot>

        <div>我是底部div>
    div>
template>
<script>
    // 父组件
    Vue.component("father", {
      
        template: "#father",
        // 子组件
        components: {
      
            "son": {
      
                template: "#son",
            }
        }
    });
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
        },
        // 专门用于定义计算属性的
        computed: {
      
        },
        // 专门用于定义局部组件的
        components: {
      
        }
    });
script>
body>
html>

具名插槽

1.什么是具名插槽
默认情况下有多少个匿名插槽, 我们填充的数据就会被拷贝多少份
这导致了所有插槽中填充的内容都是一样的
那么如果我们想给不同的插槽中填充不同的内容怎么办呢?
这个时候就可以使用具名插槽

2.具名插槽使用
通过插槽的name属性给插槽指定名称
在使用时可以通过slot="name"方式, 指定当前内容用于替换哪一个插槽

注意点: 如果没有指定要替换哪个插槽中的内容, 则不会被替换



<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>53-Vue组件-具名插槽title>
    <script src="js/vue.js">script>
head>
<body>


<div id="app">
    <father>father>
div>
<template id="father">
    <div>
        <son>
            
            <div slot="one">我是追加的内容1div>
            <div slot="one">我是追加的内容11div>
            <div slot="two">我是追加的内容2div>
            <div slot="two">我是追加的内容22div>
        son>
    div>
template>
<template id="son">
    <div>
        <div>我是头部div>
        
        
        <slot name="one">我是默认内容slot>
        <slot name="two">我是默认内容slot>
        <div>我是底部div>
    div>
template>
<script>
    // 父组件
    Vue.component("father", {
      
        template: "#father",
        // 子组件
        components: {
      
            "son": {
      
                template: "#son",
            }
        }
    });
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
        },
        // 专门用于定义计算属性的
        computed: {
      
        },
        // 专门用于定义局部组件的
        components: {
      
        }
    });
script>
body>
html>

v-slot指令

1.什么是v-slot指令?
v-slot指令是Vue2.6中用于替代slot属性的一个指令
在Vue2.6之前, 我们通过slot属性告诉Vue当前内容填充到哪一个具名插槽
从Vue2.6开始, 我们通过v-slot指令告诉Vue当前内容填充到哪一个具名插槽

注意点: v-slot指令只能用在template标签上
可以使用#号替代v-slot:



<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>54-Vue组件-v-slot指令title>
    <script src="js/vue.js">script>
head>
<body>


<div id="app">
    <father>father>
div>
<template id="father">
    <div>
        <son>
            
            
            
            
            <template #one>
                <div>我是追加的内容1div>
                <div>我是追加的内容11div>
            template>
            <template #two>
                <div>我是追加的内容2div>
                <div>我是追加的内容22div>
            template>
        son>
    div>
template>
<template id="son">
    <div>
        <div>我是头部div>
        <slot name="one">我是one默认内容slot>
        <slot name="two">我是two默认内容slot>
        <div>我是底部div>
    div>
template>
<script>
    // 父组件
    Vue.component("father", {
      
        template: "#father",
        // 子组件
        components: {
      
            "son": {
      
                template: "#son",
            }
        }
    });
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
        },
        // 专门用于定义计算属性的
        computed: {
      
        },
        // 专门用于定义局部组件的
        components: {
      
        }
    });
script>
body>
html>

作用域插槽

1.什么是作用域插槽
作用域插槽就是带数据的插槽, 就是让父组件在填充子组件插槽内容时也能使用子组件的数据

2.如何使用作用域插槽
2.1在slot中通过 v-bind:数据名称=“数据名称” 方式暴露数据
2.2在父组件中通过 接收数据
2.3在父组件的中通过 作用域名称.数据名称 方式使用数据



<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>55-Vue组件-作用域插槽title>
    <script src="js/vue.js">script>
head>
<body>


<div id="app">
    <father>father>
div>
<template id="father">
    <div>
        <son>

            
            
            <template slot-scope="abc">

                <li v-for="(name, index) in abc.names">{
    {name}}li>
            template>
        son>
    div>
template>
<template id="son">
    <div>
        <div>我是头部 {
    {names}}div>
        
        <slot v-bind:names="names">我是默认内容 {
    {names}}slot>
        <div>我是底部div>
    div>
template>
<script>
    // 父组件
    Vue.component("father", {
      
        template: "#father",
        // 子组件
        components: {
      
            "son": {
      
                template: "#son",
                data:function () {
      
                    return {
      
                        names: ["zs", "ls", "ww", "zl"]
                    }
                }
            }
        }
    });
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
        },
        // 专门用于定义计算属性的
        computed: {
      
        },
        // 专门用于定义局部组件的
        components: {
      
        }
    });
script>
body>
html>

v-slot指令取代slot-scope

在 2.6.0 中,我们为具名插槽和作用域插槽引入了一个新的统一的语法 (即 v-slot 指令)。
它取代了 slot 和 slot-scope

也就是说我们除了可以通过v-slot指令告诉Vue内容要填充到哪一个具名插槽中
还可以通过v-slot指令告诉Vue如何接收作用域插槽暴露的数据

v-slot:插槽名称=“作用域名称”



<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>56-Vue组件-v-slot指令title>
    <script src="js/vue.js">script>
head>
<body>


<div id="app">
    <father>father>
div>
<template id="father">
    <div>
        <son>
            
            
            
            <template #one="abc">
                <li v-for="(name, index) in abc.names">{
    {name}}li>
            template>
        son>
    div>
template>
<template id="son">
    <div>
        <div>我是头部 {
    {names}}div>

        <slot name="one" v-bind:names="names">我是默认内容 {
    {names}}slot>
        <div>我是底部div>
    div>
template>
<script>
    // 父组件
    Vue.component("father", {
      
        template: "#father",
        // 子组件
        components: {
      
            "son": {
      
                template: "#son",
                data:function () {
      
                    return {
      
                        names: ["zs", "ls", "ww", "zl"]
                    }
                }
            }
        }
    });
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
        },
        // 专门用于定义计算属性的
        computed: {
      
        },
        // 专门用于定义局部组件的
        components: {
      
        }
    });
script>
body>
html>

Vuex共享数据

1.什么是Vuex?
vuex 是 Vue 配套的 公共数据管理工具,它可以把一些共享的数据,保存到 vuex 中,
方便整个程序中的任何组件直接获取或修改我们的公共数据

注意点:
只有需要共享的才放到vuex上, 不需要共享的数据依然放到组件自身的data上

1.当前在企业开发中我们遇到了两个问题:
1.如果想要在子组件中使用祖先组件中的数据, 那么就必须一层一层的传递(非常麻烦)
2.兄弟组件之间不能直接传递数据, 如果兄弟组件之间想要传递数据, 那么就必须借助父组件(非常麻烦)
解决方案: 使用Vuex

2.什么是Vuex?
vuex 是 Vue 配套的 公共数据管理工具,我们可以将共享的数据保存到 vuex 中,
方便整个程序中的任何组件都可以获取和修改vuex中保存的公共数据

注意点:
必须在引入Vue之后再引入Vuex
只有需要共享的才放到vuex上, 不需要共享的数据依然放到组件自身的data上


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>58-Vuex-共享数据title>
    <script src="js/vue.js">script>
    
    
    <script src="js/vuex.js">script>
head>
<body>


<div id="app">
    <grandfather>grandfather>
div>
<template id="grandfather">
    <div>
        <p>{
    {this.$store.state.msg}}p>
        <father>father>
    div>
template>
<template id="father">
    <div>
        
        <p>{
    {this.$store.state.msg}}p>
        <son>son>
    div>
template>
<template id="son">
    <div>
        <p>{
    {this.$store.state.msg}}p>
    div>
template>

<script>
    // 2.创建Vuex对象
    const store = new Vuex.Store({
      
        // 这里的state就相当于组件中的data, 就是专门用于保存共享数据的
        state: {
      
            msg: "知播渔"
        },
    });
    // 爷爷组件
    Vue.component("grandfather", {
      
        template: "#grandfather",
        // 3.在祖先组件中添加store的key保存Vuex对象
        // 只要祖先组件中保存了Vuex对象 , 那么祖先组件和所有的后代组件就可以使用Vuex中保存的共享数据了
        store: store,
        // 爸爸组件
        components: {
      
            "father": {
      
                template: "#father",
                // 儿子组件
                components: {
      
                    "son": {
      
                        template: "#son",
                    }
                }
            }
        }
    });
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
        },
        // 专门用于定义计算属性的
        computed: {
      
        },
        // 专门用于定义局部组件的
        components: {
      
        },
    });
script>
body>
html>

修改数据


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>59-Vuex-修改共享数据title>
    <script src="js/vue.js">script>
    <script src="js/vuex.js">script>
head>
<body>

1.当前在企业开发中我们遇到了两个问题:
1.如果想要在子组件中使用祖先组件中的数据, 那么就必须一层一层的传递(非常麻烦)
2.兄弟组件之间不能直接传递数据, 如果兄弟组件之间想要传递数据, 那么就必须借助父组件(非常麻烦)
解决方案: 使用Vuex

2.什么是Vuex?
vuex 是 Vue 配套的 公共数据管理工具,它可以把一些共享的数据,保存到 vuex 中,
方便整个程序中的任何组件直接获取或修改我们的公共数据

注意点:
必须在引入Vue之后再引入Vuex
只有需要共享的才放到vuex上, 不需要共享的数据依然放到组件自身的data上


<div id="app">
    <father>father>
div>
<template id="father">
    <div>
        <son1>son1>
        <son2>son2>
    div>
template>
<template id="son1">
    <div>
        
        <button @click="add">增加button>
        <button @click="sub">减少button>
        <input type="text" :value="this.$store.state.count">
    div>
template>
<template id="son2">
    <div>

        <button @click="add">增加button>
        <button @click="sub">减少button>
        <input type="text" :value="this.$store.state.count">
    div>
template>

<script>
    const store = new Vuex.Store({
      
        // state: 用于保存共享数据
        state: {
      
            count: 0
        },
         mutations: 用于保存修改共享数据的方法
        mutations: {
      
            // 注意点: 在执行mutations中定义的方法的时候, 系统会自动给这些方法传递一个state参数
            //         state中就保存了共享的数据
            mAdd(state){
      
                state.count = state.count + 1;
            },
            mSub(state){
      
                state.count = state.count - 1;
            }
        }
    });
    // 爸爸组件
    Vue.component("father", {
      
        template: "#father",
        store: store,
        // 儿子组件
        components: {
      
            "son1": {
      
                template: "#son1",
                methods: {
      
                    add(){
      
                        // 注意点: 在Vuex中不推荐直接修改共享数据
                        // this.$store.state.count = this.$store.state.count + 1;
                        this.$store.commit("mAdd");
                    },
                    sub(){
      
                        // this.$store.state.count = this.$store.state.count - 1;
                        this.$store.commit("mSub");
                    }
                }
            },
            "son2": {
      
                template: "#son2",
                methods: {
      
                    add(){
      
                        // 注意点: 在Vuex中不推荐直接修改共享数据
                        // 如果多个组件都修改了共享的数据, 那么后期数据发生了错误, 我们如果需要去调试错误
                        // 就需要把每一个修改了共享数据的组件都检查一遍, 这样非常低效, 非常的不利于我们去维护
                        // this.$store.state.count = this.$store.state.count + 1;
                        this.$store.commit("mAdd");
                    },
                    sub(){
      
                        // this.$store.state.count = this.$store.state.count - 1;
                        this.$store.commit("mSub");
                    }
                }
            }
        }
    });
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
        },
        // 专门用于定义计算属性的
        computed: {
      
        },
        // 专门用于定义局部组件的
        components: {
      
        }
    });
script>
body>
html>

Vuex里面的getters

1.什么是Vuex的getters?
Vuex的getters属性就和组件的计算属性一样, 会将数据缓存起来, 只有数据发生变化才会重新计算


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>60-Vuex-getterstitle>
    <script src="js/vue.js">script>
    <script src="js/vuex.js">script>
head>
<body>


<div id="app">
    <father>father>
div>
<template id="father">
    <div>






        {
    {this.$store.getters.formart}}
        {
    {this.$store.getters.formart}}
        {
    {this.$store.getters.formart}}
    div>
template>

<script>
    const store = new Vuex.Store({
      
        // state: 用于保存共享数据
        state: {
      
            msg: "知播渔"
        },
        // mutations: 用于保存修改共享数据的方法
        mutations: {
      
        },
        getters: {
      
            formart(state){
      
                console.log("getters方法被执行了");
                return state.msg + "www.it666.com"
            }
        }
    });
    // 爸爸组件
    Vue.component("father", {
      
        template: "#father",
        store: store,
        // data: function () {
      
        //     return {
      
        //         msg: "知播渔"
        //     }
        // },
        // computed: {
      
        //     formart(){
      
        //         console.log("计算属性的方法被执行了");
        //         return this.msg + "www.it666.com";
        //     }
        // }
    });
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
      
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
        },
        // 专门用于定义计算属性的
        computed: {
      
        },
        // 专门用于定义局部组件的
        components: {
      
        }
    });
script>
body>
html>

Vue Router

1.什么是Vue Router?
Vue Router和v-if/v-show一样, 是用来切换组件的显示的
v-if/v-show是标记来切换(true/false)
Vue Router用哈希来切换(#/xxx)
比v-if/v-show强大的是Vue Router不仅仅能够切换组件的显示, 还能够在切换的时候传递参数

2.Vue Router使用
2.1导入Vue Router
2.2定义路由规则
2.3根据路由规则创建路由对象
2.4将路径对象挂载到Vue实例中
2.5修改URL哈希值
2.6通过渲染匹配的组件


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>62-VueRouter-基本使用title>
    <style>
        *{
      
            margin: 0;
            padding: 0;
        }
        .onepage, .twopage{
      
            width: 500px;
            height: 500px;
        }
        .onepage{
      
            background: pink;
        }
        .twopage{
      
            background: skyblue;
        }
        /*.router-link-active{*/
        /*    background: red;*/
        /*}*/
        .nj-active{
      
            background: skyblue;
        }
    style>
    <script src="js/vue.js">script>
    
    
    <script src="js/vue-router.js">script>
head>
<body>


<div id="app">
   
    
    
    <router-link to="/one" tag="button">切换到第一个界面router-link>
    <router-link to="/two" tag="button">切换到第二个界面router-link>
    
    
    <router-view>router-view>
div>
<template id="one">
    <div class="onepage">
        <p>我是第一个界面p>
    div>
template>
<template id="two">
    <div class="twopage">
        <p>我是第二个界面p>
    div>
template>
<script>

    // 1.定义组件
    const one = {
      
        template: "#one"
    };
    const two = {
      
        template: "#two"
    };
    // 2.定义切换的规则(定义路由规则)
    const routes = [
        // 重定向路由
        {
       path: '/', redirect: '/two' },
        // 数组中的每一个对象就是一条规则
        {
       path: '/one', component: one },
        {
       path: '/two', component: two }
    ];
    // 3.根据自定义的切换规则创建路由对象
    const router = new VueRouter({
      
        routes: routes,
        // 指定导航激活状态样式类名
        linkActiveClass: "nj-active"
    });

    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 4.将创建好的路由对象绑定到Vue实例上
        router: router,
        // 这里就是MVVM中的Model
        data: {
      
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
        },
        // 专门用于定义计算属性的
        computed: {
      
        },
        // 专门用于定义局部组件的
        components: {
      
            one: one,
            two: two
        }
    });
script>
body>
html>

VueRouter-参数传递

1.Vue Router传递参数
只要将Vue Router挂载到了Vue实例对象上, 我们就可以通过vue.$route拿到路由对象
只要能拿到路由对象, 就可以通过路由对象拿到传递的参数

方式一: 通过URL参数参数(?key=value&key=value), 通过this. r o u t e . q u e r y 获 取 方 式 二 : 通 过 占 位 符 传 递 ( 路 由 规 则 中 / : k e y / : k e y , 路 径 中 / v a l u e / v a l u e ) , 通 过 t h i s . route.query获取 方式二: 通过占位符传递(路由规则中/:key/:key, 路径中/value/value), 通过this. route.query:(/:key/:key,/value/value),this.route.params获取


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>63-VueRouter-参数传递title>
    <style>
        *{
      
            margin: 0;
            padding: 0;
        }
        .onepage, .twopage{
      
            width: 500px;
            height: 500px;
        }
        .onepage{
      
            background: pink;
        }
        .twopage{
      
            background: skyblue;
        }
        /*.router-link-active{*/
        /*    background: red;*/
        /*}*/
        .nj-active{
      
            background: skyblue;
        }
    style>
    <script src="js/vue.js">script>
    
    <script src="js/vue-router.js">script>
head>
<body>


<div id="app">
    
    <router-link to="/one?name=lnj&age=33" tag="button">切换到第一个界面router-link>
    
    <router-link to="/two/zs/66" tag="button">切换到第二个界面router-link>
    
    
    <router-view>router-view>
div>
<template id="one">
    <div class="onepage">
        <p>我是第一个界面p>
    div>
template>
<template id="two">
    <div class="twopage">
        <p>我是第二个界面p>
    div>
template>
<script>
    // 1.定义组件
    const one = {
      
        template: "#one",
        created: function () {
      
            console.log(this.$route);
            console.log(this.$route.query.name);
            console.log(this.$route.query.age);
        }
    };
    const two = {
      
        template: "#two",
        created: function () {
      
            console.log(this.$route);
            console.log(this.$route.params.name);
            console.log(this.$route.params.age);
        }
    };
    // 2.定义切换的规则(定义路由规则)
    const routes = [
        // 数组中的每一个对象就是一条规则
        {
       path: '/one', component: one },
        {
       path: '/two/:name/:age', component: two }
    ];
    // 3.根据自定义的切换规则创建路由对象
    const router = new VueRouter({
      
        routes: routes,
        linkActiveClass: "nj-active"
    });
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 4.将创建好的路由对象绑定到Vue实例上
        router: router,
        // 这里就是MVVM中的Model
        data: {
      
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
        },
        // 专门用于定义计算属性的
        computed: {
      
        },
        // 专门用于定义局部组件的
        components: {
      
            one: one,
            two: two
        }
    });
    // console.log(vue.$route);
script>
body>
html>

嵌套路由

1.什么是嵌套路由?
嵌套路由也称之为子路由, 就是在被切换的组件中又切换其它子组件
例如: 在one界面中又有两个按钮, 通过这两个按钮进一步切换one中的内容


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>64-VueRouter-嵌套路由title>
    <style>
        *{
      
            margin: 0;
            padding: 0;
        }
        .onepage, .twopage{
      
            width: 500px;
            height: 500px;
        }
        .onepage{
      
            background: pink;
        }
        .twopage{
      
            background: skyblue;
        }
        .onesub1page, .onesub2page{
      
            width: 100%;
            height: 300px;
        }
        .onesub1page{
      
            background: orangered;
        }
        .onesub2page{
      
            background: blueviolet;
        }
        .nj-active{
      
            background: skyblue;
        }
    style>
    <script src="js/vue.js">script>
    
    <script src="js/vue-router.js">script>
head>
<body>


<div id="app">
    <router-link to="/one" tag="button">切换到第一个界面router-link>
    <router-link to="/two" tag="button">切换到第二个界面router-link>
    
    
    <router-view>router-view>
div>
<template id="one">
    <div class="onepage">
        <p>我是第一个界面p>
        <router-link to="/one/onesub1" tag="button">切换到第一个子界面router-link>
        <router-link to="/one/onesub2" tag="button">切换到第二个子界面router-link>
        
        
        <router-view>router-view>
    div>
template>
<template id="onesub1">
    <div class="onesub1page">
        <p>我是第一个界面子界面1p>
    div>
template>
<template id="onesub2">
    <div class="onesub2page">
        <p>我是第一个界面子界面2p>
    div>
template>
<template id="two">
    <div class="twopage">
        <p>我是第二个界面p>
    div>
template>
<script>
    // 1.定义组件
    const onesub1 = {
      
        template: "#onesub1",
    };
    const onesub2 = {
      
        template: "#onesub2",
    };
    const one = {
      
        template: "#one",
        components:{
      
            onesub1:onesub1,
            onesub2: onesub2
        }
    };
    const two = {
      
        template: "#two"
    };
    // 2.定义切换的规则(定义路由规则)
    const routes = [
        // 数组中的每一个对象就是一条规则
        {
      
            path: '/one',
            component: one,
            children:[
                {
      
                    // 注意点: 如果是嵌套路由(子路由), 那么不用写一级路径的地址, 并且也不用写/
                    path: "onesub1",
                    component: onesub1
                },
                {
      
                    // 注意点: 如果是嵌套路由(子路由), 那么不用写一级路径的地址, 并且也不用写/
                    path: "onesub2",
                    component: onesub2
                }
            ]
        },
        // { path: '/one/onesub1', component: onesub1 },
        // { path: '/one/onesub2', component: onesub2 },
        {
       path: '/two', component: two }
    ];
    // 3.根据自定义的切换规则创建路由对象
    const router = new VueRouter({
      
        routes: routes,
        linkActiveClass: "nj-active"
    });
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 4.将创建好的路由对象绑定到Vue实例上
        router: router,
        // 这里就是MVVM中的Model
        data: {
      
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
        },
        // 专门用于定义计算属性的
        computed: {
      
        },
        // 专门用于定义局部组件的
        components: {
      
            one: one,
            two: two
        }
    });
    // console.log(vue.$route);
script>
body>
html>

命名视图


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>66-VueRouter-命名视图title>
    <style>
        *{
      
            margin: 0;
            padding: 0;
        }
        .onepage, .twopage{
      
            width: 200px;
            height: 200px;
        }
        .onepage{
      
            background: pink;
        }
        .twopage{
      
            background: skyblue;
        }
        .nj-active{
      
            background: skyblue;
        }
    style>
    <script src="js/vue.js">script>
    
    <script src="js/vue-router.js">script>
head>
<body>


<div id="app">
    
    
    
    
    
    <router-view name="name1">router-view>
    <router-view name="name2">router-view>
div>
<template id="one">
    <div class="onepage">
        <p>我是第一个界面p>
    div>
template>
<template id="two">
    <div class="twopage">
        <p>我是第二个界面p>
    div>
template>
<script>
    // 1.定义组件
    const one = {
      
        template: "#one",
    };
    const two = {
      
        template: "#two"
    };
    // 2.定义切换的规则(定义路由规则)
    const routes = [
        // 数组中的每一个对象就是一条规则
        {
      
            path: '/',
            components: {
      
                name1: one,
                name2: two
            }
        },
    ];
    // 3.根据自定义的切换规则创建路由对象
    const router = new VueRouter({
      
        routes: routes,
        linkActiveClass: "nj-active"
    });
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 4.将创建好的路由对象绑定到Vue实例上
        router: router,
        // 这里就是MVVM中的Model
        data: {
      
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
        },
        // 专门用于定义计算属性的
        computed: {
      
        },
        // 专门用于定义局部组件的
        components: {
      
            one: one,
            two: two
        }
    });
    // console.log(vue.$route);
script>
body>
html>

watch属性

1.什么是Watch属性?
Watch属性是专门用于监听数据变化的, 只要数据发生了变化, 就会自动调用对应数据的回调方法

2.Watch监听路由变化
Watch属性不仅仅能够监听数据的变化, 还能够监听路由地址的变化
在企业开发中我们可以通过Watch来判断当前界面是从哪个界面跳转过来的


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>67-VueRouter-Watch属性title>
    <script src="js/vue.js">script>
    <script src="js/vue-router.js">script>
head>
<body>


<div id="app">

    

    
    <a href="#/one">切换到第一个界面a>
    <a href="#/two">切换到第二个界面a>
    <router-view>router-view>
div>
<template id="one">
    <div class="onepage">
        <p>我是第一个界面p>
    div>
template>
<template id="two">
    <div class="twopage">
        <p>我是第二个界面p>
    div>
template>

<script>
    // 1.定义组件
    const one = {
      
        template: "#one",
    };
    const two = {
      
        template: "#two"
    };
    // 2.定义切换的规则(定义路由规则)
    const routes = [
        // 数组中的每一个对象就是一条规则
        {
       path: '/one', component: one },
        {
       path: '/two', component: two }
    ];
    // 3.根据自定义的切换规则创建路由对象
    const router = new VueRouter({
      
        routes: routes
    });

    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 4.将创建好的路由对象绑定到Vue实例上
        router: router,
        watch: {
      
            // 可以通过watch监听Model中数据的变化, 只要数据发生变化, 就会自动调用对应的回调函数
          num1: function (newValue, oldValue) {
      
              // console.log(this.num1);
              // console.log(newValue, oldValue);
              this.res = parseInt(this.num1) + parseInt(this.num2)
          },
          num2: function (newValue, oldValue) {
      
              this.res = parseInt(this.num1) + parseInt(this.num2)
          },
            // 可以通过watch监听路由地址的变化, 只要路由地址发生变化, 就会自动调用对应的回调函数
          "$route.path": function (newValue, oldValue) {
      
              console.log(newValue, oldValue);
          }
        },
        // 这里就是MVVM中的Model
        data: {
      
            num1: 0,
            num2: 0,
            res: 0
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
            change1(){
      
                this.res = parseInt(this.num1) + parseInt(this.num2)
            },
            change2(){
      
                this.res = parseInt(this.num1) + parseInt(this.num2)
            }
        },
        // 专门用于定义计算属性的
        computed: {
      
        },
        // 专门用于定义局部组件的
        components: {
      
            one: one,
            two: two
        }
    });
    console.log(vue.$route);
script>
body>
html>

生命周期方法

1.什么是生命周期方法?
和wbpack生命周期方法一样, 都是在从生到死的特定阶段调用的方法
PS: 生命周期钩子 = 生命周期函数 = 生命周期事件
2.Vue生命周期方法分类
2.1创建期间的生命周期方法
beforeCreate:在调用beforeCreate的时候, 仅仅表示Vue实例刚刚被创建出来
此时此刻还没有初始化好Vue实例中的数据和方法, 所以此时此刻还不能访问Vue实例中保存的数据和方法
created:在调用created的时候, 是我们最早能够访问Vue实例中保存的数据和方法的地方
beforeMount:在调用beforeMount的时候, 表示Vue已经编译好了最终模板, 但是还没有将最终的模板渲染到界面上
mounted:在调用mounted的时候, 表示Vue已经完成了模板的渲染, 表示我们已经可以拿到界面上渲染之后的内容了
2.2运行期间的生命周期方法
beforeUpdate:在调用beforeUpdate的时候, 表示Vue实例中保存的数据被修改了
注意点: 只有保存的数据被修改了才会调用beforeUpdate, 否则不会调用
注意点: 在调用beforeUpdate的时候, 数据已经更新了, 但是界面还没有更新
updated:在调用updated的时候, 表示Vue实例中保存的数据被修改了, 并且界面也同步了修改的数据了
也就是说: 数据和界面都同步更新之后就会调用updated
2.3销毁期间的生命周期方法
beforeDestroy:在调用beforeDestroy的时候, 表示当前组件即将被销毁了
注意点: 只要组件不被销毁, 那么beforeDestroy就不会调用
beforeDestroy函数是我们最后能够访问到组件数据和方法的函数
** destroyed**:在调用destroyed的时候, 表示当前组件已经被销毁了
注意点: 只要组件不被销毁, 那么destroyed就不会调用
不要在这个生命周期方法中再去操作组件中数据和方法


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>68-Vue-生命周期方法title>
    <script src="js/vue.js">script>
head>
<body>


<div id="app">
    <p>{
    {msg}}p>
div>


<script>
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        beforeCreate:function(){
      
            /*
            在调用beforeCreate的时候, 仅仅表示Vue实例刚刚被创建出来
            此时此刻还没有初始化好Vue实例中的数据和方法, 所以此时此刻还不能访问Vue实例中保存的数据和方法
            * */
            // console.log(this.msg);
            // console.log(this.say);
        },
        created:function(){
      
            /*
            在调用created的时候, 是我们最早能够访问Vue实例中保存的数据和方法的地方
            * */
            // console.log(this.msg);
            // console.log(this.say);
        },
        beforeMount:function(){
      
            /*
            在调用beforeMount的时候, 表示Vue已经编译好了最终模板, 但是还没有将最终的模板渲染到界面上
            * */
            // console.log(document.querySelector("p").innerHTML);
            // console.log(document.querySelector("p").innerText);
        },
        mounted:function(){
      
            /*
            在调用mounted的时候, 表示Vue已经完成了模板的渲染, 表示我们已经可以拿到界面上渲染之后的内容了
            * */
            console.log(document.querySelector("p").innerHTML);
            console.log(document.querySelector("p").innerText);
        },
        el: '#app',
        // 专门用于监听数据变化的
        watch: {
      
        },
        // 这里就是MVVM中的Model
        data: {
      
            msg: "知播渔"
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
            say(){
      
                console.log("say");
            }
        },
        // 专门用于定义计算属性的
        computed: {
      
        },
        // 专门用于定义局部组件的
        components: {
      
        }
    });
script>
body>
html>

ref属性

1.Vue特殊特性
Vue特点: 数据驱动界面更新, 无需操作DOM来更新界面
也就是说Vue不推荐我们直接操作DOM, 但是在企业开发中有时候我们确实需要拿到DOM操作DOM
那么如果不推荐使用原生的语法获取DOM, 我们应该如何获取DOM?
在Vue中如果想要拿到DOM元素我们可以通过ref来获取

2.ref使用
2.1在需要获取的元素上添加ref属性. 例如:

我是段落
2.2在使用的地方通过 this. r e f s . x x x 获 取 , 例 如 t h i s . refs.xxx获取, 例如 this. refs.xxx,this.ref.myppp

3.ref特点
ref添加到元素DOM上, 拿到的就是元素DOM
ref添加到组件上, 拿到的就是组件


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>71-Vue-特殊特性title>
    <script src="js/vue.js">script>
head>
<body>


<div id="app">
    <button @click="myFn">我是按钮button>
    <p ref="myppp">我是原生的DOMp>
    <one id="myOne" ref="myOne">one>
div>
<template id="one">
    <div>
        <p>我是组件p>
    div>
template>
<script>
    Vue.component("one", {
      
        template: "#one",
        data: function(){
      
            return {
      
                msg: "知播渔"
            }
        },
        methods: {
      
            say(){
      
                console.log("say");
            }
        },
    });
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        // 专门用于监听数据变化的
        watch: {
      
        },
        // 这里就是MVVM中的Model
        data: {
      
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
            myFn(){
      
                // 注意点: 如果是通过原生的语法来获取元素, 无论是原生的元素还是自定义的组件, 拿到的都是原生的元素
                // 注意点: 并且VUE官方并不推荐我们这样获取
                // console.log(document.querySelector("p"));
                // console.log(document.querySelector("#myOne"));

                // 在Vue中如果想获取原生的元素或者获取自定义的组件, 可以通过ref来获取
                // 注意点: ref如果是添加给元素的元素, 那么拿到的就是元素的元素
                //         ref如果是添加给自定义的组件, 那么拿到的就是自定义的组件
                console.log(this.$refs);
                console.log(this.$refs.myppp);
                console.log(this.$refs.myOne);
                console.log(this.$refs.myOne.msg);
                console.log(this.$refs.myOne.say);
            }
        },
        // 专门用于定义计算属性的
        computed: {
      
        },
        // 专门用于定义局部组件的
        components: {
      
        }
    });
script>
body>
html>

组件的第二种渲染方式-render

1.Vue渲染组件的两种方式
1.1先定义注册组件, 然后在Vue实例中当做标签来使用
1.2先定义注册组件, 然后通过Vue实例的render方法来渲染

2.两种渲染方法的区别
1.1当做标签来渲染, 不会覆盖Vue实例控制区域
1.2通过render方法来渲染, 会覆盖Vue实例控制区域


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>72-Vue-组件渲染方式title>
    <script src="js/vue.js">script>
head>
<body>


<div id="app">

div>
<template id="one">
    <div>
        <p>我是组件222p>
    div>
template>
<script>
    Vue.component("one", {
      
        template: "#one"
    });
    // 这里就是MVVM中的View Model
    let vue = new Vue({
      
        el: '#app',
        render: function(createElement){
      
            let html = createElement("one");
            return html;
        },
        // 专门用于监听数据变化的
        watch: {
      
        },
        // 这里就是MVVM中的Model
        data: {
      
        },
        // 专门用于存储监听事件回调函数
        methods: {
      
        },
        // 专门用于定义计算属性的
        computed: {
      
        },
        // 专门用于定义局部组件的
        components: {
      
        }
    });
script>
body>
html>

Vue-CLI

1.什么是Vue-CLI(Command Line Interface)?
Vue-CLI是vue官方提供的脚手架工具,
默认已经帮我们搭建好了一套利用webpack管理vue的项目结构

2.如何安装Vue-cli和使用Vue-CLI?
安装脚手架工具: npm install -g @vue/cli
检查是否安装成功: vue --version
通过脚手架创建项目: vue create project-name

3.通过Vue-CLI生成的项目结构解读
3.1在Vue-CLI2.x中生成的项目结构中我们能够看到build文件夹和config文件夹
这两个文件夹中存储了webpack相关的配置, 我们可以针对项目需求修改webpack配置
3.2在Vue-CLI3以后生成的项目结构中已经没有了build文件夹和config文件夹
这么做的目的是为了化繁为简, 让初学者不用关心webpack, 只用关心如何使用Vue

node_modules文件夹: 存储了依赖的相关的包
public文件夹: 任何放置在 public 文件夹的静态资源都会被简单的复制,
而不经过 webpack。你需要通过绝对路径来引用它们
一般用于存储一些永远不会改变的静态资源或者webpack不支持的第三方库
src文件夹: 代码文件夹
|----assets文件夹: 存储项目中自己的一些静态文件(图片/字体等)
|----components文件夹: 存储项目中的自定义组件(小组件,公共组件)
|----views文件夹: 存储项目中的自定义组件(大组件,页面级组件,路由级别组件)
|----router文件夹: 存储VueRouter相关文件
|----store文件夹: 存储Vuex相关文件
|----App.vue:根组件
|----main.js:入口js文件

你可能感兴趣的:(vue,vue,前端)