前端开发_9.Vue学习总结

Vue学习总结


前言

想必框架的学习对于一个前端势必不可少的。
So,那就学呗!

一、Vue是什么?

介绍

  • Vue(读音 /vjuː/, 类似于 view) 是一套构建用户界面的渐进式框架。
  • Vue 只关注视图层, 采用自底向上增量开发的设计。
  • Vue 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。

参考资料

  • 中文文档
  • 官方文档
  • https://github.com/vue3/vue3-News 源代码库
  • https://juejin.cn/post/6874585127658192910 //新特性
  • https://juejin.cn/post/6977929393511514148
#直接引入
<script src="https://cdn.staticfile.org/vue/3.0.5/vue.global.js"></script>
##一、常用内置指令:
1. v-text : 更新元素的 textContent 
2.  v-html : 更新元素的 innerHTML 
3. v-if : 如果为 true, 当前标签才会输出到页面 
4. v-else: 如果为 false, 当前标签才会输出到页面 
5. v-show : 通过控制 display 样式来控制显示/隐藏 
6. v-for : 遍历数组/对象 
7. v-on : 绑定事件监听, 一般简写为@ 
8. v-bind : 绑定解析表达式, 可以省略 v-bind 
9. v-model : 双向数据绑定 
10. v-cloak : 防止闪现, 与 css 配合: [v-cloak] { display: none }
## 二、自定义指令
1. 注册全局指令 
Vue.directive('my-directive', function(el, binding){ el.innerHTML = binding.value.toupperCase() }) 
2. 注册局部指令 
 directives : { 'my-directive' : { bind (el, binding) { el.innerHTML = binding.value.toupperCase() } } } 
#使用指令 v-my-directive='xxx'

#.三、 vue 生命周期分析
1) 初始化显示 * beforeCreate() * created() * beforeMount() * mounted()
2) 更新状态: this.xxx = value, * beforeUpdate() * updated() 
3) 销毁 vue 实例: vm.$destory(), * beforeDestory() * destoryed()
#1. mounted(): 发送 ajax 请求, 启动定时器等异步任务 
#2. beforeDestory(): 做收尾工作, 如: 清除定时器

一、理论知识:

MVVM 模型

  1. M:模型(Model) :对应 data 中的数据
  2. V:视图(View) :模板
  3. VM:视图模型(ViewModel) : Vue 实例对象
  • const是常量,let是变量,proxy是代理意思,release是开放版template模板

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

  • v-model 也可以将数据绑定到元素的属性,input、textarea、select标签表单元素
    其他标签的属性绑定数据用 v-bind

  • 系统预定义修饰符

## 事件处理
1. v-on 绑定的时间被触发之后,会去 Vue 实例对象的 methods 中查找对应的回调函数
2. 绑定回调函数名称的时候,后面可以加() 也可以不加@click="function";@click="function()"
 常见修饰符:
.once    - 只触发一次回调
.prevent - 调用 event.preventDefault() 阻止默认行为
.stop    - 调用 event.stopPropagation() 阻止事件冒泡
.self    - 只当事件是从侦听器绑定的元素本身触发时才触发回调
.capture - 添加事件侦听器时使用 capture 模式

- 可以给绑定的回调函数传递参数
@click="function('name', 'zsy')"
- 也可以传递原生事件对象
@click="function('name', 'zsy', $event)"
按键修饰符分类

## 指令
#自定义全局指令语法
Vue.directive('自定义指令名称', {
  声明周期名称: function (el) {
    指令业务逻辑代码
  }
})
#获取自定义指令传递的参数
#在执行自定义指令对应的方法的时候,除了会传递el给我们,
#还会传递一个对象,这个对象中就保存了指令传递过来的参数。
#如何自定义局部指令
directives: {
    'color': {
        bind: function (el, binding) {
            el.style.color = binding.value
        }
    }
}

## 计算属性
 注意点:
- 虽然在定义计算属性的时候是通过一个函数返回的数据,
  但是在使用计算属性的时候不能在计算属性名称后面加上小括号,
  因为他是一个属性不是一个函数(方法)
1. 通过函数和计算属性都能实现上面的需求,区别是什么?
- 函数特点:每次调用都会执行
- 计算属性特点:只要返回的结果没有发生变化,计算属性只会执行一次
2. 计算属性的应用场景
由于计算属性会将返回的结果缓存起来,所以如果返回的数据不经常发生变化使用计算属性的性能要比使用函数的性能高

## 过滤器
1. 过滤器
过滤器和函数和计算属性一样都是用来处理数据的
但是过滤器一般用于格式化插入的文本数据
2. 如何自定义全局过滤器
Vue.filter('过滤器名称', 过滤器处理函数(要处理的数据))
3. 如何使用全局过滤器
{{msg | 过滤器名称}}
:value="msg | 过滤器名称"
4. 如何自定义一个局部指令
给创建 Vue 实例时传递的对象添加
filters: {
    // key: 过滤器名称
    // value: 过滤器处理函数
    'formatStr': function(value) {}
}
5. 注意点
- 只能在插值语法和 v-bind 中使用
- 过滤器可以连续使用



##插槽
注意点:
插槽可以指定默认数据,如果使用者没有填充值,就会使用默认数据

1. 什么是插槽?
Vue中使用 slot 标签代表一个插槽,插槽中可以被替换为任何模板代码,包括html
2. 为什么要使用插槽?
默认情况下是不能在使用子组件的时候给子组件动态添加内容的,如果想给子组件动态添加内容,那么就必须使用插槽。
3. 匿名插槽
插槽是可以指定名称的,如果没有指定名称,那么称之为匿名插槽
匿名插槽的特点:有多少个匿名插槽,填充的数据就会被拷贝几份,一般只写一个匿名插槽
4. 什么是具名插槽
默认情况下有多少个匿名插槽,我们填充的数据就会被拷贝多少份,这导致了所有插槽内填充的内容都是一样的
那么如果我们想给不同的插槽填充不同的内容,就需要使用具名插槽。
5. 具名插槽使用
通过插槽的name属性给插槽指定名称
在使用时可以通过slot='name' 方式,指定当前内容用于替换哪一个插槽

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

2. 如何使用作用域插槽
- 在 slot 中通过 v-bind:数据名称='数据名称' 的方式暴露数据
- 在父组件中通过 <template slot-scope='作用域名称'> 接收数据
- 在父组件的 <template></template> 中通过 作用域名称.数据名称 方式使用数据

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

使用方法
v-slot:插槽名称='作用域名称'

3. 作用域插槽的应用场景
子组件提供数据,父组件决定如何渲染
-->

编程式路由导航

相关 API:

  1. this.$router.push(path): 相当于点击路由链接(可以返回到当前路由界面)
  2. this.$router.replace(path): 用新路由替换当前路由(不可以返回到当前路由界面)
  3. this.$router.back(): 请求(返回)上一个记录路由
  4. this.$router.go(-1): 请求(返回)上一个记录路由
  5. this.$router.go(1): 请求下一个记录路由

路由的理解

  1. 什么是路由? 1. 一个路由就是一组映射关系(key - value) 2. key 为路径, value 可能是 function 或 component
  2. . 路由分类 1. 后端路由: 1) 理解:value 是 function, 用于处理客户端提交的请求。 2) 工作过程:服务器接收到一个请求时, 根据请求路径找到匹配的函数 来处理请求, 返回响应数据。 2. 前端路由: 1) 理解:value 是 component,用于展示页面内容。 2) 工作过程:当浏览器的路径改变时, 对应的组件就会显示。

vue-router 的理解

vue 的一个插件库,专门用来实现 SPA 应用
6.1.2 对 SPA 应用的理解

  1. 单页 Web 应用(single page web application,SPA)。
  2. 整个应用只有一个完整的页面。
  3. 点击页面中的导航链接不会刷新页面,只会做页面的局部更新。
  4. 数据需要通过 ajax 请求获取。

二、实战案例

1.基本模板

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>demo</title>
    <style>
        [v-cloak] {
            display: none;
        }
    </style>
</head>
<body>
<script src="../js/vue.js"></script>
<div id="app">
    <p v-once>你的名字:{{name}} <small>(只渲染一次v-once)</small></p>
    <p v-cloak>你的名字:{{name}}<small>(v-cloak 指令作用:数据渲染之后自动显示元素)</small></p>
    <p>你的名字:{{name}}<small>(跟着变化)</small></p>
    <button @click="btn1">点我</button>
    <small>(事件处理@click)</small><br>
    <!--<input> <textarea><select> 元素上可以用 v-model 指令创建双向数据绑定;-->
    <input type="text" v-model="name"><small>(双向绑定v-model)</small>
