文章目录
- 🚏 一、Vue组件化编程 components
- 🚏 二、Vue脚手架
- 🚀 1、创建Vue脚手架
- 🚄 2、使用Vue脚手架创建项目步骤--自定义
- 🚒 3、使用Vue脚手架创建项目--2.0/3.0默认
- 🚤 4、分析Vue脚手架结构
- 🚗 5、render函数
- 🚲 6、修改默认配置
- 🚀 7、ref属性
- 🚄 8、props配置项(重要)
- 🚒 9、mixin配置项(混入/混合)
- 🚤 10、插件
- 🚗 11、scoped样式
- 🚲 12、TodoList案例
- 🚀 13、浏览器的本地存储
- 🚄 13、TodoList本地存储
- 🚒 14、组件的自定义事件 子组件给父组件传
- 🚤 15、TodoList案例自定义事件
- 🚗 16、全局事件总线 <font color = red > 重要:任意组件间通信</font>
- 🚲 17、TodoList事件总线
- 🚀 18、消息订阅与发布 任意组件间通信
- 🚄 17、TodoList消息订阅与发布
- 🚒 18、TodoList编辑功能
- 🚤 19、过度与动画
- 🚗 20、TodoList过度与动画
😹 作者: gh-xiaohe
😻 gh-xiaohe的博客
😽 觉得博主文章写的不错的话,希望大家三连(✌关注,✌点赞,✌评论),多多支持一下!!!
🚏 一、Vue组件化编程 components
🚬 传统方式编写应用
🚬 组件式编写应用
🚬 组件的概念
实现应用中局部功能代码和资源的集合
🚬 组件的作用
复用编码,简化项目编码,提高运行效率
🚀 1、非单文件组件
- 一个文件中包含n个组件
- 缺点 : 样式不能跟着组件走
🚬 组件的定义
总结:
<!-- Vue中使用组件的三大步骤: 一、定义组件(创建组件) 二、注册组件 三、使用组件(写组件标签) 一、如何定义一个组件? 使用Vue.extend(options)创建,其中options和new Vue(options)时传入的那个options几乎一样,但也有点区别; 区别如下: 1.el不要写,为什么? ——— 最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器。 2.data必须写成函数,为什么? ———— 避免组件被复用时,数据存在引用关系。 备注:使用template可以配置组件结构。 二、如何注册组件? 1.局部注册:靠new Vue的时候传入components选项 2.全局注册:靠Vue.component('组件名',组件) 三、编写组件标签: <school></school> -->
① 基础
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>一个重要的内置关系</title> <!-- 引入Vue --> <script type="text/javascript" src="../js/vue.js"></script> </head> <body> <div id="root"> <h2>学校名称:{{schoolName}}</h2> <h2>学校地址:{{address}}</h2> <hr> <h2>学生姓名:{{studentName}}</h2> <h2>学生年龄:{{age}}</h2> </div> </body> <script type="text/javascript"> Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。 new Vue({ el: "#root", data: { schoolName: '清华大学', address: '北京', studentName: '张三', age: 18 } }) </script> </html>
② 创建school组件 局部组件(常用)
步骤:
- 创建组件
- 注册组件
- 编辑组件标签
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>一个重要的内置关系</title> <!-- 引入Vue --> <script type="text/javascript" src="../js/vue.js"></script> </head> <body> <div id="root"> <hr> <!-- 第三步:编写组件标签 --> <school></school> <hr> <!-- 第三步:编写组件标签 --> <student></student> <student></student> </div> </body> <script type="text/javascript"> Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。 //第一步:创建school组件 const school = Vue.extend({ // 传入配置对象 template:` <div> <h2>学校名称:{{schoolName}}</h2> <h2>学校地址:{{address}}</h2> </div> `, // el:'#root', //组件定义时,一定不要写el配置项,因为最终所有的组件都要被一个vm管理,由vm决定服务于哪个容器。 data(){ // data 函数式(普通函数),不能书写成对象时,使用对象式时,有引用关系 return { schoolName:'Tom', address:'北京昌平' } }, }) //第一步:创建student组件 const student = Vue.extend({ template:` <div> <h2>学生姓名:{{studentName}}</h2> <h2>学生年龄:{{age}}</h2> </div> `, data(){ return { studentName:'张三', age:18 } } }) new Vue({ el: "#root", //第二步:注册组件(局部注册) components:{ school, // 组件名 或者 组件名 school:创建组件时的名字 student } }) </script> </html>
③ 交互点我提示学校名const school = Vue.extend({ // 传入配置对象 template:` <div> <h2>学校名称:{{schoolName}}</h2> <h2>学校地址:{{address}}</h2> <button @click="showName">点我提示学校名</button> </div> `, data(){ return { schoolName:'Tom', address:'北京昌平' } }, methods: { showName(){ alert(this.schoolName) } }, })
④ 全局注册组件
- Vue.component(‘hello’,hello) // 组件的名字 组件的位置
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>基本使用</title> <script type="text/javascript" src="../js/vue.js"></script> </head> <body> <div id="root"> <!-- 第三步:编写组件标签 --> <school></school> <!-- 第三步:编写组件标签 --> <student></student> </div> <div id="root2"> <!-- 第三步:编写组件标签 --> <hello></hello> </div> </body> <script type="text/javascript"> Vue.config.productionTip = false //第一步:创建hello组件 const hello = Vue.extend({ template:` <div> <h2>你好啊!{{name}}</h2> </div> `, data(){ return { name:'Tom' } } }) //第二步:全局注册组件 Vue.component('hello',hello) // 组件的名字 组件的位置 //创建vm new Vue({ el:'#root', data:{ msg:'你好啊!' }, //第二步:注册组件(局部注册) components:{ school, student } }) new Vue({ el:'#root2', }) </script> </html>
🚬 组件的注意事项
总结:
<!-- 几个注意点: 1.关于组件名: 一个单词组成: 第一种写法(首字母小写):school 第二种写法(首字母大写):School 多个单词组成: 第一种写法(kebab-case命名):my-school 'my-school' 第二种写法(CamelCase命名):MySchool (需要Vue脚手架支持) 备注: (1).组件名尽可能回避HTML中已有的元素名称,例如:h2、H2都不行。 (2).可以使用name配置项指定组件在开发者工具中呈现的名字。 2.关于组件标签: 第一种写法:<school></school> 第二种写法:<school/> 备注:不用使用脚手架时,<school/>会导致后续组件不能渲染。 3.一个简写方式: const school = Vue.extend(options) 可简写为:const school = options -->
简写 创建组件 (推荐)
- 单文件组件时,常用
const hello = { template:` <div> <h2>你好啊!{{name}}</h2> </div> `, data(){ return { name:'Tom' } } }
🚬 组件的嵌套
school 是父 student 是子
- student 组件应该写在 school组件的上面
- student 组件中定义 school组件
- school 的使用 定义哪个组件 在 template 中 使用
① 组件的嵌套
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>一个重要的内置关系</title> <!-- 引入Vue --> <script type="text/javascript" src="../js/vue.js"></script> </head> <body> <div id="root"> <school></school> </div> </body> <script type="text/javascript"> Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。 //创建 student 组件 const student = Vue.extend({ template:` <div> <h2>学生姓名:{{studentName}}</h2> <h2>学生年龄:{{age}}</h2> </div> `, data(){ return { studentName:'张三', age:18 } }, }) //创建 school组件 const school = Vue.extend({ // 传入配置对象 template:` <div> <h2>学校名称:{{schoolName}}</h2> <h2>学校地址:{{address}}</h2> <student></student> </div> `, data(){ return { schoolName:'Tom学校', address:'北京昌平' } }, components:{ student, } }) new Vue({ el: "#root", components:{ school, } }) </script> </html>
② 定义个 hello 组件 要求:和school是平级的<div id="root"> <school></school> <hello></hello> </div> //定义hello组件 const hello = Vue.extend({ template:`<h1>{{msg}}</h1>`, data(){ return { msg:'欢迎来和Tom一起学习!' } } }) new Vue({ el: "#root", components:{ school, hello, } })
③ 开发中常用技巧 定义一个:app组件
作用:用于管理应用里面所有的组件<div id="root"> <app></app> </div> //定义app组件 const app = Vue.extend({ template:` <div> <hello></hello> <school></school> </div> `, components:{ school, // 引入 school 组件, 不用在引用student 引用父组件即可 hello } }) //创建vm new Vue({ el:'#root', //注册组件(局部) components:{app} })
如果 容器中什么都不想写,怎么办
- 容器里面干干净净
//创建vm new Vue({ template:'<app></app>', el:'#root', //注册组件(局部) components:{app} })
🚬 VueComponent的构造函数
总结:
<!-- 关于VueComponent: 1.school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的。 2.我们只需要写<school/>或<school></school>,Vue解析时会帮我们创建school组件的实例对象, 即Vue帮我们执行的:new VueComponent(options)。 3.特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent!!!! 4.关于this指向: (1).组件配置中: data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【VueComponent实例对象】。 (2).new Vue(options)配置中: data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【Vue实例对象】。 5.VueComponent的实例对象,以后简称vc(也可称之为:组件实例对象)。 Vue的实例对象,以后简称vm。 -->
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>VueComponent</title> <script type="text/javascript" src="../js/vue.js"></script> </head> <body> <div id="root"> <school></school> <hello></hello> school </div> </body> <script type="text/javascript"> Vue.config.productionTip = false //定义school组件 const school = Vue.extend({ name:'school', template:` <div> <h2>学校名称:{{name}}</h2> <h2>学校地址:{{address}}</h2> <button @click="showName">点我提示学校名</button> </div> `, data(){ return { name:'Tom', address:'北京' } }, methods: { showName(){ console.log('showName',this) } }, }) const test = Vue.extend({ template:`<span>atguigu</span>` }) //定义hello组件 const hello = Vue.extend({ template:` <div> <h2>{{msg}}</h2> <test></test> </div> `, data(){ return { msg:'你好啊!' } }, components:{test} }) console.log('@',school) // Vue 的 VueComponent的构造函数 console.log('#',hello) // 每次调用都会 创建一个新的 构造函数对象 // 每次调用Vue.extend,返回的都是一个全新的VueComponent!!!! //创建vm const vm = new Vue({ el:'#root', components:{school,hello} }) </script> </html>
体现vm 管理 一个一个的vc
🚬 Vue实例与组件实例
- vc有的功能vm都有,vm有一个功能vc就没有,vm可以通过el决定来为哪个容器服务,vc不可以
🚬 重要的内置关系
总结:
<!-- 1.一个重要的内置关系:VueComponent.prototype.__proto__ === Vue.prototype 2.为什么要有这个关系:让组件实例对象(vc)可以访问到 Vue原型上的属性、方法。 -->
① 原型相关知识
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>一个重要的内置关系</title> <!-- 引入Vue --> <script type="text/javascript" src="../js/vue.js"></script> </head> <body> <div id="root"> </div> </body> <script type="text/javascript"> Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。 //定义一个构造函数 function Demo(){ this.a = 1 this.b = 2 } //创建一个Demo的实例对象 const d = new Demo() console.log(Demo.prototype) // 函数身上的 显示原型属性 console.log(d.__proto__) // 实例身上的 隐式原型属性 统统都指向的了一个对象 原型对象 console.log(Demo.prototype === d.__proto__) //程序员通过显示原型属性操作原型对象,追加一个x属性,值为99 Demo.prototype.x = 99 console.log('@',d.__proto__.x) // 在顺着这条线去找 或者 console.log('@',d.x) console.log('@',d) </script> </html>
② 内置关系
- .prototype.proto === Vue.prototype
- 目的:让组件实例对象(vc)可以访问到 Vue原型上的属性、方法。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>一个重要的内置关系</title> <!-- 引入Vue --> <script type="text/javascript" src="../js/vue.js"></script> </head> <body> <div id="root"> <school></school> </div> </body> <script type="text/javascript"> Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。 Vue.prototype.x = 99 //定义school组件 本质 是VueComponent const school = Vue.extend({ name:'school', template:` <div> <h2>学校名称:{{name}}</h2> <h2>学校地址:{{address}}</h2> <button @click="showX">点我输出x</button> </div> `, data(){ return { name:'Tom', address:'北京' } }, methods: { showX(){ console.log(this) console.log(this.x) } }, }) //创建一个vm const vm = new Vue({ el:'#root', data:{ msg:'你好' }, components:{school} }) // VueComponent 需要调用 extend 此时换成 school // console.log(VueComponent.prototype.__proto__ === Vue.prototype) console.log(school.prototype.__proto__ === Vue.prototype) // true </script> </html>
🚄 2、单文件组件
- 一个文件中包含1个组件
- 单文件组件后缀都是==.vue==结尾
① Vue文件的基本结构
<template> // 组件的结构 </template> <script> // 组件交互相关的代码(数据、方法等等) </script> <style> // 组件的样式 </style>
② 组件的定义 基本使用(简单使用)
school 组件
<template> <div class="demo"> <h2>学校名称:{{name}}</h2> <h2>学校地址:{{address}}</h2> <button @click="showName">点我提示学校名</button> </div> </template> <script> export default { // 默认暴露 name:'School', // 组件的名字 data(){ return { name:'Tom', // 数据 address:'北京昌平' } }, methods: { showName(){ alert(this.name) } }, } </script> <style> .demo{ background-color: orange; } </style>
student 组件
<template> <div> <h2>学生姓名:{{name}}</h2> <h2>学生年龄:{{age}}</h2> </div> </template> <script> export default { name:'Student', data(){ return { name:'张三', age:18 } } } </script>
App组件
<template> // ③ 使用组件 <div> <School></School> <Student></Student> </div> </template> <script> // ① 引入组件 import School from './School.vue' import Student from './Student.vue' export default { name:'App', // 汇总所有的组件 // ② 注册组件 components:{ School, Student } } </script>
③ 创建vm:main.js
// 引入 App 组件 .vue 可以省略 import App from './App.vue' new Vue({ el:'#root', // template:`<App></App>`, 和 ④ 书写一个即可 components:{App}, // 注册组件 App })
④ 容器 index.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>练习一下单文件组件的语法</title> </head> <body> <!-- 准备一个容器 --> <div id="root"> <App></App> </div> <!-- Vue --> <script type="text/javascript" src="../js/vue.js"></script> <!-- 先让模板出来在 引入main.js 入口文件--> <script type="text/javascript" src="./main.js"></script> </body> </html>
逻辑:
🚏 二、Vue脚手架
- 官网:https://cli.vuejs.org/zh/
🚀 1、创建Vue脚手架
- 第一步(仅第一次执行):全局安装@vue/cli。
npm install -g @vue/cli - 第二步:切换到你要创建项目的目录>,然后使用命令创建项目
vue create xxxx - 第三步:启动项目
npm run serve - 备注:
- 如出现下载缓慢请配置 npm 淘宝镜像:npm config set registry https://registry.npm.taobao.org
- Vue 脚手架隐藏了所有 webpack 相关的配置,若想查看具体的 webpakc 配置,
请执行:vue inspect > output.js
🚄 2、使用Vue脚手架创建项目步骤–自定义
运行
- cd 02myvue1
- npm run serve
🚒 3、使用Vue脚手架创建项目–2.0/3.0默认
运行
- cd vue-test1
- npm run serve
🚤 4、分析Vue脚手架结构
index.html 结构
<!DOCTYPE html> <html lang=""> <head> <meta charset="utf-8"> <!-- 针对IE浏览器的一个特殊配置,含义是让IE浏览器以最高的渲染级别渲染页面 --> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <!-- 开启移动端的理想视口 --> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <!-- 配置页签图标 --> <link rel="icon" href="<%= BASE_URL %>favicon.ico"> <!-- 引入第三方样式 --> <link rel="stylesheet" href="<%= BASE_URL %>css/bootstrap.css"> <!-- 配置网页标题 --> <title>硅谷系统</title> </head> <body> <!-- 当浏览器不支持js时noscript中的元素就会被渲染 --> <noscript> <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> </noscript> <!-- 容器 --> <div id="app"></div> <!-- built files will be auto injected --> </body> </html>
🚗 5、render函数
总结:
<-- 关于不同版本的Vue: 1.vue.js与vue.runtime.xxx.js的区别: (1).vue.js是完整版的Vue,包含:核心功能+模板解析器。 (2).vue.runtime.xxx.js是运行版的Vue,只包含:核心功能;没有模板解析器。 2.因为vue.runtime.xxx.js没有模板解析器,所以不能使用template配置项,需要使用 render函数接收到的createElement函数去指定具体内容。 -->
① mian.js 不认识书写成---->自己认为的写法
//引入Vue import Vue from 'vue' //引入App组件,它是所有组件的父组件 import App from './App.vue' //关闭vue的生产提示 Vue.config.productionTip = false //创建Vue实例对象---vm new Vue({ el:'#app', template:`<App></App>`, components:{App}, })
② 精简代码,验证信息
//引入Vue import Vue from 'vue' Vue.config.productionTip = false new Vue({ el:'#app', template:`<h1>你好啊</h1>`, })
验证
③ 解决办法2—> 引入完整版本的Vue
//引入Vue import Vue from 'vue/dist/vue' Vue.config.productionTip = false new Vue({ el:'#app', template:`<h1>你好啊</h1>`, })
④ 解决办法1—> 使用render(渲染)函数
- render需要返回值
- 可以接收参数
new Vue({ el:'#app', render(createElement) { // createElement 创建元素 // 查看createElement的类型 看是函数还是对象 // createElement 创建具体的元素,编写具体的内容 console.log(typeof createElement) // function 是函数 return null } })
推导过程
// ① new Vue({ el:'#app', render(createElement) { return createElement('h1','你好啊') } }) // ② 没有使用到this可以写成箭头函数 new Vue({ el:'#app', render:(createElement)=> { return createElement('h1','你好啊') } }) // ③ 箭头函数左面含有一个参数 可以省略小括号 new Vue({ el:'#app', render:createElement=> { return createElement('h1','你好啊') } }) // ④ 箭头函数只有一句函数体,并且还return new Vue({ el:'#app', render:createElement=> createElement('h1','你好啊') }) // ⑤ createElement 使用字母替代 render:q=> q('h1','你好啊') new Vue({ el:'#app', render:h=> h('h1','你好啊') }) // 页面上成功返回
和创建的基础代码 还有一点区别:参数
- 原因:h1是HTML中的内置元素,里面需要写具体的内容,需要传递第二个参数
- 如果使用的是组件 就不用内容
// 两个参数 new Vue({ el:'#app', render:h=> h('h1','你好啊') }) // 一个参数 import App from './App.vue' new Vue({ el:'#app', // render函数完成了这个功能:将App组件放入容器中 render: h => h(App) // 不加入引号 读取变量 })
- 如果一直使用完整版本的Vue开发时不会有任何问题,webpack打包,发布后,已经变成浏览器认识的纯粹js文件,template模板解析器就没有什么作用了
🚲 6、修改默认配置
总结:
## vue.config.js配置文件 1. 使用vue inspect > output.js可以查看到Vue脚手架的默认配置。 2. 使用vue.config.js可以对脚手架进行个性化定制,详情见:https://cli.vuejs.org/zh
🚬 查看Vue的配置文件
- vue把核心的配置文件给隐藏了,怕不小心,修改错误,项目跑不起来程序,查看核心配置文件命令:vue inspect > output.js
🚬 脚手架默认的配置哪些文件不可以修改
🚬 修改Vue的默认配置
- 官网左侧栏中的都可以进行修改:https://cli.vuejs.org/zh/config/
- 写个vue.config.js 文件 和 package.json同级,在vue.config.js中书写需要修改的配置,程序读取时,会把vue.config.js中程序员书写的相关内容,与vue的核心配置文件进行整合,最核心的配置碰不到,之后需要重新的启动npm run serve
module.exports = {
pages: {
index: {
//入口
entry: 'src/main.js',
},
},
lintOnSave:false, //关闭语法检查
}
🚀 7、ref属性
总结:
原生<div> <h1 v-text="msg" id="title"></h1> <button ref="btn" @click="showDOM">点我输出上方的DOM元素</button> </div> <script> export default { name:'App', components:{}, data() { }, methods: { showDOM(){ console.log(document.getElementById("title")) console.log(this.$refs.title) //真实DOM元素 console.log(this.$refs.btn) //真实DOM元素 console.log(this.$refs.sch) //School组件的实例对象(vc) } }, } </script>
vue
<div> <h1 v-text="msg" ref="title"></h1> <button ref="btn" @click="showDOM">点我输出上方的DOM元素</button> </div> <script> export default { name:'App', components:{}, data() { }, methods: { showDOM(){ // this App.vue 的 vc console.log(this.$refs.title) //真实DOM元素 console.log(this.$refs.btn) //真实DOM元素 } }, } </script>
🚬 获取DOM元素
<template> <div> <h1 v-text="msg" ref="title"></h1> <button ref="btn" @click="showDOM">点我输出上方的DOM元素</button> <School ref="sch"/> </div> </template> <script> //引入School组件 import { Col } from 'element-ui' import School from './components/School' export default { name:'App', components:{School}, data() { return { msg:'欢迎学习Vue!' } }, methods: { showDOM(){ console.log(this.$refs.title) //真实DOM元素 console.log(this.$refs.btn) //真实DOM元素 console.log(this.$refs.sch) //School组件的实例对象(vc) } }, } </script>
🚄 8、props配置项(重要)
总结:
① 基础student.vue
<template> <div> <h1>{{msg}}</h1> <h2>学生姓名:{{name}}</h2> <h2>学生性别:{{sex}}</h2> <h2>学生年龄:{{age}}</h2> </div> </template> <script> export default { name:'Student', data() { console.log(this) return { msg:'我是一名热爱学习的学生', name: '张三', sex: '男', age: '18', } }, } </script>
app.vue
<template> <div> <Student/> </div> </template> <script> import Student from './components/Student' export default { name:'App', components:{Student} } </script>
🚬 方式一:简单的方式
② 引入比人的组件传入的数据不一样==(引入组件传入数据)== props
- app.vue –> 引入student 组件 传递参数
<div> <Student name="李四" sex="女" age="18"/> </div>
- student 组件还要声明一下,student 中的组件数据就不能写死
<script> export default { name:'Student', data() { console.log(this) return { msg:'我是一名热爱学习的学生', } }, //简单声明接收 props:['name','age','sex'] } </script>
③ 如果操作传入过来的数据: 比如:给年龄加一岁,使用普通参数传参会出现问题
<div> <h1>{{msg}}</h1> <h2>学生姓名:{{name}}</h2> <h2>学生性别:{{sex}}</h2> <h2>学生年龄:{{age + 1}}</h2> </div>
解决办法:app.vue中绑定age 的值
- age 表示的是字符串
- :age 的值是运行 “18” js表达式 里面执行的结果
<div> <Student name="李四" sex="女" :age="18"/> </div>
🚬 方式二:接收的同时对数据进行类型限制
<script> export default { name:'Student', data() { console.log(this) return { msg:'我是一名热爱学习的学生', } }, //接收的同时对数据进行类型限制 props:{ name:String, age:Number, sex:String } } </script>
如果你没有进行绑定:age 控制台会提示你的错误
🚬 方式三:接收的同时对数据:进行类型限制+默认值的指定+必要性的限制
<script> export default { name:'Student', data() { console.log(this) return { msg:'我是一名热爱学习的学生', } }, //接收的同时对数据:进行类型限制+默认值的指定+必要性的限制 props:{ name:{ type:String, //name的类型是字符串 required:true, //name是必要的 }, age:{ type:Number, default:99 //默认值 }, sex:{ type:String, required:true } } } </script>
app.vue
<div> <Student sex="女" /> </div>
注意:
- 1、传入的参数不要瞎声明
<script>
export default {
name:'Student',
data() {
console.log(this)
return {
msg:'我是一名热爱学习的学生',
}
},
props:['name','age','sex','phone']
}
</script>
- 2、外部传递的参数不能修改
- 修改外部传递参数age的数值
<template>
<div>
<h1>{{msg}}</h1>
<h2>学生姓名:{{name}}</h2>
<h2>学生性别:{{sex}}</h2>
<h2>学生年龄:{{age}}</h2>
<button @click="updateAge">尝试修改收到的年龄</button>
</div>
</template>
<script>
export default {
name:'Student',
data() {
console.log(this)
return {
msg:'我是一名热爱学习的学生',
}
},
methods: {
updateAge(){
this.age = 22
}
},
//简单声明接收
props:['name','age','sex']
}
</script>
- 解决办法
<template>
<div>
<h1>{{msg}}</h1>
<h2>学生姓名:{{name}}</h2>
<h2>学生性别:{{sex}}</h2>
<h2>学生年龄:{{age}}</h2>
<h2>学生年龄:{{myAge+1}}</h2>
</div>
</template>
<script>
export default {
name:'Student',
data() {
console.log(this)
return {
msg:'我是一名热爱学习的学生',
myAge:this.age // props 的优先级更高,能获取到
}
},
methods: {
updateAge(){
this.myAge++
}
},
//简单声明接收
props:['name','age','sex']
}
</script>
🚒 9、mixin配置项(混入/混合)
总结:
① 基础student.vue
<template> <div> <h2 @click="showName">学生姓名:{{name}}</h2> <h2>学生性别:{{sex}}</h2> </div> </template> <script> export default { name:'Student', data() { return { name:'张三', sex:'男' } }, methods: { showName(){ alert(this.name) } }, } </script>
school.vue
<template> <div> <h2 @click="showName">学校名称:{{name}}</h2> <h2>学校地址:{{address}}</h2> </div> </template> <script> export default { name:'School', data() { return { name:'Tom学校', address:'北京', } }, methods: { showName(){ alert(this.name) } }, } </script>
app.vue
<template> <div> <School/> <hr> <Student/> </div> </template> <script> import School from './components/School' import Student from './components/Student' export default { name:'App', components:{School,Student} } </script>
- 两个组件共享一个配置混入(混合)
mixin.jsexport const hunhe = { methods: { showName(){ alert(this.name) } }, mounted() { console.log('你好啊!') }, } export const hunhe2 = { data() { return { x:100, y:200 } }, }
引入mixin.js Student.vue 和 School.vue
<script> //引入一个hunhe import {hunhe,hunhe2} from '../mixin' export default { name:'School', data() { return { name:'Tom学校', address:'北京', x:666 } }, mixins:[hunhe,hunhe2], } </script>
混合的原则
- 你没有的 混合给你
- 你有 混合也有的 用自己的,不用混合的
- 生命周期不以任何人为主,都要,混合的生命周期在前
全局混合:
main.js中引入 Student.vue 和 School.vue都不进行引入
- 所有的vc 和 vm 都会得到
import {hunhe,hunhe2} from './mixin' Vue.mixin(hunhe) Vue.mixin(hunhe2)
🚤 10、插件
总结:
① 基础 student.vue ```vue <template> <div> <h2>学生姓名:{{name}}</h2> <h2>学生性别:{{sex}}</h2> </div> </template> <script> export default { name:'Student', data() { return { name:'张三', sex:'男' } }, methods: { showName(){ alert(this.name) } }, } </script>
school.vue
<template> <div> <h2>学校名称:{{name}}</h2> <h2>学校地址:{{address}}</h2> </div> </template> <script> export default { name:'School', data() { return { name:'Tom学校', address:'北京', } }, methods: { showName(){ alert(this.name) } }, } </script>
app.vue
<template> <div> <School/> <hr> <Student/> </div> </template> <script> import School from './components/School' import Student from './components/Student' export default { name:'App', components:{School,Student} } </script>
🚬 定义一个Vue里面的插件(对象)
plugins.js
export default { install(Vue,x,y,z){ console.log(x,y,z) //全局过滤器 Vue.filter('mySlice',function(value){ return value.slice(0,4) }) //定义全局指令 Vue.directive('fbind',{ //指令与元素成功绑定时(一上来) bind(element,binding){ element.value = binding.value }, //指令所在元素被插入页面时 inserted(element,binding){ element.focus() }, //指令所在的模板被重新解析时 update(element,binding){ element.value = binding.value } }) //定义混入 Vue.mixin({ data() { return { x:100, y:200 } }, }) //给Vue原型上添加一个方法(vm和vc就都能用了) Vue.prototype.hello = ()=>{alert('你好啊')} } }
main.js —> 引入、应用插件 在vm之前
//引入插件 import plugins from './plugins' //应用(使用)插件 Vue.use(plugins,1,2,3) //创建vm new Vue({ el:'#app', render: h => h(App) })
🚗 11、scoped样式
总结:
① 基础student.vue
<template> <div> <h2>学生姓名:{{name}}</h2> <h2>学生性别:{{sex}}</h2> </div> </template> <script> export default { name:'Student', data() { return { name:'张三', sex:'男' } }, methods: { showName(){ alert(this.name) } }, } </script>
school.vue
<template> <div> <h2>学校名称:{{name}}</h2> <h2>学校地址:{{address}}</h2> </div> </template> <script> export default { name:'School', data() { return { name:'Tom学校', address:'北京', } }, methods: { showName(){ alert(this.name) } }, } </script>
app.vue
<template> <div> <School/> <hr> <Student/> </div> </template> <script> import School from './components/School' import Student from './components/Student' export default { name:'App', components:{School,Student} } </script>
② 给Student 和 School 组件 编写样式
- 组件的样式最终都汇总在一起了,容易出现问题类名冲突
// School 组件 <div class="demo"> <h2 class="title">学校名称:{{name}}</h2> <h2>学校地址:{{address}}</h2> </div> <style> .demo{ background-color: skyblue; } </style> // Student 组件 <template> <div class="demo"> <h2 class="title">学生姓名:{{name}}</h2> <h2 class="atguigu">学生性别:{{sex}}</h2> </div> </template> <style > .demo{ background-color: pink; } </style> // 组件样式之间发生冲突
解决办法:一个属性scoped局部的// School 组件 <style scoped> .demo{ background-color: skyblue; } </style> // Student 组件 <style lang="less" scoped> .demo{ background-color: pink; } </style>
App组件不适合,使用scopedApp组件中书写样式(所有组件的头),一般来说App中书写的样式,基本上很多组件都在用
style 标签中有个lang 里面可以写 less 或者是 css 样式
- 如果只写less vue 脚手架处理不了less
- 不写 lang 默认是css
- 需要安装 npm i less-loader 注意和webpack 的版本是否冲突,安装 7版本 npm i less-loader@7
- 查看版本 npm view webpack versions
<style lang="less" scoped> .demo{ background-color: pink; <!-- less 嵌套 --> .atguigu{ font-size: 40px; } } </style>
🚲 12、TodoList案例
看TodoList案例博客:TodoList案例博客
🚀 13、浏览器的本地存储
总结:
🚬 localStorage
- 读的结果不存在时是 null
- 浏览器关闭,数据不会消失
- 数据什么时候会消失
- 引导了用户点击了删除按钮
- 用户主动地清空缓存
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>localStorage</title> </head> <body> <h2>localStorage</h2> <button onclick="saveData()">点我保存一个数据</button> <button onclick="readData()">点我读取一个数据</button> <button onclick="deleteData()">点我删除一个数据</button> <button onclick="deleteAllData()">点我清空一个数据</button> <script type="text/javascript" > let p = {name:'张三',age:18} function saveData(){ localStorage.setItem('msg','hello!!!') localStorage.setItem('msg2',666) localStorage.setItem('person',JSON.stringify(p)) } function readData(){ console.log(localStorage.getItem('msg')) console.log(localStorage.getItem('msg2')) const result = localStorage.getItem('person') console.log(JSON.parse(result)) // console.log(localStorage.getItem('msg3')) } function deleteData(){ localStorage.removeItem('msg2') } function deleteAllData(){ localStorage.clear() } </script> </body> </html>
🚬 sessionStorage
- 一次会话,浏览器一关数据就消失
- 使用方法和 localStorage 是一样的
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>sessionStorage</title> </head> <body> <h2>sessionStorage</h2> <button onclick="saveData()">点我保存一个数据</button></br> <button onclick="readData()">点我读取一个数据</button></br> <button onclick="deleteData()">点我删除一个数据</button></br> <button onclick="deleteAllData()">点我清空一个数据</button> <script type="text/javascript" > let p = {name:'张三',age:18} function saveData(){ sessionStorage.setItem('msg','hello!!!') sessionStorage.setItem('msg2',666) sessionStorage.setItem('person',JSON.stringify(p)) } function readData(){ console.log(sessionStorage.getItem('msg')) console.log(sessionStorage.getItem('msg2')) const result = sessionStorage.getItem('person') console.log(JSON.parse(result)) // console.log(sessionStorage.getItem('msg3')) } function deleteData(){ sessionStorage.removeItem('msg2') } function deleteAllData(){ sessionStorage.clear() } </script> </body> </html>
🚄 13、TodoList本地存储
看TodoList案例博客:TodoList案例博客
🚒 14、组件的自定义事件 子组件给父组件传
- 给组件使用
- 给谁绑的事件,就找谁触发事件
总结:
🚬 自定义事件–绑定
① 基础
School.vue
<template> <div class="school"> <h2>学校名称:{{name}}</h2> <h2>学校地址:{{address}}</h2> </div> </template> <script> export default { name:'School', props:['getSchoolName'], data() { return { name:'Tom学校', address:'北京', } }, } </script> <style scoped> .school{ background-color: skyblue; padding: 5px; } </style>
Student.vue
<template> <div class="student"> <h2>学生姓名:{{name}}</h2> <h2>学生性别:{{sex}}</h2> </div> </template> <script> export default { name:'Student', data() { return { name:'张三', sex:'男', } }, } </script> <style lang="less" scoped> .student{ background-color: pink; padding: 5px; margin-top: 30px; } </style>
App.vue
<template> <div class="app"> <h1>{{msg}}</h1> <School/> <Student/> </div> </template> <script> import Student from './components/Student' import School from './components/School' export default { name:'App', components:{School,Student}, data() { return { msg:'你好啊!', } }, } </script> <style scoped> .app{ background-color: gray; padding: 5px; } </style>
② School 组件下面有个按钮,点击按钮把学校名交给App 子组件 传递给 父组件
- 给谁绑的事件,就找谁触发事件
App.vue
<template> <div class="app"> <!-- 通过父组件给子组件传递函数类型的props实现:子给父传递数据 --> <School :getSchoolName="getSchoolName"/> <Student/> </div> </template> <script> export default { name:'App', components:{School,Student}, methods: { getSchoolName(name){ console.log('App收到了学校名:',name) }, }, } </script>
School.vue
<template> <div class="school"> <button @click="sendSchoolName">把学校名给App</button> </div> </template> <script> export default { props:['getSchoolName'], methods: { sendSchoolName(){ this.getSchoolName(this.name) } }, } </script>
③ 把学生名给App 换一种方式–>使用自定义事件🚭 自定义绑定事件方式一:
App.vue
<template> <div class="app"> <h1>{{msg}}</h1> <!-- 通过父组件给子组件传递函数类型的props实现:子给父传递数据 --> <School :getSchoolName="getSchoolName"/> <!-- 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第一种写法,使用@或v-on) --> <Student @atguigu="getStudentName"/> </div> </template> <script> export default { methods: { getSchoolName(name){ console.log('App收到了学校名:',name) }, getStudentName(){ console.log('自定义绑定事件触发') } }, } </script>
Student.vue
<template> <div class="student"> <button @click="sendStudentlName">把学生名给App</button> </div> </template> <script> export default { methods: { sendStudentlName(){ //触发Student组件实例身上的atguigu事件 this.$emit('atguigu',this.name) // 触发哪个事件 }, }, } </script>
二者之间的区别
- propes 和 自定义事件 都需要两个回调
- propes 给 School组件,School组件亲自去调用
- 自定义事件,并没有给 Student 组件,什么都没有传,只是绑定了一个自定义事件,做为自定义事件的回调在使用
- 数据是如何过去的 Student 组件触发了这个事件
🚭 自定义绑定事件方式二:
- 虽然麻烦但是灵活性很强
- 比如:定时器,等五秒后在绑定自定义事件
app.vue
- 在app组件里面,通过app的vc(this.$refs.student),就可以获取到Student组件的实例对象
<div class="app"> <!-- 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第一种写法,使用@或v-on) --> <!-- <Student @atguigu="getStudentName" @demo="m1"/> --> <!-- 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第二种写法,使用ref) --> <Student ref="student"/> </div> <script> export default { ounted() { // app 挂载完毕 // this.$refs.studen Student组件的实例对象 $on 当什么时候 atguigu 被触发的时候 触发回调 this.$refs.student.$on('atguigu',this.getStudentName) //绑定自定义事件 // this.$refs.student.$once('atguigu',this.getStudentName) //绑定自定义事件(一次性) }, } </script>
🚭 触发事件时候传递很多数据过去
// 方式一 school.vue <script> methods: { sendStudentlName(){ this.$emit('atguigu',this.name,666,888,900) }, }, </script> app.vue <script> methods: { getStudentName(name,x,y,z){ console.log('App收到了学生名:',name,x,y,z) }, }, } </script> 开发中的方式 // 方式一 : 把数据包装成一个对象传递过去 school.vue <script> methods: { sendStudentlName(){ this.$emit('atguigu',{}) }, }, </script> // 方式二: es6 写法 正常传递,接收 school.vue <script> methods: { sendStudentlName(){ this.$emit('atguigu',this.name,666,888,900) }, }, </script> app.vue <script> methods: { // name 正常结构,其他的参数不管传递多少,整理到params数组上 getStudentName(name,...params){ console.log('App收到了学生名:',name,params) }, }, } </script>
🚬 组件自定义–解绑事件
Student.vue
<template> <div class="student"> <button @click="add">点我number++</button> <button @click="unbind">解绑atguigu事件</button> </template> <script> export default { methods: { unbind(){ this.$off('atguigu') //解绑一个自定义事件 // this.$off(['atguigu','demo']) //解绑多个自定义事件 // this.$off() //解绑所有的自定义事件 } }, } </script>
🚬 注意点
- app在收到Student传入的姓名后,不是在控制台上打印,而是在页面上做一个呈现
第一种写法,使用@或v-on
app.vue
<template> <div class="app"> <h1>{{msg}},学生姓名是:{{studentName}}</h1> <!-- 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第一种写法,使用@或v-on) --> <Student @atguigu="getStudentName" @demo="m1"/> </div> </template> <script> export default { data() { return { msg:'你好啊!', studentName:'' } }, methods: { getStudentName(name,...params){ console.log('App收到了学生名:',name,params) this.studentName = name } }, } </script>
第二种写法,使用ref
<template> <div class="app"> <h1>{{msg}},学生姓名是:{{studentName}}</h1> <!-- 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第二种写法,使用ref) --> <Student ref="student"/> </div> </template> <script> export default { data() { return { msg:'你好啊!', studentName:'' } }, methods: { getStudentName(name,...params){ console.log('App收到了学生名:',name,params) this.studentName = name } }, mounted() { this.$refs.student.$on('atguigu',this.getStudentName) //绑定自定义事件 }, } </script>
注意:
- 有人可能嫌麻烦 把getStudentName写在 mounted中 普通函数方式 不可行
- why?谁触发了 atguigu 事件,事件当中回掉的this就是谁,所以此时是Student组件的vc
- 有人可能嫌麻烦 把getStudentName写在 mounted中 箭头函数
- 箭头函数没有实例对象,向上查找,找到 mounted 钩子,此时是App
<script> export default { data() { return { msg:'你好啊!', studentName:'' } }, /* methods: { getStudentName(name,...params){ console.log('App收到了学生名:',name,params) this.studentName = name } },*/ mounted() { this.$refs.student.$on('atguigu',function(name,...params)) //绑定自定义事件 console.log(this) // 此时是this 是Student组件的vc }, } </script> <script> mounted() { this.$refs.student.$on('atguigu',(name,...params)=>) //绑定自定义事件 console.log(this) // 此时是this 是Student组件的vc }, } </script>
- 组件使用原生事件
<Student ref="student" @click="show"/> // 这么写不可以,给当做自定义事件 <Student ref="student" @click.native="show"/> //native 原生的,本来的
🚤 15、TodoList案例自定义事件
看TodoList案例博客:TodoList案例博客
🚗 16、全局事件总线 重要:任意组件间通信
总结:
理解:
① 基础
Student.vue
<template> <div class="student"> <h2>学生姓名:{{name}}</h2> <h2>学生性别:{{sex}}</h2> </div> </template> <script> export default { name:'Student', data() { return { name:'张三', sex:'男', } } } </script>
School.vue
<template> <div class="school"> <h2>学校名称:{{name}}</h2> <h2>学校地址:{{address}}</h2> </div> </template> <script> export default { name:'School', data() { return { name:'Tom', address:'北京', } }, } </script>
App.vue
<template> <div class="app"> <h1>{{msg}}</h1> <School/> <Student/> </div> </template> <script> import Student from './components/Student' import School from './components/School' export default { name:'App', components:{School,Student}, data() { return { msg:'你好啊!', } } } </script>
② 实现让所有组件都能看到 组件x
- 放在main.js中的 beforeCreate
main.js
//引入Vue import Vue from 'vue' //引入App import App from './App.vue' //关闭Vue的生产提示 Vue.config.productionTip = false //创建vm new Vue({ el:'#app', render: h => h(App), beforeCreate() { Vue.prototype.$bus = this //安装全局事件总线 }, })
School.vue
<script> export default { mounted() { this.$bus.$on('hello',(data)=>{ console.log('我是School组件,收到了数据',data) }) }, beforeDestroy() { this.$bus.$off('hello') // 销毁 傀儡身上的事件 }, } </script>
Student.vue 传给学校数据
<template> <div class="student"> <h2>学生姓名:{{name}}</h2> <h2>学生性别:{{sex}}</h2> <button @click="sendStudentName">把学生名给School组件</button> </div> </template> <script> export default { methods: { sendStudentName(){ this.$bus.$emit('hello',this.name) } }, } </script>
🚲 17、TodoList事件总线
看TodoList案例博客:TodoList案例博客
🚀 18、消息订阅与发布 任意组件间通信
- 推荐使用全局事件总线,全局事件总线是原生的。
总结:
理解:
🚬 需要引入一个消息订阅与发布的第三方实现库: PubSubJS
🚬 使用 PubSubJS
-
在线文档: https://github.com/mroderick/PubSubJS
-
下载: npm install -S pubsub-js
-
相关语法
- (1) import PubSub from ‘pubsub-js’ // 引入
- (2) PubSub.subscribe(‘msgName’, functon(msgName, data){ })
- (3) PubSub.publish(‘msgName’, data): 发布消息, 触发订阅的回调函数调用
- (4) PubSub.unsubscribe(token): 取消消息的订阅
🚬 使用 pubsub
- School 组件订阅消息
- Student 发布消息
- 安装 npm install -S pubsub-js
- 引入 import pubsub from ‘pubsub-js’ // pubsub 是对象
School.vue
<template> <div class="school"> <h2>学校名称:{{name}}</h2> <h2>学校地址:{{address}}</h2> </div> </template> <script> import pubsub from 'pubsub-js' export default { name:'School', data() { return { name:'Tom', address:'北京', } }, mounted() {// 执行的回调 一个参数是 函数名 第二个是 消息 this.pubId = pubsub.subscribe('hello',(msgName,data)=>{ // subscribe 订阅 console.log(this) // 普通函数 使用 pubsub 库 this 是undefined 使用箭头函数 this是vc School console.log('有人发布了hello消息,heVlo消息的回调执行了',msgName,data) }) }, beforeDestroy() { pubsub.unsubscribe(this.pubId) // 解绑 订阅 }, } </script>
Student.vue
<template> <div class="student"> <h2>学生姓名:{{name}}</h2> <h2>学生性别:{{sex}}</h2> <button @click="sendStudentName">把学生名给School组件</button> </div> </template> <script> import pubsub from 'pubsub-js' export default { name:'Student', data() { return { name:'张三', sex:'男', } }, mounted() { }, methods: { sendStudentName(){ pubsub.publish('hello',666) // publish 发布 hello 带着数据 } }, } </script>
🚄 17、TodoList消息订阅与发布
看TodoList案例博客:TodoList案例博客
🚒 18、TodoList编辑功能
看TodoList案例博客:TodoList案例博客
🚬 $nextTick 重要
总结:
理解:
🚤 19、过度与动画
总结:
🚬 动画
-
让谁有动画的效果就用transition标签给包裹起来
-
template 中所实现的名字是固定
-
三个样式的类名
-
v-enter 进入的起点 反之对应 v-leave 离开的起点
-
v-enter-active 进入过程中 反之对应 v-leave-active 离开过程中
- enter进入时的动画 active激活 进入时要激活的样式
- leave离开 离开时要激活的样式
-
v-enter -to 进入的终点 反之对应 v-leave-to 离开的终点
-
v 可以替换成过度时的名字
-
template 中 appear 页面出现时就呈效果
-
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-avWWp35j-1659536526495)(VUE入门.assets/image-20220803221812340.png)]
-
app.vue
<template> <div> <Test/> <Test2/> <Test3/> </div> </template> <script> import Test from './components/Test' import Test2 from './components/Test2' import Test3 from './components/Test3' export default { name:'App', components:{Test,Test2,Test3}, } </script>
test.vue
- 像左离开,像右出现
① 基础
<template> <div> <button @click="isShow = !isShow">显示/隐藏</button> <h1 v-show="isShow">你好啊!</h1> </div> </template> <script> export default { name:'Test', data() { return { isShow:true } }, } </script> <style scoped> h1{ background-color: orange; } </style>
② 实现<template> <div> <button @click="isShow = !isShow">显示/隐藏</button> <!-- transition 过度 appear 呈现 hello 过度时起的名字--> <transition name="hello" appear> <h1 v-show="isShow">你好啊!</h1> </transition> </div> </template> <script> export default { name:'Test', data() { return { isShow:true } }, } </script> <style scoped> h1{ background-color: orange; } /* css3知识 */ /* 使用动画 两个样式的类名 linear 匀速 reverse 反转*/ .hello-enter-active{ animation: atguigu 0.5s linear; } .hello-leave-active{ animation: atguigu 0.5s linear reverse; } /* 动画定义一个关键帧 名字可以随意 */ @keyframes atguigu { from{ /* 来 */ transform: translateX(-100%); } to{ /* 来到 */ transform: translateX(0px); } } </style>
🚬 过度
test2.vue —> test1.vue 的效果
<template> <div> <button @click="isShow = !isShow">显示/隐藏</button> <!-- transition 过度 appear 呈现 hello 过度时起的名字--> <transition name="hello" appear> <h1 v-show="isShow">你好啊!</h1> </transition> </div> </template> <script> export default { name:'Test', data() { return { isShow:true } }, } </script> <style scoped> h1{ background-color: orange; } /* 进入的起点、离开的终点 */ .hello-enter,.hello-leave-to{ transform: translateX(-100%); } /* 来的激活时的样式,离开时激活的样式 */ .hello-enter-active,.hello-leave-active{ transition: 0.5s linear; } /* 进入的终点、离开的起点 */ .hello-enter-to,.hello-leave{ transform: translateX(0); } </style>
🚬 多个元素同样的过度效果
错误写法一:
<template> <div> <button @click="isShow = !isShow">显示/隐藏</button> <!-- transition 过度 appear 呈现 hello 过度时起的名字--> <transition name="hello" appear> <h1 v-show="isShow">你好啊!</h1> <h1 v-show="isShow">我很好谢谢!</h1> </transition> </div> </template>
- 只有一个展示
错误写法二:
<template> <div> <button @click="isShow = !isShow">显示/隐藏</button> <!-- transition 过度 appear 呈现 hello 过度时起的名字--> <transition-group name="hello" appear> <h1 v-show="isShow">你好啊!</h1> <h1 v-show="isShow">我很好谢谢!</h1> </transition-group > </div> </template>
正确方式一:
<template> <div> <button @click="isShow = !isShow">显示/隐藏</button> <!-- transition 过度 appear 呈现 hello 过度时起的名字--> <!-- 真是列表中使用 v-for 生成 key 值--> <transition-group name="hello" appear> <h1 v-show="isShow" key="1">你好啊!</h1> <h1 v-show="isShow" key="2">我很好谢谢!</h1> </transition-group > </div> </template>
正确方式二:
- 使用transition标签,使用div标签把两个h1标签包裹起来 但是两个展示效果不能互斥,互斥无法实现,互斥只能使用 transition-group 显示取反
<template> <div> <button @click="isShow = !isShow">显示/隐藏</button> <!-- transition 过度 appear 呈现 hello 过度时起的名字--> <!-- 真是列表中使用 v-for 生成 key 值--> <transition-group name="hello" appear> <div> <h1 v-show="isShow" key="1">你好啊!</h1> <h1 v-show="isShow" key="2">我很好谢谢!</h1> </div> </transition-group > </div> </template>
🚬 集成第三方动画
- 网址:https://www.npmjs.com/package/animate.css
① 基础
<template> <div> <button @click="isShow = !isShow">显示/隐藏</button> <transition-group > <h1 v-show="!isShow" key="1">你好啊!</h1> <h1 v-show="isShow" key="2">我很好谢谢你</h1> </transition-group> </div> </template> <script> import 'animate.css' export default { name:'Test', data() { return { isShow:true } }, } </script> <style scoped> h1{ background-color: orange; } </style>
② 使用
- 安装 npm install animate.css
- 引入 import ‘animate.css’ 样式
<template> <div> <button @click="isShow = !isShow">显示/隐藏</button> <!-- 首页中有很多样式和动画,直接左侧还有演示直接复制即可 --> <transition-group appear name="animate__animated animate__bounce" enter-active-class="animate__swing" leave-active-class="animate__backOutUp" > <h1 v-show="!isShow" key="1">你好啊!</h1> <h1 v-show="isShow" key="2">我很好谢谢你</h1> </transition-group> </div> </template>
🚗 20、TodoList过度与动画
看TodoList案例博客:TodoList案例博客