文章目录
Vue.js是什么?(・∀・*) 🌿
Vue安装Ⅲ种方式 🍵
Hello Vue.js 😀
列表生成 🍉
计时器 ⏲
了解 MVVM 💬
Vue的生命周期 ❤️
插值表达式 🤪
v-once 🥒
v-html 🍵
v-text ☘️
v-pre 🥦
v-cloak 🥤
v-bind 🔍
小案例 🚩
Vue.js是什么?(・∀・*) 🌿
Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架
Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层
当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动
Vue安装Ⅲ种方式 🍵
🍉 使用 CDN 引入
🍉 在官网下载,学习阶段推荐下载开发版本,方便阅读源代码和调试
🍉 使用 NPM 等包管理工具进行安装(在构建大型应用时推荐)
Hello Vue.js 😀
Hello Vue.js 仪式感必须有
<body> <div id="app"> {{message}} </div> <!-- 引入开发版本的 Vue.js --> <script src="../js/vue.js"></script> <!-- 实例Vue对象 --> <script> // new 构造函数,这里参数传入的是一个对象配置项,el,data都是Vue的配置项……键值对的形式 new Vue({ // 挂载到id为app的dom上,被挂载的对象交由Vue管理 el:'#app', // Vue对象的数据块,值是一个对象,依然是键值对 data:{ message:'Hello Vue' } }) </script> </body>
在浏览器打开,你会发现
源码的 5087 行就是Vue的构造函数,如下所示,我们要知其然知其所以然 🚀
列表生成 🍉
原生 Js 做一个循环列表,首先得获取 DOM,然后循环创建 li ,并且把数据通过 innerText 添加进 li 中去,这种编程范式称为 命令式 ,你说一句,他做一步,现在,我们使用了 Vue 框架,这时候,我们应该转变思想,不应该固化再 命令式,在 Vue 中,不再获取 DOM ,或者说很少,因为 Vue 是数据驱动视图,数据双向绑定,采用了 MVVM 架构设计,但是没有完全遵守 MVVM 的规范,说来抽象,写段代码
<body> <div id="app"> <ul> <!-- 使用 v-for item是遍历后的数据 in关键字 names是Vue实例的数据 --> <li v-for="item in names"> {{item}} </li> </ul> </div> <script src="../js/vue.js"></script> <script> new Vue({ el: '#app', data: { names: ['小刘', '小张', '奥特曼', '侠岚'] } }) </script> </body>
打开浏览器
惊呆了,惊呆了
这种通过标签🏷来标识要进行什么操作,这种编程方式称为 声明式
add(){……} 是 ES6函数的简写形式
等价于 function add(){……}
计时器 ⏲
这里引入了新的配置项,叫做 methods ,意思就是方法集合,专门存放 Vue 的方法
<body> <div id="app"> <button @click="sub">-</button> <span>{{count}}</span> <button @click="add">+</button> </div> <script src="../js/vue.js"></script> <script> new Vue({ el: '#app', data: { count: 0 }, methods: { add() { this.count++; }, sub() { this.count--; } } }) </script> </body>
演示
了解 MVVM 💬
MVVM(Model-View-ViewModel)是对 MVC(Model-View-Control)的进一步改进
『View』:视图层(UI 用户界面)
『ViewModel』:业务逻辑层(一切 js 可视为业务逻辑)
『Model』:数据层(存储数据及对数据的处理如增删改查)
MVVM 将数据双向绑定(data-binding)作为核心思想,View 和 Model 之间没有联系,它们通过 ViewModel(Vue) 这个桥梁进行交互
Model 和 ViewModel 之间的交互是双向的,因此 View 的变化会自动同步到 Model,而 Model 的变化也会反馈到 View 上显示
当用户操作 View,ViewModel 感知到变化,然后通知 Model 发生相应改变;反之当 Model 发生改变,ViewModel 也能感知到变化,使 View 作出相应更新
Vue的生命周期 ❤️
了解更多Vue的生命周期钩子函数
<body> <div id="app"></div> <script src="../js/vue.js"></script> <script> new Vue({ el: '#app', // beforeCreate // 在实例初始化之后,进行数据侦听和事件/侦听器的配置之前同步调用 beforeCreate() { console.log("创建前beforeCreate...") }, // created // 在实例创建完成后被立即同步调用。 // 在这一步中,实例已完成对选项的处理,意味着以下内容已被配置完毕:数据侦听、计算属性、方法、事件/侦听器的回调函数。然而,挂载阶段还没开始,且 $el property 目前尚不可用。 created() { console.log("创建created...") }, // beforeMount // 在挂载开始之前被调用:相关的 render 函数首次被调用。该钩子在服务器端渲染期间不被调用 beforeMount() { console.log("挂载前beforeMount...") }, // mounted // 实例被挂载后调用,这时 el 被新创建的 vm.$el 替换了。如果根实例挂载到了一个文档内的元素上,当 mounted 被调用时 vm.$el 也在文档内。 // 注意 mounted 不会保证所有的子组件也都被挂载完成。如果你希望等到整个视图都渲染完毕再执行某些操作,可以在 mounted 内部使用 vm.$nextTick: /* mounted: function () { this.$nextTick(function () { // 仅在整个视图都被渲染之后才会运行的代码 }) } */ mounted() { console.log("被挂载mounted..."); }, // beforeUpdate // 在数据发生改变后,DOM 被更新之前被调用。这里适合在现有 DOM 将要被更新之前访问它,比如移除手动添加的事件监听器。 // 该钩子在服务器端渲染期间不被调用,因为只有初次渲染会在服务器端进行。 beforeUpdate() { console.log("数据更新前beforeUpdate...") }, // updated // 在数据更改导致的虚拟 DOM 重新渲染和更新完毕之后被调用。 updated() { console.log("虚拟DOM渲染完毕updated...") }, // beforeDestroy // 实例销毁之前调用。在这一步,实例仍然完全可用。 beforeDestroy() { consloe.log("销毁前beforeDestroy...") }, // destroyed // 实例销毁后调用。该钩子被调用后,对应 Vue 实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁。 destroyed() { console.log("销毁实例destroyed...") }, // …… // 还有一些生命周期钩子,这里就不一一列举了 }) </script> </body>
插值表达式 🤪
{{ }} 前面写的这个表达式,也叫插值表达式,不仅仅可以写Vue变量,也可以写简单表达式
<body> <div id="app"> {{a}} {{b}} {{a + b}} {{b * 2}} {{a == b ? '等':'不等'}} </div> <script src="../js/vue.js"></script> <script> new Vue({ el: '#app', data: { a: 1, b: 2 } }) </script> </body>
v-once 🥒
v-once 指令不需要表达式,使用该指令的元素只渲染一次,不会随着数据的改变而改变
定义了网站标题 title , 当我们给 title 赋值时,它会被改变
<body> <div id="app"> <h2>{{title}}</h2> </div> <script src="../js/vue.js"></script> <script> var app = new Vue({ el:'#app', data:{ title:'王子的烦恼' } }) </script> </body>
现在有一个需求,一些数据是不变的,他只在初始化页面时做一个展示,那该怎么办呢,没错,v-once指令
<body> <div id="app"> <h2 v-once>{{title}}</h2> </div> <script src="../js/vue.js"></script> <script> var app = new Vue({ el:'#app', data:{ title:'王子的烦恼' } }) </script> </body>
v-html 🍵
用于插值,只不过如果有html标签,则会渲染,有xxs攻击的风险
<body> <div id="app"> <h2>{{baidu}}</h2> <h2 v-html="csdn"></h2> </div> <script src="../js/vue.js"></script> <script> new Vue({ el:'#app', data:{ baidu: '<a href="https://www.baidu.com">百度一下<a/>', csdn: '<a href="https://csdn.net">csdn<a/>' } }) </script> </body>
v-text ☘️
用于插值,会当作普通文本处理,会覆盖原有的文字
<body> <div id="app"> <!-- v-text 会覆盖原有的文本 --> <h2 v-text="csdn">我感觉我要没了</h2> </div> <script src="../js/vue.js"></script> <script> new Vue({ el: '#app', data: { csdn: '<a href="https://csdn.net">csdn<a/>' } }) </script> </body>
v-pre 🥦
v-pre用于跳过这个元素和它子元素编译,用于显示原本的样子
<body> <div id="app"> <h2 v-text="csdn">我感觉我要没了</h2> <h2 v-pre>{{csdn}}</h2> </div> <script src="../js/vue.js"></script> <script> new Vue({ el: '#app', data: { csdn: '<a href="https://csdn.net">csdn<a/>' } }) </script> </body>
v-cloak 🥤
在首次加载时,可能因为某些原因导致加载延迟,就会出现 {{12312}} 这样的显示效果,显然让用户看到是很不好的,可以使用 v-cloak 指令解决,给元素添加这个指令,然后通过 css 选择器给添加了这个标签元素设置 display:none,就隐藏了,当vue加载完毕,会清除你添加的 v-cloak指令,这时元素就显示出来了,这就解决了这个问题
问题复现
使用定时器,延迟两秒种再创建 Vue 实例
<body> <div id="app"> <div>{{message}}</div> <div>{{message}}</div> </div> <script src="../js/vue.js"></script> <script> setTimeout(function () { new Vue({ el: '#app', data: { message: 'hello' } }) }, 2000) </script> </body>
解决
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> [v-cloak]{ display: none; } </style> </head> <body> <div id="app" v-cloak> <div>{{message}}</div> <div>{{message}}</div> </div> <script src="../js/vue.js"></script> <script> setTimeout(function () { new Vue({ el: '#app', data: { message: 'hello' } }) }, 2000) </script> </body> </html>
v-bind 🔍
动态绑定属性,某些属性比如 src ,我们也希望可以动态绑定,这时就可以借助 v-bind 实现
普通使用
<body> <div id="app"> <img v-bind:src="imgURL1" alt="" width="400"> <!-- 简写 --> <img :src="imgURL2" alt="" width="400"> </div> <script src="../js/vue.js"></script> <script> new Vue({ el: '#app', data: { imgURL1: 'http://zhouql.vip/images/tou/t1.png', imgURL2: 'http://zhouql.vip/images/tou/t2.png' } }) </script> </body>
绑定对象
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> .active { color: #FFF; background-color: red; } .hover { color: #FFF; background-color: #69F; } .title { border-radius: 10px; } </style> </head> <body> <div id="app"> <span class="active">{{message}}</span> <span :class="hover">{{message}}</span> <span class="title" :class={active:isActive,hover:!isHover}>{{message}}</span> <button @click="change">点击</button> </div> <script src="../js/vue.js"></script> <script> new Vue({ el: '#app', data: { message: '对象语法动态绑定 class', hover: 'hover', isActive: true, isHover: true }, methods: { change() { this.isActive = !this.isActive; } }, }) </script> </body> </html>
数组语法
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> .active { background-color: red; } .hover { color: #fff; border-radius: 10px; } </style> </head> <body> <div id="app"> <span :class="[active,hover]">{{message}}</span> </div> <script src="../js/vue.js"></script> <script> new Vue({ el: '#app', data: { message: 'Hello', active: 'active', hover: 'hover' } }) </script> </body> </html>
对象语法绑定样式
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> div { margin-top: 10px; width: 400px; } </style> </head> <body> <div id="app"> <div :style="{fontSize:fontSize + 'px',backgroundColor:fontColor,color:color}">对象语法绑定样式</div> <div :style="getStyles()">对象语法绑定样式</div> </div> <script src="../js/vue.js"></script> <script> new Vue({ el: '#app', data: { fontSize: 30, fontColor: 'red', color: '#fff' }, methods: { getStyles() { return { fontSize: this.fontSize + 'px', backgroundColor: this.fontColor, color: this.color } } }, }) </script> </body> </html>
数组语法绑定样式
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div id="app"> <h2 :style="[styleArr]">{{message}}</h2> </div> <script src="../js/vue.js"></script> <script> new Vue({ el: '#app', data: { message: '数组语法', styleArr: { backgroundColor: 'red', color: '#fff', width: '300px' } } }) </script> </body> </html>
小案例 🚩
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>作业</title> <style> li { list-style: none; cursor: pointer; width: 300px; } .bg { background-color: red; color: #fff; } </style> </head> <body> <div id="app"> <ul> <li v-for="(item,index) in movies" @click="changeBgRed(index)" :class="{bg:index == activeIndex}">{{item}} </li> </ul> </div> <script src="../js/vue.js"></script> <script> new Vue({ el: '#app', data: { movies: ['你的名字', '千与千寻', '萤火虫之墓', '天气之子'], activeIndex: 0 }, methods: { changeBgRed(index) { this.activeIndex = index; } } }) </script> </body> </html>