<!--    但是如果想要给"元素的属性"绑定数据,就必须使用 v-bind-->
    <input type="text" v-bind:value="name+'单向绑定v-bind'"/>
    <input type="text" :value="name + 'test'"/>
    <p>----------------------------------------------------</p>
    <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>
    <p>----------------------------------------------------</p>
    <p v-if="show">我是true(v-if)</p>
    <p v-if="hidden">我是false</p>

    <p v-if="score >= 80">优秀</p>
    <p v-else-if="score >= 60">良好</p>
    <p v-else>一般</p>
    <p>----------------------------------------------------</p>
    <h3 v-show="show">我是true(v-show)</h3>
    <h3 v-show="hidden">我是false</h3>
    <p>----------------------------------------------------</p>
    <ul>
        <li v-for="(value, index) in list"> {{index}} - {{value}}</li>
    </ul>
    <ul>
        <li v-for="(value, index) in string"> {{index}} - {{value}}</li>
    </ul>
    <ul>
        <li v-for="(value, index) in numbers"> {{index}} - {{value}}</li>
    </ul>
    <ul>
        <li v-for="(value, key,index) in object"> {{key}} - {{value}}--{{index}}</li>
    </ul>
    <p>----------------------------------------------------</p>


</div>
<script>
   
    const obj = {
        name: "zy",
        msg: '<span>This is span</span>',
        show: true,
        hidden: false,
        age: 18,
        score: 30,
        list: ['zs', 'ls', 'ww', 'zl'],
        string: 'zsy',
        numbers: '12345',
        object: {
            name: 'zsy',
            age: '18',
            github: 'https://github.com/zsy0216'
        }
    }

    const vue = new Vue({
        el: "#app",
        data: obj,
        methods: {
            btn1() {
                this.name = "zzy"
            },
        }
    })

</script>
</body>
</html>

2.Vue指令通过 v-bind 绑定类名格式

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>demo</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        .size {
            font-size: 30px;
        }
        .color {
            color: red;
        }
        .active {
            background: skyblue;
        }
    </style>
</head>
<body>
<script src="../js/vue.js"></script>
<div id="app">
    <!--    通过 v-bind 绑定类名格式-->
    <p class="size color active"> 这是段落 </p>
    <p :class="['size', 'color', 'active']"> 这是段落1: 通过数组绑定 class </p>
    <p :class="['size', 'color', flag ? 'active' : '']"> 这是段落2 通过三目运算符绑定 class </p>
    <p :class="['size', 'color', {'active' : false}]"> 这是段落3:通过对应绑定 class </p>
    <p :class="object"> 这是段落4: 通过实例中的对象来绑定 class </p>
    <br><hr>
    <p :style="{color: 'red'}">这是段落1</p>
    <p :style="object1">这是段落2</p>
    <p :style="[object1, blueObj]">这是段落3</p>
</div>
<script>
    //const是常量,let是变量,proxy是代理意思,release是开放版template模板
    //代码规范大型项目为2个空格
    const obj = {
        flag: false,
        object: {
            size: false,
            color: true,
            active: true
        },
        object1:{
            color: 'red',
            'font-size': '30px'
        },
        blueObj: {
            background: 'skyblue'
        }
    }

    const vue = new Vue({
        el: "#app",
        data: obj,
        methods: {
            btn1() {
                this.name = "zzy"
            },
        }
    })

</script>
</body>
</html>

3.Vue指令v-on

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>13-Vue指令v-on</title>
    <script src="../js/vue.js"></script>
    <style>
        * {margin: 0;padding: 0;}
        .a {width: 300px;height: 300px;background: red;}
        .b {width: 200px;height: 200px;background: blue;}
        .c {width: 100px;height: 100px;background: green;}
    </style>
</head>
<body>
<div id="app">
    <button v-on:click="click">Button</button>
    <button @click="click">Button2</button>

    <button @click.once="click">事件修饰符 .once</button>
    <a href="#" @click.prevent="click">事件修饰符 .prevent</a>
    <a href="#" @click.prevent @click.prevent @click.capture="click">事件修饰符 .prevent</a>

    <!-- 默认情况下,嵌套的元素中如果都监听了相同的事件,那么会触发事件冒泡 -->
    <div class="a" @click="fn1">
        <div class="b" @click="fn2">
            <div class="c" @click.stop="fn3">事件修饰符 .stop</div>
        </div>
    </div>

    <!-- .self 只有当前元素的事件被触发时才会执行 -->
    <div class="a" @click="fn1">
        <div class="b" @click.self="fn2">
            <div class="c" @click="fn3">事件修饰符 .self</div>
        </div>
    </div>

    <!-- 默认情况下是事件冒泡,.capture可以转换成事件捕获 -->
    <div class="a" @click.capture="fn1">
        <div class="b" @click.capture="fn2">
            <div class="c" @click.capture="fn3">事件修饰符 .capture</div>
        </div>
    </div>
<!--    https://cn.vuejs.org/v2/guide/events.html#%E6%8C%89%E9%94%AE%E4%BF%AE%E9%A5%B0%E7%AC%A6-->
    按键修饰符:<input type="text" @keyup="handleKeyUp()" size="124%" value="其他特殊按键修饰符参考:"/>
</div>
</body>
<script>
    /* 1. 创建 vue 实例对象 VM */
    let vm = new Vue({
        // 2. 声明vue的实例对象控制页面的哪个区域 View
        el: '#app',
        // 3. 声明vue控制区域可以使用的数据 Model
        data: {
        },
        methods: {
            click() {alert("button clicked")},
            fn1() {alert("红色")},
            fn2() {alert("蓝色")},
            fn3() {alert("绿色")},
            handleKeyUp(){alert("按下了键盘")}
        }
    })
</script>
</html>

4.Vue自定义全局,局部指令

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>14-Vue自定义全局指令</title>
    <script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
    <!-- 自定义指令 v-red 使字体变为红色 -->
    <p v-red>这是段落</p>
    <!-- 自定义指令 v-color 传参 -->
    <p v-color="color">这是段落传递颜色参数</p>
    <!-- 自定义指令 v-focus 渲染之后被选中有光标 -->
    <input type="text" v-focus/>
    <p>{{test}}</p>
</div>
<div id="app1">
    <p v-style="'blue'">这是段落1 使用了全局指令</p>
    <p v-color="'blue'">这是段落1 使用了局部指令</p>
</div>
<div id="app2">
    <p v-style="'red'">这是段落2 使用了全局指令</p>
    <p v-color="'red'">这是段落2 使用了局部指令</p>
</div>
</body>
<script>
    Vue.directive('style', {
        // el: 被绑定指令的元素
        bind: function (el, binding) {
            el.style.color = binding.value
        }
    })
    /* 自定义指令 v-red */
    Vue.directive('red', {
        // el: 被绑定指令的元素
        bind: function (el) {
            el.style.color = 'red'
        }
    })
    /* 自定义指令 v-color */
    Vue.directive('color', {
        // el: 被绑定指令的元素
        bind: function (el, binding) {
            el.style.color = binding.value
        }
    })
    Vue.directive('focus', {
        // el: 被绑定指令的元素
        inserted: function (el) {
            el.focus()
        }
    })

    /* 1. 创建 vue 实例对象 VM */
    let vm = new Vue({
        // 2. 声明vue的实例对象控制页面的哪个区域 View
        el: '#app',
        // 3. 声明vue控制区域可以使用的数据 Model
        data: {
            color: 'blue',
            test:'----------------------------'
        },
        methods: {}
    })

    /* 2. 创建 vue 实例对象 VM 局部指令*/
    let vm1 = new Vue({
        // 2. 声明vue的实例对象控制页面的哪个区域 View
        el: '#app1',
        // 3. 声明vue控制区域可以使用的数据 Model
        data: {
        },
        methods: {
        }
    })

    let vm2 = new Vue({
        // 2. 声明vue的实例对象控制页面的哪个区域 View
        el: '#app2',
        // 3. 声明vue控制区域可以使用的数据 Model
        data: {
        },
        methods: {
        },
        directives: {
            'color': {
                bind: function (el, binding) {
                    el.style.color = binding.value
                }
            }
        }
    })
</script>
</html>

5.Vue计算属性

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>16-Vue计算属性</title>
    <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
    <p> {{name}} </p>
    <p> {{age + 1}} </p>
    <p> {{msg.split("").reverse().join("")}} </p>
    <p> {{handleMsg}} </p>
</div>
</body>
<script>
    /* 1. 创建 vue 实例对象 */
    let vm = new Vue({
        // 2. 声明vue的实例对象控制页面的哪个区域
        el: '#app',
        // 3. 声明vue控制区域可以使用的数据
        data: {
            name: 'zsy',
            age: 18,
            msg: "6120ysz/moc.buhtig//:sptth"
        },
        // 定义计算属性
        computed: {
            handleMsg: function() {
                let res = this.msg.split("").reverse().join("");
                return res;
            }
        }
    })
</script>
</html>

6.Vue计算属性和函数

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>17-Vue计算属性和函数</title>
    <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
    <p>通过计算属性处理:{{cptMsg}} </p>
    <p>通过计算属性处理:{{cptMsg}} </p>
    <p>通过计算属性处理:{{cptMsg}} </p>
    <p>通过计算属性处理:{{cptTime}}</p>

    <p>通过方法处理: {{fnMsg()}} </p>
    <p>通过方法处理: {{fnMsg()}} </p>
    <p>通过方法处理: {{fnMsg()}} </p>
    <p>通过方法处理:{{fnTime}}</p>
