前端Vue框架 02 斗篷指令:v-cloak, 指令: 属性指令:v-bind, 表单指令:v-model, 条件指令:v-show v-if, 循环指令:v-for Arr操作 前台数据库(localStorage | sessionStorage)
""" v-cloak:避免屏幕闪烁 1)属性选择器,会将v-cloak属性所在的标签隐藏 2)当vue环境加载后,会将v-cloak属性解析移除,所以内容{{ num }}就会显示出来 3)而现在vue已经准备完毕,所以用户会直接看到数值10,而不会看到 页面从{{ num }}闪烁成数值10 """
<style> [v-cloak] { display: none; } </style> <div id="app" v-cloak> <p>{{ num }}</p> </div> <script> new Vue({ el: '#app', data: { num: 10 }, }) </script>
2.
""" /** 属性指令 * 1)语法:v-bind:属性名="变量" * 2)针对不同属性,使用方式稍微有一丢丢区别 * i)自定义属性以及title这些,直接赋值的,使用方式如下(t是变量,'o'是常量) * <p v-bind:title="t" v-bind:owen="'o'">段落</p> * ii)class属性(重点): * 绑定的变量:值可以为一个类名 "p1",也可以为多个类名 "p1 p2" * 绑定的数组:数组的每一个成员都是一个变量 * 绑定的字典:key就是类名,value是绝对该类名是否起作用 * iii)style属性(了解): * 绑定的变量:值是一个字典 */ """
<p v-bind:title="t" v-bind:owen="'o'">段落</p> <script> new Vue({ el: '#app', data: { t: '悬浮提示', }, }) </script>
<!-- a是变量,值就是类名 b就是类名,不是变量 c是变量,值为布尔,决定b类是否起作用 d是变量,值可以为一个类名 'p1' 也可以为多个类名 "p1 p2 ..." calss="p1 b p2 p3" --> <p v-bind:class="[a, {b: c}]" v-bind:class="d"></p> <script> let app = new Vue({ el: '#app', data: { a: 'p1', c: true, d: 'p2 p3', }, }) </script>
<p v-bind:style="myStyle"></p> <script> let app = new Vue({ el: '#app', data: { myStyle: { width: '50px', height: '50px', backgroundColor: 'pink', borderRadius: '50%' } }, }) </script>
<button v-bind:class="{live: isLive == 1}" v-on:click="changeLive(1)">1</button> <button v-bind:class="{live: isLive == 2}" v-on:click="changeLive(2)">2</button> <button v-bind:class="{live: isLive == 3}" v-on:click="changeLive(3)">3</button> <script> let app = new Vue({ el: '#app', data: { isLive: 1, }, methods: { changeLive (index) { // this就代表当前vue对象,和app变量等价 // app.isLive = index; this.isLive = index; } } }) </script>
<!-- 1)v-bind: 可以简写为 : 2)v-on: 可以简写为 @ --> <button v-bind:class="{live: isLive == 1}" v-on:click="changeLive(1)">1</button> <button :class="{live: isLive == 2}" @click="changeLive(2)">2</button> <button :class="{live: isLive == 3}" @click="changeLive(3)">3</button>
<style> body { /* 不允许文本选中 */ user-select: none; } .d1:hover { color: orange; /* 鼠标样式 */ cursor: pointer; } /* 只有按下采用样式,抬起就没了 */ .d1:active { color: red; } /* div标签压根不支持 :visited 伪类 */ .d1:visited { color: pink; } .d2.c1 { color: orange; } .d2.c2 { color: red; } .d2.c3 { color: pink; } </style> <div id="app"> <div class="d1">伪类操作</div> <br><br><br> <!-- click: 单击 dblclick:双击 mouseover:悬浮 mouseout:离开 mousedown:按下 mouseup:抬起 --> <div :class="['d2', c]" @click="hFn('c1')" @mouseover="hFn('c2')" @mousedown="hFn('c3')">事件处理</div> </div> <script> new Vue({ el: '#app', data: { c: '', }, methods: { hFn (c) { this.c = c } } }) </script>
""" 1)语法:v-model="变量" 2)v-model绑定的变量控制的其实就是value属性值 3)v-model要比v-bind:value要对一个监听机制 4)数据的双向绑定: v-model可以将绑定的变量值映射给表单元素的value v-model还可以将表单元素的新value映射给报道的变量 """
<!-- 两个输入框内容会同时变化 --> <input name="n1" type="text" v-model="v1"> <input name="n2" type="text" v-model="v1"> <script> new Vue({ el: '#app', data: { v1: '' } }) </script>
注意:<button type="submit">提交</button> <!--button不写默认为submit,会提交刷新页面-->
""" /** * 1)语法:v-show="变量" | v-if="变量" * 2)两者的区别: * v-show在隐藏标签时,采用display:none渲染标签,标签通过css隐藏 * v-if在隐藏标签时,不会渲染在页面上 * * 3)v-if有家族:v-if | v-else-if | v-else * v-if是必须的,必须设置条件 * v-else-if可以为0~n个,必须设置条件 * v-else可以为0~1个 * 上方分支成立会屏蔽下方所有分支,从上至下依次类推 */ """
<div id="app"> <div> <p v-show="isShow">show控制显隐</p> <p v-if="isShow">if控制显隐</p> </div> <div> <p v-if="0">你是第1个p</p> <p v-else-if="0">你是第2个p</p> <p v-else>你是第3个p</p> </div> </div> <script> new Vue({ el: '#app', data: { isShow: false, } }) </script>
<style> body { margin: 0 } button { width: 60px; line-height: 40px; float: right; } .bGroup:after { /*消除悬浮带来的塌陷,.bGroup名字可以随意起*/ display: block; content: ''; clear: both; } .box { /* vw: view width vh: view height*/ width: 100vw; /*从左到右距离,包括拖动条*/ height: 200px; } .red { background-color: red; } .green { background-color: green; } .blue { background-color: blue; } button.active { background-color: cyan; } </style> <div id="app"> <div class="bGroup"> <button :class="{active: isShow === 'red'}" @click="isShow = 'red'">红</button> <button :class="{active: isShow === 'green'}" @click="isShow = 'green'">绿</button> <button :class="{active: isShow === 'blue'}" @click="isShow = 'blue'">蓝</button> </div> <div> <div v-if="isShow === 'red'" class="box red"></div> <div v-else-if="isShow === 'green'" class="box green"></div> <div v-else class="box blue"></div> </div> </div> <script> new Vue({ el: '#app', data: { isShow: 'red' } }) </script>
"""
/**
* 1)语法:v-for="ele in obj" obj是被遍历的对象,ele是遍历得到的每一次结果
* 2)遍历可迭代对象的首要结果,都是可迭代对象容器中的值,其次还可以遍历得到索引及键等数据
* 字符串:v-for="v in str" | v-for="(v, i) in str"
* 数组:v-for="v in arr" | v-for="(v, i) in arr"
* 对象:v-for="v in obj" | v-for="(v, k) in obj" | v-for="(v, k, i) in obj"
* 注:v-for遍历要依赖于一个所属标签,该标签及内部所有内容会被遍历复用
*/
"""
<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <title>循环指令</title> </head> <body> <div id="app"> <!-- 遍历数字 5 【1】【2】【3】【4】【5】 --> <p>{{ d1 }}</p> <i v-for="e in d1">【{{ e }}】</i> <hr> <!-- 遍历字符串 abc 【a】【b】【c】 【0a】【1b】【2c】 --> <p>{{ d2 }}</p> <i v-for="e in d2">【{{ e }}】</i> <i v-for="(e, i) in d2">【{{ i }}{{ e }}】</i> <hr> <!-- 遍历数组 [ 1, 3, 5 ] 【1】【3】【5】 【01】【13】【25】 --> <p>{{ d3 }}</p> <i v-for="e in d3">【{{ e }}】</i> <i v-for="(e, i) in d3">【{{ i }}{{ e }}】</i> <hr> <!-- 遍历对象 { "name": "Bob", "age": 17.5, "gender": "男" } 【Bob】【17.5】【男】 【name-Bob】【age-17.5】【gender-男】 【name-Bob-0】【age-17.5-1】【gender-男-2】 --> <p>{{ d4 }}</p> <i v-for="e in d4">【{{ e }}】</i> <i v-for="(e, k) in d4">【{{ k }}-{{ e }}】</i> <i v-for="(e, k, i) in d4">【{{ k }}-{{ e }}-{{ i }}】</i> <hr> </div> </body> <script> new Vue({ el: '#app', data: { d1: 5, d2: 'abc', d3: [1, 3, 5], d4: { name: "Bob", age: 17.5, gender: "男" } } }) </script>
<style> .box { width: 280px; border: 1px solid #eee; border-radius: 5px; overflow: hidden; /* 隐藏超出父级显示范围外的内容 */ text-align: center; /* 文本相关的属性大多默认值是inherit */ float: left; margin: 10px; } .box img { width: 100%; /*有效宽度,不包括右侧拖动条*/ } </style> <div id="app"> <div class="box" v-for="obj in goods"> <img :src="obj.img" alt=""> <p>{{ obj.title }}</p> </div> </div> <script> let goods = [ { "img": "https://***1.jpg", "title": "纯种拆家专家1" }, { "img": "https://***2.jpg", "title": "纯种拆家专家2" }, ]; new Vue({ el: '#app', data: { goods, } }) </script>
准备知识
""" 6、数组操作:unshift、shift、push、pop、splice(begin_index, count, args) function fn (...args) {} 可变长参数 7、前端数据库 localStorage 永久存储 和cookie存储(几k)相比,优势在于能传几m的容量 sessionStorage 生命周期同所属页面标签 和cookie相比,同样能存几m的内容 存:localStorage.key = value 取:localStorage.key 清:localStorage.clear() | localStorage.removeItem(key) """
可以在调试页面中查看
操作如下图, 由localStorage,sessionStorage存储的内容包含域名可以看出,只能在当前域名下用,不是整个浏览器共享的(他们和cookies一样,基于域名安全的同源策略)
"""
尾增:arr.push(ele)
首增:arr.unshift(ele)
尾删:arr.pop()
首删:arr.shift()
增删改插:arr.splice(begin_index, count, args)
"""
"""
// 存
// 持久化化存储,永远保存
localStorage.name = "Bob";
// 持久化化存储,生命周期同所属标签(页面),页面关闭,重新打开就会丢失
sessionStorage.name = "Tom";
// 取
console.log(localStorage.name);
console.log(sessionStorage.name);
// 清空
localStorage.clear();
sessionStorage.clear();
// 短板:只能存储字符串,所有对象和数组需要转换为json类型字符串,再进行存储
let a = [1, 2, 3];
localStorage.arr = JSON.stringify(a);
let b = JSON.parse(localStorage.arr);
console.log(b);
"""
<style> li:hover { color: red; cursor: pointer; } </style> <div id="app"> <form> <input type="text" v-model="info"> <button type="button" @click="sendInfo">留言</button> </form> <ul> <li v-for="(info, index) in info_arr" @click="deleteInfo(index)">{{ info }}</li> </ul> </div> <script> new Vue({ el: '#app', data: { info: '', // 三目运算符: 条件 ? 结果1 : 结果2 info_arr: localStorage.info_arr ? JSON.parse(localStorage.info_arr) : [], }, methods: { sendInfo () { // 完成留言:将info添加到info_arr // 增 push unshift | 删 pop shift if (this.info) { // 留言 this.info_arr.push(this.info); // 清空输入框 this.info = ''; // 前台数据持久化(缓存) localStorage.info_arr = JSON.stringify(this.info_arr); } }, deleteInfo(index) { // 删 this.info_arr.splice(index, 1); // 同步给数据库 localStorage.info_arr = JSON.stringify(this.info_arr); } } }) </script>
""" 1、v-cloak斗篷指令 2、属性指令 v-bind:title="变量" :class="变量" | :class="[变量1, ..., 变量n]" | :class="{类名: 布尔变量}" :style="字典变量" 3、事件:@click @dblclick @mouseover|out|down|up 鼠标单击、双击、悬浮、移开、按下、抬起 4、表单指令: v-model绑定变量控制value属性,可以实现双向绑定 5、条件指令: v-show | v-if v-if | v-else-if | v-else 6、循环指令: 字符串:v-for="v in str" | v-for="(v, i) in str" 数组:v-for="v in arr" | v-for="(v, i) in arr" 对象:v-for="v in obj" | v-for="(v, k) in obj" | v-for="(v, k, i) in obj" 7、Array操作 arr.push(ele) arr.unshift(ele) arr.pop() arr.shift() arr.splice(begin_index, count, args) 8、前台数据库 localStorage | sessionStorage 1)操作就类似于obj,直接 .key 语法访问 value 2)localStorage永久存储 3)sessionStorage生命周期同所属页面标签 """
6道小练习
""" 1、有以下代码(绑定属性title) <div style="width:90px;height:90px;background:red"></div> 点击该标签,就会有一个变量记录点击的次数,且会在该标签被悬浮是用title属性提示用户【当前一共被点击了几下】 ---- <div style="width:90px;height:90px;background:red" @click="num += 1" :title="'当前一共被点击了' + num + '下'"></div> <script> new Vue({ el: '#app', data: { num: 0 } }) </script> ---- 2、有一下代码(绑定属性class,点击事件改变) <style> .l {width:100px;height:50px;background:red;} .r {width:50px;height:50px;background:blue;} .c {width:50px;height:50px;background:cyan;border-radius:50%} </style> <button>长方形</button> <button>正方形</button> <button>圆形</button> <div></div> 初始div是显示长方形,点击不同按钮,可以改变div的形状 ---- <style> .l {width:100px;height:50px;background:red;} .r {width:50px;height:50px;background:blue;} .c {width:50px;height:50px;background:cyan;border-radius:50%} </style> <button @click="myClass = 'l'">长方形</button> <button @click="myClass = 'r'">正方形</button> <button @click="myClass = 'c'">圆形</button> <div :class="myClass"></div> <script> new Vue({ el: '#app', data: { myClass: 'l' } }) </script> ---- 3、能不能在第二题基础上实现,在div自身 按下变正方形,抬起变圆形,移开重新变为长方形(鼠标事件) --- <div :class="myClass" @mousedown="myClass = 'r'" @mouseup="myClass = 'c'" @mouseout="myClass = 'l'"></div> --- 4、有下方代码(表单指令,条件指令) <input type="text" /> <div style="width:100px;height:50px;background:red;"></div> <div style="width:50px;height:50px;background:blue;"></div> <div style="width:50px;height:50px;background:cyan;border-radius:50%"></div> 输入框输入l显示长方形,输入r显示正方形,输入c显示圆形,没内容或是其他内容,不显示任何形状 ---- <input type="text" v-model="isShow"/> <div v-if="isShow === 'l'" style="width:100px;height:50px;background:red;"></div> <div v-else-if="isShow === 'r'" style="width:50px;height:50px;background:blue;"></div> <div v-else-if="isShow === 'c'" style="width:50px;height:50px;background:cyan;border-radius:50%"></div> <script> new Vue({ el: '#app', data: { isShow: '', } }) </script> ---- 5、有以下数据(循环指令) books = [ { name: '西游记', price: 66, author: 'Bob'}, { name: '东游记', price: 77, author: 'Tom'}, { name: '西厢记', price: 88, author: 'Jerry'}, ] 用表格table渲染以上数据 ---- <table border="1"> <tr> <th>书名</th> <th>价格</th> <th>作者</th> </tr> <tr v-for="book in books"> <td v-for="v in book">{{ v }}</td> </tr> </table> <script> books = [ { name: '西游记', price: 66, author: 'Bob'}, { name: '东游记', price: 77, author: 'Tom'}, { name: '西厢记', price: 88, author: 'Jerry'}, ] new Vue({ el: '#app', data: { books, } }) </script> ---- 6、选做题:在第五题基础上, i) 可以在表格每条数据后加一个 删除 按钮,可以删除当前书籍 ii) 可以增加三个输入框,一个提交框,完成新增书籍 iii) 刷新页面数据不会重置 ---- <div id="app"> <form> 书名:<input type="text" v-model="name"> 价格:<input type="text" v-model="price"> 作者:<input type="text" v-model="author"> <button type="button" @click="addBook">新增</button> </form> <table border="1"> <tr> <th>书名</th> <th>价格</th> <th>作者</th> <th>删除</th> </tr> <tr v-for="book in books"> <td v-for="v in book">{{ v }}</td> <td @click="deleteBook">删除</td> </tr> </table> </div> </body> <script src="js/vue.js"></script> <script> books = [ {name: '西游记', price: 66, author: 'Bob'}, {name: '东游记', price: 77, author: 'Tom'}, {name: '西厢记', price: 88, author: 'Jerry'}, ]; new Vue({ el: '#app', data: { books: localStorage.books ? JSON.parse(localStorage.books) : books, name: '', price: '', author: '', }, methods: { deleteBook(index) { this.books.splice(index, 1); localStorage.books = JSON.stringify(this.books); }, addBook() { // 安全处理可以自己写的更详细 if (this.name && this.price && this.author) { this.books.push({ name: this.name, price: this.price, author: this.author }); localStorage.books = JSON.stringify(this.books); } } } }) </script> """