VUE之指令,组件
一:指令集
(1)v-once
(1)作用:
(1)使得标签内部的属性一旦被赋值便不可以被更改
(2)如果是input框 可以主动输入数据进行更改
(2)使用方式
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<div id="app"> <!-- 其不加 v-once input框内数据可以更改--> <p><input type="text" v-model="num"></p> <!-- 其加了v-once input框内数据不能随着别的数据变动而变动 但是可以主动变动--> <p><input type="text" v-model="num" v-once></p> <!-- 无论标签内部数据是否变动 其都不会变动--> <p v-once>{{num}}</p> </div> </body> <script> let app = new Vue({ el: '#app', data: { num: 0 }, }) </script>
(2)v-cloak
(1)作用:防止页面闪烁
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<style> [v-cloak] { display: none; } </style> <!-- 不处理的情况下,每次新价值该页面,都会先渲染{{}},当vue环境加载成功,{{}}有会被解析消失 --> <!-- 处理后,vue环境没加载好时,#app是被隐藏的,vue环境加载成功,会依次#app的v-cloak属性,就不会出现{{}}渲染闪烁问题 --> <div id="app" v-cloak> {{ }} {{ }} {{ }} </div> <script src="js/vue.js"></script> <script> new Vue({ el: '#app', }) </script>
(3)v-if与v-show
(1)作用:
(1)可以控制标签的显隐
(2)绑定的都是布尔值
(3)v-if不会渲染标签
(5)v-show会以{display:none}的形式隐藏标签
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<div id="app"> <!-- 其下方布尔值对应为false不会再页面渲染出来 且检测内部html标签也不会被渲染--> <p v-if="is_show">if标签渲染</p> <!-- 其下方布尔值对应为false不会再页面渲染出来 检测内部html标签会以display:none的形式渲染--> <p v-show="is_show">show标签渲染</p> </div> </body> <script> let app = new Vue({ el: '#app', data: { is_show: false } }) </script>
(4)v-if条件判断
(1)作用:
(1)类似于条件语句进行逻辑判断
(2)使用方式:
v-if = '布尔值'
v-else-if = '布尔值'
v-else
PS:v-else没有条件 上述条件都不成立 走else条件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<div id="app"> <!-- 情况一 v-if布尔值为真 只有其才会进行页面渲染--> <p v-if="0">if条件语句运行</p> <!-- 情况二 v-else-if布尔值为真 其余都为假 只有其才会进行页面渲染--> <p v-else-if="0">else-if条件语句运行</p> <!-- 情况三 上述if条件都为假 else会进行渲染 且只要if条件对应的布尔值为假 无论else对应的布尔值如何 都会进行渲染--> <p v-else>else条件语句运行</p> </div> </body> <script> let app = new Vue({ el: '#app', }) </script>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<style> .box { width: 400px; height: 300px; } .r { background-color: red; } .y { background-color: yellow } .b { background-color: blue; } </style> </head> <body> <div id="app"> <div class="em"> <p> <!-- 点击事件 此时点击红 页面显示红色框 以此类推--> <button @click="chang_box('rbox')">红</button> <button @click="chang_box('ybox')">黄</button> <button @click="chang_box('bbox')">蓝</button> </p> <!-- 页面渲染三个框 根据showname对应的值不同进行不同的页面渲染 --> <div class="box r" v-if="showname=='rbox'"></div> <div class="box y" v-else-if="showname=='ybox'"></div> <div class="box b" v-else="showname=='bbox'"></div> </div> </div> </body> <script> let app = new Vue({ el: '#app', data: { // 默认渲染红色 showname: 'rbox' }, methods: { // 上述点击事件会进行传参 当传参的参数赋值给函数 函数将传值赋值给showname chang_box(name) { this.showname = name } } }) </script>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <script src="https://cn.vuejs.org/js/vue.min.js"></script> <style> .box { width: 400px; height: 300px; } .r { background-color: red; } .y { background-color: yellow } .b { background-color: blue; } .active { color: blueviolet; } </style> </head> <body> <div id="app"> <div class="em"> <p> <!-- 根据布尔值判断这个按钮字体显示--> <button @click="changeBox('rbox')" :class="{active:showname=='rbox'}">红</button> <button @click="changeBox('ybox')" :class="{active:showname=='ybox'}">黄</button> <button @click="changeBox('bbox')" :class="{active:showname=='bbox'}">蓝</button> </p> <p> <!-- 三元表达式 如果条件成立则给字体进行渲染 如果不成立则将页面置位空--> <button @click="changeBox('rbox')" :class="showname == 'rbox' ? 'active' : ''">红</button> <button @click="changeBox('ybox')" :class="showname == 'ybox' ? 'active' : ''">黄</button> <button @click="changeBox('bbox')" :class="showname == 'bbox' ? 'active' : ''">蓝</button> </p> <div class="box r" v-if="showname == 'rbox'"></div> <div class="box y" v-else-if="showname == 'ybox'"></div> <div class="box b" v-else></div> </div> </div> </body> <script> let app = new Vue({ el: '#app', data: { // 默认渲染红色 showname: 'rbox' }, methods: { // 上述点击事件会进行传参 当传参的参数赋值给函数 函数将传值赋值给showname changeBox(name) { this.showname = name } } }) </script> </html>
(5)v-pre
(1)作用:让标签在受VUE控制区域内的标签 不受VUE控制
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<div id="app"> <p>{{ msg }}</p> <!-- v-pre 指令可以在vue控制范围内,形成局部vue不控制区域 {{ }} 和 v-if 都会原样输出,不会被解析 --> <p v-pre> {{ }} <span v-if="hehe"></span> </p> </div> <script src="js/vue.js"></script> <script> new Vue({ el: '#app', data: { msg: 'message' } }) </script>
(6)v-for
(1)作用:对语句进行for循环
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <script src="https://cn.vuejs.org/js/vue.min.js"></script> </head> <body> <div id="app"> <div> <!-- 基础使用方式--> <span v-for="ch in str">{{ ch }}</span> </div> <div> <!--针对循环遍历的标签 ch循环的一个个原素 index索引,通过会提供key属性来优化渲染速度,但key的值必须唯一(key可以不用提供) --> <span v-for="(ch, index) in str" :key="ch + index">{{ index }}{{ ch }}</span> </div> <div> <!-- 便利字典对应的value--> <p v-for="ele in dic">{{ ele }}</p> </div> <div> <!-- 便利 key,value--> <p v-for="(ele, k) in dic">{{ k }}:{{ ele }}</p> </div> <div> <!-- 便利key value index--> <p v-for="(ele, k, i) in dic">{{ i }}{{ k }}:{{ ele }}</p> </div> </div> </body> <script> new Vue({ el: '#app', data: { str: '鸡你太美啊!', arr: [3, 4, 1, 2, 5], dic: { name: 'SR', age: 18, gender: '男神', } } }) </script> </html>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <script src="https://cn.vuejs.org/js/vue.min.js"></script> <style> li:hover { color: red; cursor: pointer; } li{ list-style: none; } </style> </head> <body> <div id="app"> <p> <input type="text" v-model="userMsg"> <button @click="sendMsg" type="button">留言</button> <ul> <li v-for="(msg, index) in msgs" @click="deleteMsg(index)">{{index}}:{{msg}}</li> </ul> </p> </div> </body> <script> let app = new Vue({ el: '#app', data: { // 三元表达式 判断存储数据库中是否有数据 如果有则渲染出来 msgs: localStorage.msgs ? JSON.parse(localStorage.msgs) : [], // 存储用户留言 userMsg: '' // 用户留言 }, methods: { sendMsg() { // 尾增 // this.msgs.push(this.userMsg); // 首增 // this.msgs.unshift(this.userMsg); let userMsg = this.userMsg; // 获取用户输入的值 if (userMsg) { this.msgs.unshift(userMsg); // 列表首增用户输入数据 localStorage.msgs = JSON.stringify(this.msgs); // 将数据已字符串格式存入前段数据库 this.userMsg = '' // 清空用户的留言框 } }, deleteMsg(index){ // 从索引位置开始操作 操作1位 没有操作结果 this.msgs.splice(index,1) // 开始索引 操作长度 操作的结果们 } } }) </script> </html>
二:属性
(1)计算属性
(1)特点
(1)computed用来声明方法属性的
(2)声明的方法属性 不能与data中定义的重复
(3)方法属性必须在页面中渲染 才会对内部的出现的变量进行监听
(4)计算属性的值 来源于监听方法的返回值
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <script src="https://cn.vuejs.org/js/vue.min.js"></script> </head> <body> <div id="app"> 姓:<input type="text" v-model="fName"> 名:<input type="text" v-model="lName"> 姓名:<b>{{ flName }}</b> </div> </body> <script> let app = new Vue({ el:'#app', data:{ fName:'', lName:'', }, computed:{ flName(){ // fName 与 lName 值发生改变 该方法就会触发 // 计算属性的值 来源于该函数的返回值 flName return this.fName + this.lName } } }) </script> </html>
(2)监听属性
(1)watch为data中已存在的属性设置监听事件
(2)监听属性值发生改变 就会触发该方法
(3)监听事件方法的返回值 无任何意义
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <script src="https://cn.vuejs.org/js/vue.min.js"></script> </head> <body> <div id="app"> 姓名:<input type="text" v-model="fullName"> 姓:<b>{{ firstName }}</b> 名:<b>{{ lastName }}</b> </div> </body> <script> let app = new Vue({ el: '#app', data: { fullName: '', firstName: '', lastName: '', }, watch:{ // 监听事件的开启方式 fullName(){ nameArr = this.fullName.split(''); // 字符串切换列表 this.firstName = nameArr[0]; this.lastName = nameArr[1]; } } }) </script> </html>
三:组件
(1)基本概念
(1)定义:一个包含html + css + js的集合体属于一个组件
(2)分类
(1)根组件:属于new Vue()产生的组件 在项目开发中一个项目 只有一个组件
(2)全局组件:不用注册就可以成为任何一个组件的子组件
(3)局部组件:需要注册才能成为局部组件的一个子组件
(3)特点
(1)每一个组件都包含自己的 html + css + js逻辑
(2)每一个组件都有自己template模板 用来标识自己html结构
(3)每一个template只有一个根标签
(4)根组件一般不提供template模板 就是由真实的挂载点提供
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <script src="https://cn.vuejs.org/js/vue.min.js"></script> </head> <body> <div id="app"> {{msg}} </div> </body> <script> let app = new Vue({ el: '#app', data: { msg: '组件' }, template: ` <div> </div>> // 此时不会被渲染 在加载顺序的时候 其会有限加载虚拟模板 而不是dom内部数据 导致上述内部数据消失 <div>{{msg}}</div> // 其会被加载 <div>{{msg}}</div> // 其不会被加载 一个模板下只有一个根标签 ` }) </script> </html>
(2)局部组件
(1)创建局部组件
(2)注册局部组件
(3)调用局部组件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <script src="https://cn.vuejs.org/js/vue.min.js"></script> <style> .box { box-shadow: 0 3px 5px 0 #666; width: 240px; height: 300px; text-align: center; padding: 20px 0; float: left; margin: 5px; } .box img { width: 200px; } </style> </head> <body> <div id="app"> <!-- 调用局部组件 因为含有大写字母 此时标签不能识别大写字母 因此需要使用---> <local-tag></local-tag> <local-tag></local-tag> </div> </body> <script> // 定义局部组件 给局部组件命名 let localTag = { template: ` <div class="box"> <img src="img/001.png" alt=""> <h3>猫星人</h3> <p>猫星人❤猫星人</p> </div> ` }; let app = new Vue({ el: '#app', // 注册局部组件 components: { localTag // 等价于 localTag:localTag } }) </script> </html>
(3)全局组件
(1)创建全局组件
(2)父组件之间调用
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <script src="https://cn.vuejs.org/js/vue.min.js"></script> <style> .box { box-shadow: 0 3px 5px 0 #666; width: 240px; height: 300px; text-align: center; padding: 20px 0; float: left; margin: 5px; } .box img { width: 200px; } </style> </head> <body> <div id="app"> <!-- 调用局部组件 因为含有大写字母 此时标签不能识别大写字母 因此需要使用---> <global-tag></global-tag> <global-tag></global-tag> <global-tag></global-tag> <global-tag></global-tag> </div> </body> <script> // 定义全局组件 给局部组件命名 Vue.component('global-tag', { template: ` <div class="box" @click="action"> <img src="img/001.png" alt=""> <p>猫星人</p> <p >猫星人❤{{num}}</p> </div>> `, data() { // 给上述的爱心赋值 使用返回值的原因是因为 有多个图片每个对应自己独立的 return { num: 0 } }, methods: { action() { this.num++ } } }); let app = new Vue({ el: '#app', // 注册局部组件 }) </script> </html>
三:组件交互
(1)父传子
(1)基本思路:数据交互 - 父传子 - 通过绑定属性的方式
(1)父组件提供数据
(2)父组件模板中 子组件设置自定义属性 绑定的值由父组件提供
(3)通过props获得自定义的属性
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <script src="https://cn.vuejs.org/js/vue.min.js"></script> <style> .info { text-align: center; width: 200px; padding: 3px; box-shadow: 0 3px 5px 0 pink; float: left; margin: 5px; } .info img { width: 200px; } </style> </head> <body> <div id="app"> <!-- 在父组件模板中,为子组件标签设置自定义属性,绑定的值由父组件提供 --> <!-- my_info属于自定义属性 其值是便利出来的--> <info v-for="info in infos" :key="info.image" :my_info="info"></info> </div> </body> <script> // 给所有被渲染的图片打印信息 let infos = [ { image: 'img/001.png', // 这些都是图片路径 title: '猫星人' }, { image: 'img/002.png', title: '蛋糕' }, { image: 'img/003.png', title: '蓝糕' }, { image: 'img/004.png', title: '二哈' // 图片命名 }, ]; let info = { template: ` <div class="info"> <img :src="my_info.image" alt=""> <p>{{my_info.title}}</p> </div> `, props: ['my_info'] // 通过反射获取上述变量info }; let app = new Vue({ el: '#app', components: { info // 注册局部组件 }, data: { // 为上述组件 提供数据 infos } }) </script> </html>
(2)子传父
(1)基本思路
(1)数据由子组件提供
(2)子组件内部通过触发系统事件,发送一个自定义事件,将数据携带出来
(3)父组件位子组件标签的自定义属性通过方法实现,就可以通过参数拿到子组件传递处理的参数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <script src="https://cn.vuejs.org/js/vue.min.js"></script> <style> .close:hover { cursor: pointer; color: red; } li { list-style: none; } </style> </head> <body> <div id="app"> <p> <input type="text" v-model="userMsg"> <button @click="sendMsg">留言</button> </p> <ul> <!-- 子组件通过触发系统事件 发送一个自定义事件 将数据携带过来 自定义事件remove_msg--> <msg-li v-for="(msg,index) in msgs " :msg='msg' :index='index' @remove_msg="removeAction"></msg-li> </ul> </div> </body> <script> let msgLi = { template: ` <li> <span class="close" @click="deleteMsg(index)">x </span> <span>第{{ index + 1 }}条:</span> <span>{{ msg }}</span> </li> `, props: ['msg', 'index'], methods: { // 自定一个系统事件 传递参数 deleteMsg(index) { // 数据由子组件提供 index this.$emit('remove_msg', index); } } }; let app = new Vue({ el: '#app', data: { msgs: [], userMsg: '' }, components: { msgLi }, methods: { sendMsg() { if (this.userMsg) { this.msgs.unshift(this.userMsg); this.userMsg = '' } }, // 拿到上述自定义事件remove_msg传递过来的参数 index removeAction(index) { this.msgs.splice(index, 1) } } }) </script> </html>