</div>
</body>
<script>
    /* 1. 创建 vue 实例对象 */
    let vm = new Vue({
        // 2. 声明vue的实例对象控制页面的哪个区域
        el: '#app',
        // 3. 声明vue控制区域可以使用的数据
        data: {
            name: 'zsy',
            age: 18,
            msg: "6120ysz/moc.buhtig//:sptth",
            fnTime: 0,
            cptTime: 0
        },
        methods: {
            fnMsg() {
                this.fnTime++
                return this.msg.split("").reverse().join("");
            }
        },
        // 定义计算属性
        computed: {
            cptMsg: function() {
                this.cptTime++
                let res = this.msg.split("").reverse().join("");
                return res;
            }
        }
    })
</script>
</html>

7.Vue自定义全局过滤器

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>18-Vue自定义全局过滤器</title>
    <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
    <!--  Vue会把name交给指定的过滤器处理之后,再把处理之后的结果插入元素  -->
    <p>{{name | formatStr | formatStr2}}</p>
</div>
</body>
<script>
    <!--  自定义全局过滤器  -->
    /*
        参数1:过滤器名称
        参数2:处理数据的函数
        注意点:默认情况下处理数据的函数接收一个参数,就是当前要被处理的数据
    * */
    Vue.filter('formatStr', (value) => {
        value = value.replace(/学院/g, '大学')
        return value
    });

    Vue.filter('formatStr2', (value) => {
        value = value.replace(/大学/g, '幼儿园')
        return value
    });

    /* 1. 创建 vue 实例对象 */
    let vm = new Vue({
        // 2. 声明vue的实例对象控制页面的哪个区域
        el: '#app',
        // 3. 声明vue控制区域可以使用的数据
        data: {
            name: '北京学院, 南京学院, 东京学院'
        }
    })
</script>
</html>

8.Vue自定义局部过滤器

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>19-Vue自定义局部过滤器</title>
    <script src="js/vue.js"></script>
</head>
<body>
<div id="app1">
    {{ ok ? 'YES' : 'NO' }}<br>
    {{ message.split("").reverse().join("") }}
    {{text.split('').reverse().join('')}}
    <!--  Vue会把name交给指定的过滤器处理之后,再把处理之后的结果插入元素  -->
    <p>{{name | formatStr}}</p>
</div>
<div id="app2">
    <p>{{name | formatStr}}</p>
</div>
</body>
<script>
    /* 1. 创建 vue 实例对象 */
    let vm1 = new Vue({
        // 2. 声明vue的实例对象控制页面的哪个区域
        el: '#app1',
        // 3. 声明vue控制区域可以使用的数据
        data: {
            name: '北京学院, 南京学院, 东京学院',
            text: "一心前朝"
        },
        // 定义局部过滤器
        filters: {
            'formatStr': (value) => {
                return value.replace(/学院/g, "大学")
            }
        }
    })
    let vm2 = new Vue({
        // 2. 声明vue的实例对象控制页面的哪个区域
        el: '#app2',
        // 3. 声明vue控制区域可以使用的数据
        data: {
            name: '北京学院, 南京学院, 东京学院'
        }
    })
</script>

9.Vue过滤器练习-格式化时间

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>20-Vue过滤器练习-格式化时间</title>
  <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
  <h2>{{ time | dateFormat("yyyy-MM-dd") }}</h2>
</div>
</body>
<script>
  /*
  * 注意点:在使用过滤器的时候,可以在过滤器名称后面加上() 传递参数
  * */
  Vue.filter("dateFormat", function (value, format){
    let date = new Date(value)
    let year = date.getFullYear()
    let month = date.getMonth() + 1 + ""
    let day = date.getDay() + ""
    let hour = date.getHours() + ""
    let minute = date.getMinutes() + ""
    let second = date.getSeconds() + ""
    if (format && format === "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")}`
  })

  /* 1. 创建 vue 实例对象 */
  let vm = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    data: {
      time: Date.now()
    }
  })
</script>
</html>

10.Vue学生管理系统

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>21-Vue学生管理系统</title>
  <script src="js/vue.js"></script>
  <style>
      * {
          margin: 0;
          padding: 0;
      }

      #app {
          width: 800px;
          margin: 50px auto;
      }

      table {
          width: 100%;
          background: #000;
      }

      table tr {
          background: #fff;
      }

      form {
          width: 100%;
          display: flex;
          justify-content: space-between;
      }
  </style>
</head>
<body>
<div id="app">
  <form v-show="isShow">
    <input type="text" placeholder="请输入序号" v-model="person.id"/>
    <input type="text" placeholder="请输入名称" v-model="person.name"/>
    <input type="text" placeholder="请输入分数" v-model="person.score"/>
    <input type="submit" @click.prevent="add" value="新增"/>
    <input type="submit" @click.prevent="query" value="查询"/>
  </form>
  <table>
    <tr>
      <th>序号</th>
      <th>姓名</th>
      <th>分数</th>
      <th>时间</th>
      <th>操作</th>
    </tr>
    <tr v-for="(person, index) in persons">
      <td><input type="text" v-model="person.id" :disabled="isDisabled"/></td>
      <td><input type="text" v-model="person.name" :disabled="isDisabled"/></td>
      <td><input type="text" v-model="person.score" :disabled="isDisabled"/></td>
      <td><input type="text" :value="person.time | dateFormat" disabled/></td>
      <td>
        <a href="#" @click.prevent="edit">编辑</a>
        <a href="#" @click.prevent="remove(index)">删除</a><br/>
        <a href="#" @click.prevent="toggle">更多操作</a>
      </td>
    </tr>
  </table>
</div>
</body>
<script>
  <!-- 日期格式化 过滤器 -->
  Vue.filter("dateFormat", function (value, format) {
    let date = new Date(value)
    let year = date.getFullYear()
    let month = date.getMonth() + 1 + ""
    let day = date.getDay() + ""
    let hour = date.getHours() + ""
    let minute = date.getMinutes() + ""
    let second = date.getSeconds() + ""
    if (format && format === "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")}`
  })

  /* 1. 创建 vue 实例对象 */
  let vm = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    data: {
      isDisabled: true,
      isShow: false,
      persons: [{
        id: 1,
        name: "zs",
        score: "99",
        time: Date.now()
      }, {
        id: 2,
        name: "ls",
        score: "88",
        time: Date.now()
      }, {
        id: 3,
        name: "ww",
        score: "88",
        time: Date.now()
      }],
      person: {
        id: "",
        name: "",
        score: ""
      }
    },
    methods: {
      edit() {
        this.isDisabled = !this.isDisabled
      },
      toggle() {
        this.isShow = !this.isShow
      },
      remove(index) {
        this.persons.splice(index, 1)
      },
      add() {
        this.person.time = Date.now()
        this.persons.push(this.person)
        this.person = {
          id: "",
          name: "",
          score: ""
        }
      },
      query() {
        let search = this.persons.filter((person) => {
          if (person.score === this.person.score) {
            return true
          }
        })
        this.persons = search
      }
    }
  })
</script>
</html>

11.Vue过渡动画

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>22-Vue过渡动画</title>
  <script src="js/vue.js"></script>
  <style>
      .box {
          margin-top: 50px;
          width: 200px;
          height: 200px;
          background: #ff0000;
      }
      .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;
      }

      .new-enter {
          opacity: 0;
      }
      .new-enter-to {
          margin-left: 300px;
          opacity: 1;
      }
      .new-enter-active {
          transition: all 3s;
      }
      .new-leave {
          opacity: 1;
      }
      .new-leave-to {
          opacity: 0;
      }
      .new-leave-active {
          transition: all 1s;
      }
  </style>
</head>
<body>
<div id="app">
  <button @click="toggle">切换显示状态</button>
  <transition>
    <div class="box" v-show="isShow"></div>
  </transition>

  <transition appear name="new">
    <div class="box" v-show="isShow"></div>
  </transition>
</div>
</body>
<script>
  /* 1. 创建 vue 实例对象 */
  let vm = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    data: {
      isShow: true
    },
    methods: {
      toggle() {
        this.isShow = !this.isShow
      }
    }
  })
</script>
</html>

12.Vue过渡动画-JS钩子

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>23-Vue过渡动画-JS钩子</title>
  <script src="js/vue.js"></script>
  <style>
      .box {
          margin-top: 50px;
          width: 200px;
          height: 200px;
          background: #ff0000;
      }

  </style>
</head>
<body>
<div id="app">
  <button @click="toggle">切换显示状态</button>
  <!--
  注意点:虽然我们是通过JS钩子函数来实现过渡动画,但是Vue默认还是会去查找类名。
  为了不让Vue去查找类名,可以给transition添加 v-bind:css="false"
  -->
  <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>
</body>
<script>
  /* 1. 创建 vue 实例对象 */
  let vm = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    data: {
      isShow: true
    },
    methods: {
      toggle() {
        this.isShow = !this.isShow
      },
      // 第一个参数代表执行动画的元素
      beforeEnter(el) {
        // 进入动画之前
        el.style.opacity = "0"

      },
      // 第二个参数 done 回调函数说明动画指定完毕,不调用后面afterEnter不会执行
      enter(el, done) {
        // 进入动画过程中
        /*
        * 注意点:如果是通过JS钩子来实现过渡动画
        * 那么必须在动画执行过程中的钩子函数中添加上
        * el.offsetWidth 或 el.offsetHeight
        * */
        // el.offsetWidth
        el.offsetHeight
        el.style.transition = "all 3s"
        // done()
        /*
        * 注意点:如果想让元素一进来就有动画,除了设置appear外,最好延迟调用 done 回调函数
        * */
        setTimeout(() => {
          done()
        }, 0)
      },
      afterEnter(el) {
        // 进入动画执行完毕
        el.style.opacity = "1"
        el.style.marginLeft = "300px"
      }
    }
  })
</script>
</html>

13.Vue过渡动画-Velocity

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>24-Vue过渡动画-Velocity</title>
  <script src="js/vue.js"></script>
  <style>
      .box {
          margin-top: 50px;
          width: 200px;
          height: 200px;
          background: #ff0000;
      }
  </style>
</head>
<body>
<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>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script>
<script>
  /* 1. 创建 vue 实例对象 */
  let vm = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    data: {
      isShow: true
    },
    methods: {
      toggle() {
        this.isShow = !this.isShow
      },
      // 第一个参数代表执行动画的元素
      beforeEnter(el) {
        // 进入动画之前
        el.style.opacity = "0"

      },
      // 第二个参数 done 回调函数说明动画指定完毕,不调用后面afterEnter不会执行
      enter(el, done) {
        // 进入动画过程中
        Velocity(el, {opacity: 1, marginLeft: "300px"}, 3000)
        done()
      },
      afterEnter(el) {
        // 进入动画执行完毕
        el.style.opacity = "1"
        el.style.marginLeft = "300px"
      }
    }
  })
</script>
</html>

14.Vue过渡动画-自定义类名

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>25-Vue过渡动画-自定义类名</title>
  <script src="js/vue.js"></script>
  <style>
      .box {
          margin-top: 50px;
          width: 200px;
          height: 200px;
          background: #ff0000;
      }

      .enter-zsy {
          opacity: 0;
      }

      .enter-to-zsy {
          opacity: 1;
          margin-left: 500px;
      }

      .enter-active-zsy {
          transition: all 3s;
      }
  </style>
</head>
<body>
<div id="app">
  <button @click="toggle">切换显示状态</button>
  <transition appear
              enter-class="enter-zsy"
              enter-active-class="enter-active-zsy"
              enter-to-class="enter-to-zsy"
  >
    <div class="box" v-show="isShow"></div>
  </transition>
  >
</div>
</body>
<script>
  /* 1. 创建 vue 实例对象 */
  let vm = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    data: {
      isShow: true
    },
    methods: {
      toggle() {
        this.isShow = !this.isShow
      }
    }
  })
</script>
</html>

15.Vue-v-for-key

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>27-Vue-v-for-key</title>
  <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
  <form>
    <input type="text" v-model="name">
    <input type="submit" @click.prevent="add" value="添加">
  </form>
  <ul>
    <li v-for="(person, index) in persons" :key="person.id">
      <input type="checkbox">
      <span>{{index}} - {{person.name}}</span>
    </li>
  </ul>
</div>
</body>
<script>
  /* 1. 创建 vue 实例对象 */
  let vm = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    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 = ""
      }
    }
  })
</script>
</html>

16.Vue列表过渡

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>28-Vue列表过渡</title>
  <script src="js/vue.js"></script>
  <style>
      .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" @click.prevent="add" value="添加">
  </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>
</body>
<script>
  /* 1. 创建 vue 实例对象 */
  let vm = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    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)
      }
    }
  })
</script>
</html>

17.Vue组件-自定义全局组件

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>29-Vue组件-自定义全局组件</title>
  <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
  <!-- 3.3 使用注册好的组件 -->
  <component-extend></component-extend>

  <component-obj></component-obj>

  <component-script></component-script>

  <component-template></component-template>
</div>
</body>
<script id="info" type="text/html">
  <div>
    <img width="200px" src="images/fm.jpg"/>
    <p>this is a description.</p>
  </div>
</script>

<template id="main">
  <div>
    <img width="200px" src="images/bg.jpg"/>
    <p>this is a description.</p>
  </div>
</template>
<script>
  // 3.1 创建组件构造器
  let Profile = Vue.extend({
    // 组件模板只能有一个根元素
    template: `
      <div>
        <img width="200px" src="images/fm.jpg"/>
        <p>this is a description.</p>
      </div>`
  })
  /*
   * 3.2 注册已经创建好的组件
   * 第一个参数:指定注册的组件的名称
   * 第二个参数:传入已经创建好的组件构造器
   */
  Vue.component("component-extend", Profile)

  let obj = {
    // 组件模板只能有一个根元素
    template: `
      <div>
        <img width="200px" src="images/bg.jpg" title="我是一只小猫" alt="都是第三方"/>
        <p>this is a description.</p>
      </div>`
  }
  // 这里会自动调用 extend 方法
  Vue.component("component-obj", obj)

  Vue.component("component-script", {
    template: '#info'
  })

  Vue.component("component-template", {
    template: '#main'
  })

  /* 1. 创建 vue 实例对象 */
  let vm = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    data: {}
  })
</script>
</html>

18.Vue组件-自定义局部组件

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>30-Vue组件-自定义局部组件</title>
  <script src="js/vue.js"></script>
</head>
<body>
<div id="app1">
  <self-component></self-component>
  <vm2-component></vm2-component>
</div>
<div id="app2">
  <self-component></self-component>
  <vm2-component></vm2-component>
</div>
</body>
<template id="main">
  <div>
    <img width="200px" src="images/bg.jpg"/>
    <p>这是全局组件.</p>
  </div>
</template>
<template id="main2">
  <div>
    <img width="200px" src="images/fm.jpg"/>
    <p>这是组件2的自定义局部组件.</p>
  </div>
</template>
<script>
  <!-- 自定义全局组件 -->
  Vue.component("self-component", {
    template: '#main'
  })

  /* 1. 创建 vue 实例对象 */
  let vm1 = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app1',
    // 3. 声明vue控制区域可以使用的数据
    data: {}
  })

  let vm2 = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app2',
    // 3. 声明vue控制区域可以使用的数据
    data: {},
    // 局部组件
    components: {
      'vm2-component': {
        template: '#main2'
      }
    }
  })
</script>
</html>

19.Vue组件-data&methods

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>31-Vue组件-data&methods</title>
  <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
  <!--
  在Vue实例控制的区域中使用的函数,系统会自动在Vue实例中查找有没有对应的方法
  -->
  <button @click="addBtn">Vue实例按钮</button>
  <p>{{app_data}}</p>

  <hr/>

  <self-component></self-component>

  <hr/>
  <component-add-data></component-add-data>
  <component-add-data></component-add-data>
  <component-add-data></component-add-data>

</div>
<template id="main">
  <div>
    <img width="200px" src="images/bg.jpg"/>
    <!--  在自定义组件中使用的函数,系统会在自定组件中查找有没有对应的方法  -->
    <button @click="selfAddBtn">自定义组件按钮</button>
    <p>{{self_data}} </p>
  </div>
</template>

<template id="add-data">
  <div>
    <button @click="addNumber">累加</button>
    <p>{{number}} </p>
  </div>
</template>
</body>
<script>
  <!-- 自定义全局组件 -->
  Vue.component("self-component", {
    template: '#main',
    // 一个组件的 data 选项必须是一个函数
    data() {
      return {
        self_data: "自定义组件 data"
      }
    },
    methods: {
      selfAddBtn() {
        alert("自定义组件中的按钮点击")
      }
    }
  })

  Vue.component("component-add-data", {
    template: '#add-data',
    /*
     * 一个组件的 data 选项必须是一个函数
     * 否则多个组件会共用一份数据,导致数据混乱
     */
    data() {
      return {
        number: 0
      }
    },
    methods: {
      addNumber() {
        this.number++
      }
    }
  })

  /* 1. 创建 vue 实例对象 */
  let vm1 = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    data: {
      app_data: "Vue 实例 data"
    },
    methods: {
      addBtn() {
        alert("Vue 实例的按钮点击")
      }
    }
  })
</script>
</html>

21.Vue组件-组件切换

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html">
<head>
  <meta charset="UTF-8">
  <title>32-Vue组件-组件切换</title>
  <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
  <button @click="toggle">元素切换</button></br>
  <p v-if="isShow">首页</p>
  <img v-else width="200px" src="images/bg.jpg"/>

  <hr/>

  <button @click="photoToggle">组件切换</button></br>
  <photo v-if="photoShow"></photo>
  <home v-else></home>
</div>
<template id="home">
  <div>
    <p>组件首页 </p>
  </div>
</template>
<template id="photo">
  <img width="200px" src="images/bg.jpg"/>
</template>
</body>
<script>
  <!-- 自定义全局组件 -->
  Vue.component("home", {
    template: '#home'
  })

  Vue.component("photo", {
    template: '#photo'
  })

  /* 1. 创建 vue 实例对象 */
  let vm1 = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    data() {
      return {
        isShow: true,
        photoShow: false
      }
    },
    methods: {
      toggle() {
        this.isShow = !this.isShow
      },
      photoToggle() {
        this.photoShow = !this.photoShow
      }
    }
  })
</script>
</html>

22.Vue组件-动态组件

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>33-Vue组件-动态组件</title>
  <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
  <button @click="toggle">组件切换</button></br>
<!--这是有缓存的  <keep-alive>-->
<!--    <component v-bind:is="name"></component>-->
<!--  </keep-alive>-->
  <home v-if="isShow"></home>
  <photo v-else ></photo>
</div>
<template id="home">
  <div>
    <p>组件首页 </p>
    <input type="checkbox"/>
  </div>
</template>
<template id="photo">
  <img width="200px" src="images/bg.jpg"/>
</template>
</body>
<script>
  <!-- 自定义全局组件 -->
  Vue.component("home", {
    template: '#home'
  })

  Vue.component("photo", {
    template: '#photo'
  })

  /* 1. 创建 vue 实例对象 */
  let vm1 = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    data() {
      return {
        isShow: true,
        name: 'home'
      }
    },
    methods: {
      toggle() {
        this.isShow = !this.isShow
        this.name = this.name === 'home' ? 'photo' : 'home'
      }
    }
  })
</script>
</html>

23.1.Vue组件-组件动画

<!DOCTYPE html>
<html lang="en">
<head>
  <link
          rel="stylesheet"
          href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"
  />
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    .v-enter,.v-leave-to {
      opacity: 0;
      margin-left: 500px;
    }
    .v-enter-to , .v-leave{
      opacity: 1;
    }
    .v-enter-active,.v-leave-active  {
      transition: all 3s;
    }

  </style>
</head>
<body>
<script src="../../js/vue.js"></script>
<div id="app">
  <button @click="toggle">切换</button>
  <br>
  <!--  <transition mode="out-in" enter-active-class="animated shake">-->
  <!--  <one v-if="isShow"></one>-->
  <!--  <two v-else></two>-->
  <!--  </transition>-->
  <transition mode="out-in" >
    <component :is="shiyan"></component>
  </transition>
</div>
<template id="first">
  <div>
    <h3>这是第一段文本</h3>
  </div>

</template>
<template id="second">
  <div>
    <h3>这是第二段文本</h3>
  </div>

</template>


<script>
  //const是常量,let是变量,proxy是代理意思,release是开放版template模板
  //代码规范大型项目为2个空格
  //组件
  Vue.component("one", {
    template: "#first"
  })
  Vue.component("two", {
    template: "#second"
  })
  const obj = {
    counter: 0,
    isShow: true,
    shiyan: "one"
  }

  const app = new Vue({

    el: "#app",
    data: obj,
    methods: {
      toggle() {
        // this.isShow=!this.isShow
        this.shiyan = this.shiyan === "one" ? "two" : "one"
      }

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

24.2.Vue组件-组件动画

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>34-Vue组件-组件动画</title>
  <script src="js/vue.js"></script>
  <style>
      .v-enter,.v-leave-to {
          opacity: 0;
          margin-left: 500px;
      }
      .v-enter-to , .v-leave{
          opacity: 1;
      }
      .v-enter-active,.v-leave-active  {
          transition: all 3s;
      }
  </style>
</head>
<body>
<div id="app">
  <button @click="toggle">组件切换</button></br>
  <transition mode="out-in">
    <component v-bind:is="name"></component>
  </transition>
</div>
<template id="home">
  <div>
    <p>组件首页 </p>
    <input type="checkbox"/>
  </div>
</template>
<template id="photo">
  <img width="200px" src="images/bg.jpg"/>
</template>
</body>
<script>
  <!-- 自定义全局组件 -->
  Vue.component("home", {
    template: '#home'
  })

  Vue.component("photo", {
    template: '#photo'
  })

  /* 1. 创建 vue 实例对象 */
  let vm1 = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    data() {
      return {
        isShow: true,
        name: 'home'
      }
    },
    methods: {
      toggle() {
        this.isShow = !this.isShow
        this.name = this.name === 'home' ? 'photo' : 'home'
      }
    }
  })
</script>
</html>

25.3.Vue组件-组件动画

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    .v-enter,.v-leave-to {
      opacity: 0;
    }
    .v-enter-active, .v-leave-active {
      transition: opacity 1s;
    }
  </style>
  <script src="../../js/vue.js"></script>
</head>
<body>

<div id="root">
  //多个元素的动画过渡
  <transition mode="out-in">
    <div v-if="show" key="hello">hello world</div>
    <div v-else key="bye">Bye World</div>
  </transition>
  <button @click="handleClick">toggle</button>

  //多个组件的动画过渡
  <transition mode="out-in" >
    <component :is="type"></component>
  </transition>
  <button @click="handleClick1">toggle</button>
</div>

<script>

  Vue.component('child',{
    template: '<div>child</div>'
  })

  Vue.component('child-one',{
    template: '<div>child-one</div>'
  })
  var vm = new Vue({
    el: "#root",
    data: {
      show: true,
      type: 'child'
    },
    methods: {
      handleClick () {
        this.show = !this.show
      },
      handleClick1 () {
        this.type = this.type === 'child' ? 'child-one' : 'child'
      }
    }
  })
</script>
</body>
</html>

26.Vue组件-父子组件

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>35-Vue组件-父子组件</title>
  <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
  <home></home>
  <father></father>
</div>
<template id="home">
  <div>
    <p> 局部组件 </p>
  </div>
</template>

<template id="father">
  <div>
    <p> 父组件 </p>
    <!--  子组件只能在定义它的父组件中使用  -->
    <son></son>
  </div>
</template>

<template id="son">
  <div>
    <p> 子组件 </p>
  </div>
</template>
</body>
<script>
  Vue.component("father", {
    template: "#father",
    components: {
      'son': {
        template: '#son'
      }
    }
  })

  /* 1. 创建 vue 实例对象 */
  let vm1 = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    data() {
      return {}
    },
    methods: {},
    components: {
      'home': {
        template: '#home'
      }
    }
  })
</script>
</html>

27.Vue组件-父子组件数据传递

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>36-Vue组件-父子组件数据传递</title>
  <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
  <father></father>
</div>

<template id="father">
  <div>
    <p> 父组件 - {{ name }} </p>
    <p> 父组件 - {{ age }} </p>
    <!--  子组件只能在定义它的父组件中使用  -->
    <son :father_name="name" :father_age="age"></son>
  </div>
</template>

<template id="son">
  <div>
    <p> 子组件 - {{father_name}}</p>
    <p> 子组件 - {{father_age}}</p>
  </div>
</template>
</body>
<script>
  Vue.component("father", {
    template: "#father",
    data() {
      return {
        name: 'zs',
        age: 18
      }
    },
    components: {
      'son': {
        template: '#son',
        props: ['father_name', 'father_age']
      }
    }
  })

  /* 1. 创建 vue 实例对象 */
  let vm1 = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    data() {
      return {}
    },
    methods: {}
  })
</script>
</html>

28.Vue组件-父子组件方法传递

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>37-Vue组件-父子组件方法传递</title>
  <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
  <father></father>
</div>

<template id="father">
  <div>
    <button @click="say">父组件按钮</button>
    <son @father_say="say"></son>
  </div>
</template>

<template id="son">
  <div>
    <button @click="say">子组件按钮</button>
  </div>
</template>
</body>
<script>
  Vue.component("father", {
    template: "#father",
    methods: {
      say() {
        alert('父组件的方法')
      }
    },
    components: {
      'son': {
        template: '#son',
        methods: {
          // 子组件自定义方法通过 this.$emit('father_say') 调用父组件方法
          say() {
            alert('子组件方法')
            this.$emit('father_say')
          }
        }
      }
    }
  })

  /* 1. 创建 vue 实例对象 */
  let vm1 = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    data() {
      return {}
    },
    methods: {}
  })
</script>
</html>

29.Vue组件-子父组件数据传递

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>38-Vue组件-子父组件数据传递</title>
  <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
  <father></father>
</div>

<template id="father">
  <div>
    <button @click="say">父组件按钮</button>
    <son @father_say="say"></son>
  </div>
</template>

<template id="son">
  <div>
    <button @click="say">子组件按钮</button>
  </div>
</template>
</body>
<script>
  Vue.component("father", {
    template: "#father",
    methods: {
      say(data) {
        alert('父组件的方法 - ' + data)
      }
    },
    components: {
      'son': {
        template: '#son',
        data() {
          return{}
        },
        methods: {
          /*
           * 子组件自定义方法通过 this.$emit('father_say') 调用父组件方法
           * 第一个参数:自定义的调用父组件方法的接收方法名
           * 后面的参数:传递给父组件方法的参数列表
           */
          say() {
            alert('子组件方法 - 下面调用父组件方法')
            this.$emit('father_say', '子组件数据')
          }
        }
      }
    }
  })

  /* 1. 创建 vue 实例对象 */
  let vm1 = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    data() {
      return {}
    },
    methods: {}
  })
</script>
</html>

30.Vue组件-组件命名

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>39-Vue组件-组件命名</title>
  <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
  <father-component></father-component>
</div>

<template id="father">
  <div>
    <button @click="say">父组件按钮</button>
    <son @parent-say="say" :parent-name="name"></son>
  </div>
</template>

<template id="son">
  <div>
    <p>子组件 - {{parentName}}</p>
    <button @click="say">子组件按钮</button>
  </div>
</template>
</body>
<script>
  Vue.component("fatherComponent", {
    template: "#father",
    data() {
      return {
        name: 'zhangsan'
      }
    },
    methods: {
      say() {
        alert('父组件的方法')
      }
    },
    components: {
      'son': {
        template: '#son',
        props: ['parentName']
        ,
        methods: {
          say() {
            alert('子组件方法 - 下面调用父组件方法')
            this.$emit('parent-say')
          }
        }
      }
    }
  })

  /* 1. 创建 vue 实例对象 */
  let vm1 = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    data() {
      return {}
    },
    methods: {}
  })
</script>
</html>

31.Vue组件-数据方法多级传递

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>40-Vue组件-数据方法多级传递</title>
  <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
  <grandfather></grandfather>
</div>

<template id="grandfather">
  <div>
    <p>grandfather - {{name}}</p>
    <button @click="say">祖组件按钮</button>
    <hr>
    <father :gfname="name" @gfsay="say"></father>
  </div>
</template>

<template id="father">
  <div>
    <p>father - {{gfname}}</p>
    <button @click="fatherFn">父组件按钮</button>
    <hr>
    <son :fname="gfname" @fsay="fatherFn"></son>
  </div>
</template>

<template id="son">
  <div>
    <p>son - {{fname}}</p>
    <button @click="sonFn">子组件按钮</button>
  </div>
</template>
</body>
<script>
  // 爷爷组件
  Vue.component("grandfather", {
    template: "#grandfather",
    data() {
      return {
        name: 'zhangsan'
      }
    },
    methods: {
      say() {
        alert("grandfather - say")
      }
    },
    // 爸爸组件
    components: {
      'father': {
        template: '#father',
        props: ['gfname'],
        methods: {
          fatherFn() {
            this.$emit('gfsay')
          }
        },
        // 儿子组件
        components: {
          'son': {
            template: '#son',
            props: ['fname'],
            methods: {
              sonFn() {
                this.$emit('fsay')
              }
            }
          }
        }
      }
    }
  })

  /* 1. 创建 vue 实例对象 */
  let vm1 = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    data() {
      return {}
    },
    methods: {}
  })
</script>
</html>

32.Vue组件-匿名插槽

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>41-Vue组件-匿名插槽</title>
  <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
  <father></father>
</div>

<template id="father">
  <div>
    <!-- 需求:在使用子组件的时候,给子组件中动态添加一些内容 -->
    <son>
      <!--
       默认情况下是不能在使用子组件的时候,给子组件动态添加内容的
       如果想给子组件动态添加内容,那么就必须使用插槽
       -->
      <h1>这是向插槽中添加的内容1</h1>
      <h1>这是向插槽中添加的内容2</h1>
      <h1>这是向插槽中添加的内容3</h1>
    </son>
  </div>
</template>

<template id="son">
  <div>
    <h1>this is 头部</h1>
    <slot>默认插槽数据</slot>
    <slot>默认插槽数据</slot>

    <h1>this is 底部</h1>
  </div>
</template>
</body>
<script>
  Vue.component("father", {
    template: "#father",
    data() {
      return {}
    },
    components: {
      'son': {
        template: '#son'
      }
    }
  })

  /* 1. 创建 vue 实例对象 */
  let vm1 = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    data() {
      return {}
    },
    methods: {}
  })
</script>
</html>

33-Vue组件-具名插槽

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>42-Vue组件-具名插槽</title>
  <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
  <father></father>
</div>

<template id="father">
  <div>
    <!-- 需求:在使用子组件的时候,给子组件中动态添加一些内容 -->
    <son>
      <!--
       默认情况下是不能在使用子组件的时候,给子组件动态添加内容的
       如果想给子组件动态添加内容,那么就必须使用插槽
       -->
      <h1 slot="one">这是替换插槽1的内容1</h1>
      <h1 slot="one">这是替换插槽1的内容2</h1>
      <h1 slot="two">这是替换插槽2的内容1</h1>
      <h1 slot="two">这是替换插槽2的内容2</h1>
    </son>
  </div>
</template>

<template id="son">
  <div>
    <h1>this is 头部</h1>

    <slot name="one">默认插槽数据</slot>
    <slot name="two">默认插槽数据</slot>

    <h1>this is 底部</h1>
  </div>
</template>
</body>
<script>
  Vue.component("father", {
    template: "#father",
    data() {
      return {}
    },
    components: {
      'son': {
        template: '#son'
      }
    }
  })

  /* 1. 创建 vue 实例对象 */
  let vm1 = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    data() {
      return {}
    },
    methods: {}
  })
</script>
</html>

34.1.Vue组件-v-slot指令

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>43-Vue组件-v-slot指令</title>
  <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
  <father></father>
</div>

<template id="father">
  <div>
    <!-- 需求:在使用子组件的时候,给子组件中动态添加一些内容 -->
    <son>
      <template v-slot:one>
        <strong><em>这是替换<br>插槽1的内容1</em></strong><hr>
        <h1>这是替换插槽1的内容1 30<small>th</small></h1>
        <pre>
          sdfsdf

        </pre>
      </template>
      <template #two>
        <h1>这是替换插槽2的内容1</h1>
        <h1>这是替换插槽2的内容22</h1>
      </template>
    </son>
  </div>
</template>

<template id="son">
  <div>
    <h1>this is 头部</h1>

    <slot name="one">默认插槽数据</slot>
    <slot name="two">默认插槽数据</slot>

    <h1>this is 底部</h1>
  </div>
</template>
</body>
<script>
  Vue.component("father", {
    template: "#father",
    data() {
      return {}
    },
    components: {
      'son': {
        template: '#son'
      }
    }
  })

  /* 1. 创建 vue 实例对象 */
  let vm1 = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    data() {
      return {}
    },
    methods: {}
  })
</script>
</html>

35.2.Vue组件-v-slot指令

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>43-Vue组件-v-slot指令</title>
  <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
  <father>
    <template #one>

    </template>
    <template #two="abb">
      {{abb.nae}}
    </template>
  </father>
</div>

<template id="father">
  <div>
    <h1>父组件</h1>
    <slot name="one">这是默认1的内容</slot><hr>
    <slot name="two" :nae="name">{{name}}这是默认2的内容</slot>
    <h1>父的组件</h1>
  </div>
</template>


</body>
<script>
  Vue.component("father", {
    template: "#father",
    data() {
      return {
        name: "shiyan"
      }
    }
  })

  /* 1. 创建 vue 实例对象 */
  let vm1 = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    data() {
      return {}
    },
    methods: {}
  })
</script>
</html>

36.Vue组件-作用域插槽

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>44-Vue组件-作用域插槽</title>
  <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
  <father></father>
</div>

<template id="father">
  <div>
    <son>
      <!-- slot-scope="abc" 接收子组件插槽暴露的数据 -->
      <template v-slot:default="abc">
        <div>匿名插槽插槽暴露的数据 - {{abc.names}}</div>
        <li v-for="name in abc.names">{{name}}</li>
      </template>

      <template #test="abc">
        <div>具名插槽插槽暴露的数据 - {{abc.names}}</div>
        <li >{{abc.nas}}</li>
      </template>
    </son>
  </div>
</template>

<template id="son">
  <div>
    <h1>this is 头部 -- {{names}}</h1>

    <!-- :names="names" 将子组件中的names数据暴露给父组件 -->
    <slot :names="names">匿名插槽数据 - {{names}}</slot>

    <slot name="test" :nas="names">默认插槽数据 - {{names}}</slot>

    <h1>this is 底部</h1>
  </div>
</template>
</body>
<script>
  Vue.component("father", {
    template: "#father",
    data() {
      return {}
    },
    components: {
      'son': {
        template: '#son',
        data() {
          return {
            names: ['zs', 'ls', 'ww', 'zl']
          }
        }
      }
    }
  })

  /* 1. 创建 vue 实例对象 */
  let vm1 = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    data() {
      return {}
    },
    methods: {}
  })
</script>
</html>

37.Vue组件-数据传递练习

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>45-Vue组件-数据传递练习</title>
  <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
  <father></father>
</div>

<template id="father">
  <div>
    <son1 @parent-change="change"></son1>
    <hr>
    <son2 :parent-num="num"></son2>
  </div>
</template>

<template id="son1">
  <div>
    <!-- 需求:在第一个子组件中添加两个按钮和一个输入框,通过按钮控制输入框数据增减 -->
    <button @click="add"> +1</button>
    <input type="text" :value="count">
    <button @click="sub"> -1</button>
  </div>
</template>
<template id="son2">
  <div>
    <!-- 需求:在第二个子组件展示第一个子组件中的数据 -->
    <input type="text" :value="parentNum" disabled>
  </div>
</template>
</body>
<script>
  Vue.component("father", {
    template: "#father",
    data() {
      return {
        num: 0
      }
    },
    methods: {
      change(newCount) {
        this.num = newCount
      }
    },
    components: {
      'son1': {
        template: '#son1',
        data() {
          return {
            count: 0
          }
        },
        methods: {
          add() {
            this.count++
            this.$emit('parent-change', this.count)
          },
          sub() {
            this.count--
            this.$emit('parent-change', this.count)
          }
        }
      },
      'son2': {
        template: '#son2',
        props: ['parentNum']
      }
    }
  })

  /* 1. 创建 vue 实例对象 */
  let vm1 = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    data() {
      return {}
    },
    methods: {}
  })
</script>
</html>

38.Vue组件-Vuex

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>46-Vue组件-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>
    <h3>{{this.$store.state.name}}</h3>
    <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.name }}</p>
  </div>
</template>
</body>
<script>
  // Vuex 对象
  const store = new Vuex.Store({
    // state 相当于组件中的 data 用于保存共享数据
    state: {
      msg: 'this is vuex msg.',
      name:"经久不息"
    }
  })



  Vue.component("grandfather", {
    template: "#grandfather",
    store: store,
    components: {
      'father': {
        template: '#father',
        components: {
          'son': {
            template: '#son',
          }
        }
      }
    }
  })

  /* 1. 创建 vue 实例对象 */
  let vm1 = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    data() {
      return {}
    },
    methods: {}
  })
</script>
</html>

39.Vuex-修改共享数据

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>47-Vuex-修改共享数据</title>
  <script src="js/vue.js"></script>
  <script src="js/vuex.js"></script>
</head>
<body>
<div id="app">
  <father></father>
</div>

<template id="father">
  <div>
    <son1 @parent-change="change"></son1>
    <hr>
    <son2 :parent-num="num"></son2>
  </div>
</template>

<template id="son1">
  <div>
    <!-- 需求:在第一个子组件中添加两个按钮和一个输入框,通过按钮控制输入框数据增减 -->
    <button @click="add"> +1</button>
    <input type="text" :value="this.$store.state.count" disabled>
    <button @click="sub"> -1</button>
  </div>
</template>
<template id="son2">
  <div>
    <!-- 需求:在第二个子组件展示第一个子组件中的数据 -->
    <button @click="add"> +1</button>
    <input type="text" :value="this.$store.state.count" disabled>
    <button @click="sub"> -1</button>
  </div>
</template>
</body>
<script>
  // Vuex 对象
  const store = new Vuex.Store({
    // state 用于保存共享数据
    state: {
      count: 0
    },
    // mutations 用于声明修改共享数据的方法
    mutations: {
      increment(state) {
        state.count++
      },
      decrement(state) {
        state.count--
      }
    }
  })

  Vue.component("father", {
    template: "#father",
    store: store,
    components: {
      'son1': {
        template: '#son1',
        methods: {
          add() {
            // 在 Vuex 中不建议直接修改共享数据
            // this.$store.state.count++
            this.$store.commit("increment")
          },
          sub() {
            // this.$store.state.count--
            this.$store.commit("decrement")
          }
        }
      },
      'son2': {
        template: '#son2',
        methods: {
          add() {
            // 在 Vuex 中不建议直接修改共享数据
            // this.$store.state.count++
            this.$store.commit("increment")
          },
          sub() {
            // this.$store.state.count--
            this.$store.commit("decrement")
          }
        }
      }
    }
  })

  /* 1. 创建 vue 实例对象 */
  let vm1 = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    data() {
      return {}
    },
    methods: {}
  })
</script>
</html>

40.Vue组件-数据传递练习

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>45-Vue组件-数据传递练习</title>
  <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
  <father></father>
</div>

<template id="father">
  <div>
    <son1 @parent-change="change"></son1>
    <hr>
    <son2 :parent-num="num"></son2>
  </div>
</template>

<template id="son1">
  <div>
    <!-- 需求:在第一个子组件中添加两个按钮和一个输入框,通过按钮控制输入框数据增减 -->
    <button @click="add"> +1</button>
    <input type="text" :value="count">
    <button @click="sub"> -1</button>
  </div>
</template>
<template id="son2">
  <div>
    <!-- 需求:在第二个子组件展示第一个子组件中的数据 -->
    <input type="text" :value="parentNum" disabled>
  </div>
</template>
</body>
<script>
  Vue.component("father", {
    template: "#father",
    data() {
      return {
        num: 0
      }
    },
    methods: {
      change(newCount) {
        this.num = newCount
      }
    },
    components: {
      'son1': {
        template: '#son1',
        data() {
          return {
            count: 0
          }
        },
        methods: {
          add() {
            this.count++
            this.$emit('parent-change', this.count)
          },
          sub() {
            this.count--
            this.$emit('parent-change', this.count)
          }
        }
      },
      'son2': {
        template: '#son2',
        props: ['parentNum']
      }
    }
  })

  /* 1. 创建 vue 实例对象 */
  let vm1 = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    data() {
      return {}
    },
    methods: {}
  })
</script>
</html>

41.Vue组件-Vuex

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>46-Vue组件-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>
    <h3>{{this.$store.state.name}}</h3>
    <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.name }}</p>
  </div>
</template>
</body>
<script>
  // Vuex 对象
  const store = new Vuex.Store({
    // state 相当于组件中的 data 用于保存共享数据
    state: {
      msg: 'this is vuex msg.',
      name:"经久不息"
    }
  })



  Vue.component("grandfather", {
    template: "#grandfather",
    store: store,
    components: {
      'father': {
        template: '#father',
        components: {
          'son': {
            template: '#son',
          }
        }
      }
    }
  })

  /* 1. 创建 vue 实例对象 */
  let vm1 = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    data() {
      return {}
    },
    methods: {}
  })
</script>
</html>

42.Vuex-修改共享数据

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>46-Vue组件-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>
    <h3>{{this.$store.state.name}}</h3>
    <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.name }}</p>
  </div>
</template>
</body>
<script>
  // Vuex 对象
  const store = new Vuex.Store({
    // state 相当于组件中的 data 用于保存共享数据
    state: {
      msg: 'this is vuex msg.',
      name:"经久不息"
    }
  })



  Vue.component("grandfather", {
    template: "#grandfather",
    store: store,
    components: {
      'father': {
        template: '#father',
        components: {
          'son': {
            template: '#son',
          }
        }
      }
    }
  })

  /* 1. 创建 vue 实例对象 */
  let vm1 = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    data() {
      return {}
    },
    methods: {}
  })
</script>
</html>

43.Vuex-getters

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>48-Vuex-getters</title>
  <script src="js/vue.js"></script>
  <script src="js/vuex.js"></script>
</head>
<body>
<div id="app">
  <father></father>
</div>

<template id="father">
  <div>
    计算属性:转大写
    <p>{{format}}</p>
    <p>{{format}}</p>
    <p>{{format}}</p>
    <hr>
    getters:转大写
    <p>{{this.$store.getters.format}}</p>
    <p>{{this.$store.getters.format}}</p>
    <p>{{this.$store.getters.format}}</p>
  </div>
</template>
</body>
<script>
  // Vuex 对象
  const store = new Vuex.Store({
    // state 用于保存共享数据
    state: {
      msg: 'this is father\'s msg'
    },
    // mutations 用于声明修改共享数据的方法
    mutations: {},
    getters: {
      format(state) {
        console.log("getters 方法执行")
        return state.msg.toUpperCase()
      }
    }
  })

  Vue.component("father", {
    template: "#father",
    store: store,
    data() {
      return {
        msg: 'this is father\'s msg'
      }
    },
    computed: {
      format() {
        console.log("计算属性方法执行")
        return this.msg.toUpperCase()
      }
    }
  })

  /* 1. 创建 vue 实例对象 */
  let vm1 = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    data() {
      return {}
    },
    methods: {}
  })
</script>
</html>

44.VueRouter-基本介绍

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>49-VueRouter-基本介绍</title>
  <script src="js/vue.js"></script>
  <script src="js/vue-router.js"></script>
  <style>
      .z-active {
          background: red;
      }
  </style>
</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>
</body>
<script>
  // 定义组件
  const one = {
    template: '#one'
  }
  const two = {
    template: '#two'
  }

  // 定义路由规则
  const routes = [
    // 通过重定向设置默认导航路由
    {path: '/', redirect:'/one'},
    {path: '/one', component: one},
    {path: '/two', component: two}
  ]
  // 根据路由规则创建路由对象
  const router = new VueRouter({
    routes,
    linkActiveClass: 'z-active'
  })


  /* 1. 创建 vue 实例对象 */
  let vm = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    data: {},
    components: {
      one, two
    },
    // 将路由router对象绑定到Vue实例
    router
  })
</script>
</html>

45.VueRouter-传递参数

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>50-VueRouter-传递参数</title>
  <script src="js/vue.js"></script>
  <script src="js/vue-router.js"></script>
  <style>
      .z-active {
          background: red;
      }
  </style>
</head>
<body>
<div id="app">
  <router-link to="/one?name=zs&age=12" tag="button">切换到第一个界面</router-link>
  <router-link to="/two/ls/13" 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>
</body>
<script>
  // 定义组件
  const one = {
    template: '#one',
    created() {
      console.log(this.$route);
      console.log(this.$route.query.name);
      console.log(this.$route.query.age);
    }
  }
  const two = {
    template: '#two',
    created() {
      console.log(this.$route)
      console.log(this.$route.params.name)
      console.log(this.$route.params.age)
    }
  }

  // 定义路由规则
  const routes = [
    // 通过重定向设置默认导航路由
    // {path: '/', redirect:'/one'},
    {path: '/one', component: one},
    {path: '/two/:name/:age', component: two}
  ]
  // 根据路由规则创建路由对象
  const router = new VueRouter({
    routes,
    linkActiveClass: 'z-active'
  })


  /* 1. 创建 vue 实例对象 */
  let vm = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    data: {},
    components: {
      one, two
    },
    // 将路由router对象绑定到Vue实例
    router
  })
</script>
</html>

46.VueRouter-嵌套路由

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>51-VueRouter-嵌套路由</title>
  <script src="js/vue.js"></script>
  <script src="js/vue-router.js"></script>
  <style>
      .z-active {
          background: red;
      }
  </style>
</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/sub1" tag="button">切换到第一个子界面</router-link>
    <router-link to="/one/sub2" tag="button">切换到第二个子界面</router-link>

    <router-view></router-view>
  </div>
</template>
<template id="onesub1">
  <div class="onesub1">
    <p>第一个子界面</p>
  </div>
</template>
<template id="onesub2">
  <div class="onesub2">
    <p>第二个子界面</p>
  </div>
</template>
<template id="two">
  <div class="twopage">
    <p>第二个界面</p>
  </div>
</template>
</body>
<script>
  // 定义组件
  const onesub1 = {
    template: '#onesub1'
  }
  const onesub2 = {
    template: '#onesub2'
  }
  const one = {
    template: '#one',
    components: {
      onesub1, onesub2
    }
  }
  const two = {
    template: '#two'
  }

  // 定义路由规则
  const routes = [
    {
      path: '/one', component: one,
      children: [
        {path: 'sub1', component: onesub1},
        {path: 'sub2', component: onesub2}
      ]
    },
    {path: '/two', component: two}
  ]
  // 根据路由规则创建路由对象
  const router = new VueRouter({
    routes,
    linkActiveClass: 'z-active'
  })

  /* 1. 创建 vue 实例对象 */
  let vm = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    data: {},
    components: {
      one, two
    },
    // 将路由router对象绑定到Vue实例
    router
  })
</script>
</html>

47.VueRouter-命名视图

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>52-VueRouter-命名视图</title>
  <script src="js/vue.js"></script>
  <script src="js/vue-router.js"></script>
  <style>
      .z-active {
          background: red;
      }
  </style>
</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>
</body>
<script>
  // 定义组件
  const onesub1 = {
    template: '#onesub1'
  }
  const onesub2 = {
    template: '#onesub2'
  }
  const one = {
    template: '#one',
    components: {
      onesub1, onesub2
    }
  }
  const two = {
    template: '#two'
  }

  // 定义路由规则
  const routes = [
    {
      path: '/',
      components: {
        name1: one,
        name2: two
      },
    },
  ]
  // 根据路由规则创建路由对象
  const router = new VueRouter({
    routes,
    linkActiveClass: 'z-active'
  })

  /* 1. 创建 vue 实例对象 */
  let vm = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    data: {},
    components: {
      one, two
    },
    // 将路由router对象绑定到Vue实例
    router
  })
</script>
</html>

48.VueRouter-watch属性

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>53-VueRouter-watch属性</title>
  <script src="js/vue.js"></script>
  <script src="js/vue-router.js"></script>
  <style>
      .z-active {
          background: red;
      }
  </style>
</head>
<body>
<div id="app">
  <p>使用监听键盘抬起方法实现加法</p>
  <input type="text" v-model="num1" @keyup="change1">
  <span> + </span>
  <input type="text" v-model="num2" @keyup="change2">
  <span> = </span>
  <input type="text" v-model="result" disabled>

  <hr>
  <p>使用watch属性实现加法</p>
  <input type="text" v-model="num3">
  <span> + </span>
  <input type="text" v-model="num4">
  <span> = </span>
  <input type="text" v-model="result2" disabled>

  <hr>
  <p>使用watch属性实现监听路由变化</p>
  <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>
</body>
<script>
  // 定义组件
  const one = {
    template: '#one'
  }
  const two = {
    template: '#two'
  }

  // 定义路由规则
  const routes = [
    // 通过重定向设置默认导航路由
    // {path: '/', redirect:'/one'},
    {path: '/one', component: one},
    {path: '/two', component: two}
  ]
  // 根据路由规则创建路由对象
  const router = new VueRouter({
    routes,
    linkActiveClass: 'z-active'
  })

  /* 1. 创建 vue 实例对象 */
  let vm = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    data: {
      num1: 0,
      num2: 0,
      result: 0,
      num3: 0,
      num4: 0,
      result2: 0,
    },
    watch: {
      num3(newValue, oldValue) {
        this.result2 = parseInt(this.num3) + parseInt(this.num4)
      },
      num4(newValue, oldValue) {
        this.result2 = parseInt(this.num3) + parseInt(this.num4)
      },

      "$route.path"(newValue, oldValue) {
        console.log(newValue, oldValue)
      }
    },
    methods: {
      change1() {
        this.result = parseInt(this.num1) + parseInt(this.num2)
      },
      change2() {
        this.result = parseInt(this.num1) + parseInt(this.num2)
      }
    },
    components: {
      one, two
    },
    // 将路由router对象绑定到Vue实例
    router
  })
</script>
</html>

49.Vue-生命周期方法

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>54-Vue-生命周期方法</title>
  <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
  <button @click="change">切换</button>
  <one v-if="isShow"></one>
  <p>{{msg}}</p>
  <!-- v-if 实现切换是通过删除和重新创建来完成的 -->
  <img src="images/lifecycle.png" alt="生命周期图示" width="50%">
</div>
<template id="one">
  <p>测试组件</p>
</template>
</body>
<script>
  const one = {
    template: '#one',
    beforeDestroy() {
      console.log("beforeDestroy")
    },
    destroyed() {
      console.log("destroyed")
    }
  }
  /* 1. 创建 vue 实例对象 */
  let vm = new Vue({
    // 2. 声明vue的实例对象控制页面的哪个区域
    el: '#app',
    // 3. 声明vue控制区域可以使用的数据
    data: {
      msg: "this is test msg.",
      isShow: true
    },
    methods: {
      change() {
        this.isShow = !this.isShow
      }
    },
    components: {
      one
    },
    beforeCreate() {
      console.log("beforeCreate")
    },
    created() {
      /* 这里是最早能访问到 Vue 实例中的 data 和 methods 的生命周期方法 */
      console.log("created")
    },
    beforeMount() {
      console.log("beforeMount")
    },
    mounted() {
      console.log("mounted")
    },
    beforeUpdate() {
      /* 这里是最后能访问到 Vue 实例中的 data 和 methods 的生命周期方法 */
      console.log("beforeUpdate")
    },
    updated() {
      console.log("updated")
    }
  })
</script>
</html>

50.Vue特殊特性

<div id="app">
  <button @click="fn1">通过原生方法获取DOM</button>
  <button @click="fn2">通过ref获取DOM</button>
  <p ref="myP">这是p元素标签渲染的内容</p>
  <one ref="myOne" id="myone"></one>
</div>
<template id="one">
  <div>
    <p>这里是组件渲染的内容</p>
  </div>
</template>
</body>
<script>
  Vue.component('one', {template: '#one'})
  let vue = new Vue({
    el: '#app',
    data: {},
    methods: {
      fn1() {
        /*
        * 通过原生方法获取 DOM 元素
        * 这里获取的都是原生的 DOM 元素对象
        * 不推荐
        * */
        console.log(document.querySelector("p"));
        console.log(document.querySelector("#myone"));
      },
      fn2() {
        /*
        * 通过ref方式获取DOM
        * 使用ref可以获取组件对象
        * */
        console.log(this.$refs);
        console.log(this.$refs.myP);
        console.log(this.$refs.myOne);
      }
    }
  })
</script>

51.Vue-组件渲染方式

<div id="app">
</div>
<template id="one">
  <div>
    <p> 组件 one</p>
  </div>
</template>
</body>
<script>
  Vue.component("one", {
    template: '#one'
  })
  let vm = new Vue({
    el: '#app',
    data: {},
    /*render(createElement) {
      return createElement("one")
    }*/
    // render: createElement => createElement("one")
    render: h => h("one")
  })
</script>

Vue3快速上手

一、创建Vue3.0工程

1.使用 vue-cli 创建

安装

## 查看@vue/cli版本,确保@vue/cli版本在4.5.0以上
vue --version
## 安装或者升级你的@vue/cli
npm install -g @vue/cli
## 创建
vue create vue_test
## 启动
cd vue_test
npm run serve

#使用Vite
## 创建工程
npm init vite-app <project-name>
## 进入工程目录
cd <project-name>
## 安装依赖
npm install
## 运行
npm run dev

新的特性

  1. Composition API(组合API)

    • setup配置
    • ref与reactive
    • watch与watchEffect
    • provide与inject
  2. 新的内置组件

    • Fragment
    • Teleport
    • Suspense
  3. 其他改变

    • 新的生命周期钩子
    • data 选项应始终被声明为一个函数
    • 移除keyCode支持作为 v-on 的修饰符

总结

主要是为了方便,有自己的代码库!以后好参照!!!
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

joyyi9

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

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

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

打赏作者

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

抵扣说明:

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

余额充值