Vue基础
1.v-model指令
v-model实现双向数据绑定
1.1 v-model实现原理
v-model:语法糖
v-model = :value + @input
<div id="app">
方法一: <input type="text" v-bind:value="msg" v-on:input="iptChange">
方法二: <input type="text" v-bind:value="msg" v-on:input="msg = $event.target.value">
<h3>{{msg}}</h3>
</div>
<script>
new Vue({
el: "#app",
data: {
msg:"你好,世界"
},
methods:{
iptChange(e){ //事件对象
this.msg = e.target.value
}
}
})
</script>
1.2 v-model实现双向数据绑定
<div id="app">
<input type="text" v-model="msg">
<h3>{{msg}}</h3>
</div>
<script>
// v-model--双向数据绑定
new Vue({
el: "#app",
data: {
msg: '哈喽哈'
}
})
</script>
1.3 js实现双向数据绑定 ---面试题
<input type="text" id="ipt" value="你好" oninput="getIpt(this.value)">
<h3 class="txt">你好</h3>
<script>
var ipt = document.querySelector('#ipt')
var txt = document.querySelector('.txt')
//声明一个data对象,专门用来存放数据
var data = {}
//Object.defineProperty(对象的名称,属性的名称,配置项)
//get代表定义这个msg时,给他赋值的数据
//set代表拿到最新的值是,要去做什么事情
Object.defineProperty(data, 'msg', {
get: function () {
return '你好,世界'
},
set: function (newVal) {
console.log(newVal);
ipt.value = newVal
txt.innerHTML = newVal
}
})
//修改
ipt.value = data.msg
txt.innerHTML = data.msg
//input值发生了改变
function getIpt(val) {
// console.log(val);
//修改数据源(data.msg),会自动触发set方法
data.msg = val
}
</script>
1.4下拉选择框
<div id="app">
<select v-model="result">
<option value="apple">苹果</option>
<option value="banana">香蕉</option>
<option value="orange">橘子</option>
<option value="mango">芒果</option>
</select>
</div>
<script>
new Vue({
el: "#app",
data: {
result:"banana"
}
})
</script>
2.vue基本指令
2.1 v-pre
让胡子语法({{}})失效
<div id="app">
<!-- v-pre 让胡子语法({{}})失效 -->
<p>当你输入<span v-pre>{{msg}}</span>时,你可以看到{{msg}}</p>
</div>
<script>
new Vue({
el: "#app",
data: {
msg:"你好世界"
}
})
</script>
<!--此时输出{{msg}}字符串-->
2.2 v-html和v-text
胡子语法和v-text一样
v-html会识别html标签
<div id="app">
<!-- 胡子语法和v-text一样 -->
<ul>
<li>{{msg}}</li> <!--你好世界-->
<li v-html='msg'></li> <!--你好世界-->
<li v-text='msg'></li> <!--你好世界-->
<div>-----------------------------------------</div>
<li>{{contain}}</li> <!--<s>12345</s>-->
<li v-html='contain'></li> <!--12345-->
<li v-text='contain'></li> <!--<s>12345</s>-->
</ul>
</div>
<script>
new Vue({
el: "#app",
data: {
msg:'你好世界',
contain:`<s>12345</s>`
}
})
</script>
2.3 v-vloak
v-vloak用于在数据渲染出来之前,将标签隐藏掉,这样用户就看不到胡子语法
访问外部链接时,网不好的情况下会将胡子语法显现出来
<style>
[v-vloak]{
display: none;
}
</style>
div id="app">
<ul>
<li>{{msg1}}</li>
<li v-vloak>{{msg2}}</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
<script>
new Vue({
el: "#app",
data: {
msg1:'你好世界1',
msg2:'你好世界2'
}
})
</script>
2.4 显示隐藏
v-show和v-if
v-show:显示隐藏控制的是css的diaplay属性---频繁切换一个元素的隐藏
v-if:显示隐藏是通过创建和销毁dom元素--一次性渲染元素
<div id="app">
<div class="box" v-show='flag'>盒子一</div>
<div class="box" v-if='flag1'>盒子二</div>
</div>
<script>
new Vue({
el: "#app",
data: {
flag: false,
flag1: false
}
})
2.5 v-if
条件判断
div id="app">
<ul>
<li v-if="score>=90">优秀</li>
<li v-else-if="score>=60">及格</li>
<li v-else>不及格</li>
</ul>
/div>
<script>
new Vue({
el: "#app",
data: {
score:70
}
})
</script>
2.6 v-on
事件
<div id="app">
<button v-on:click="btnClick">按钮1</button>
<!-- 简写 -->
<button @click="btnClick">按钮2</button>
<div class="box" v-show="flag">盒子</div>
</div>
<script>
new Vue({
el: "#app",
// data:存放数据
data: {
flag:true
},
//methods:存放方法
methods:{
btnClick(){
this.flag = !this.flag
}
}
})
</script>
2.7 v-bind
属性绑定
<div id="app">
<a v-bind:href="link">百度</a>
<!-- 简写 -->
<a :href="link">百度</a>
<button @click="goSina()">切换为新浪</button>
</div>
<script>
new Vue({
el: "#app",
data: {
link:"http://baidu.com"
},
methods:{
goSina(){
this.link="http://sina.com.cn"
}
}
})
</script>
3.类名绑定
<style>
.pink{
color: pink;
}
.border{
border: 1px solid rgb(40, 185, 230);
}
</style>
<div id="app">
<h3 v-bind:class="{'pink':isPink}">粉色</h3>
<h3 :class="{'pink':isPink,'border':isBorder}">粉色文字,边框</h3>
<!-- 三元运算符 -->
<h3 :class="isPink ? 'pink ' : ''" >粉色文字,边框</h3>
<h3 :class="isPink&&isBorder ? 'pink border' : ''" >粉色文字,边框</h3>
<!-- 数组 -->
<h3 :class="['pink','border']">粉色文字,边框</h3>
<!-- 函数 -->
<h3 :class="fn()">粉色文字,边框</h3>
</div>
<script>
new Vue({
el: "#app",
data: {
isPink:true,
isBorder:true
},
methods:{
fn(){
return ['pink','border']
}
}
})
</script>
4 style绑定
<div id="app">
<ul>
<li style="background-color:pink;color:blue">背景粉色,文字蓝色</li>
<li :style="{'background-color':bgcColor,color:txtColor}">背景粉色,文字蓝色</li>
<!-- 数组方法 -->
<li :style='colorObj'>背景粉色,文字蓝色</li>
<li :style='[colorObj,italicObj]'>背景粉色,文字蓝色、倾斜</li>
<!-- 函数方法 -->
<li :style="getStyle()">背景粉色,文字蓝色、倾斜</li>
</ul>
</div>
<script>
new Vue({
el: "#app",
data: {
bgcColor:'pink',
txtColor:'blue',
colorObj:{background:'pink',color:'blue'},
italicObj:{fontStyle:'italic'}
},
methods:{
getStyle(){
return [this.colorObj,this.italicObj]
}
}
})
</script>
5 v-for遍历
key作为唯一标识符 ---尽量选择id,而不是index 如果选用index,那么他就失去了唯一性
index在数组发生改变时,自己也会变化,所以当数组是会变化的时候,尽量不要选择index作为key
总结: 当数组不发生变化时(一次性渲染) key可以选用index/id
当数组会发生变化时,这时候会引起html重排,此时选用id
<div id="app">
<ul>
<!-- key值为id -->
<!-- <li v-for="(item,index) in arr" :key="item.id">{{item.name}} <input type="text" ></li> -->
<!-- key值为index -->
<li v-for="(item,index) in arr" :key="index">{{item.name}} <input type="text" ></li>
</ul>
<button @click="unshiftOne()">数组前添加一个</button>
</div>
<script>
new Vue({
el: "#app",
data: {
arr:[
{id:"m1",name:"圈圈"},
{id:"m2",name:"圆圆"},
{id:"m3",name:"点点"},
]
},
methods:{
unshiftOne(){
this.arr.unshift({id:"m4",name:"翠花"})
}
}
})
</script>
当key值为index时:
当key值为id时:
6.计算属性--computed
6.1基本
<div id="app">
<ul>
<li>名:{{firstname}}</li>
<li>姓:{{lastname}}</li>
<li>姓名:{{username}}</li>
</ul>
</div>
<script>
new Vue({
el: "#app",
data: {
firstname:'Michael',
lastname:'Jackson'
},
computed:{
username(){
return this.firstname+' '+this.lastname;
}
}
})
</script>
6.2小进阶
<div id="app">
<ul>
<li>名:{{firstname}}</li>
<li>姓:{{lastname}}</li>
</ul>
姓名:<input type="text" v-model="username">
</div>
<script>
new Vue({
el: "#app",
data: {
firstname:'Michael',
lastname:'Jackson'
},
computed:{
username:{
get(){
return this.firstname+' '+this.lastname;
},
set(newVal){
console.log(newVal);
let arr = newVal.split(" ")
this.firstname = arr[0]
this.lastname = arr[1] || ""
}
}
}
})
</script>
7.computed对比methods
<div id="app">
<ul>
<li>名:{{firstname}}</li>
<li>姓:{{lastname}}</li>
<li>[computed]姓名:{{username}}</li>
<li>[computed]姓名:{{username}}</li>
<li>[methods]姓名:{{username1()}}</li>
<li>[methods]姓名:{{username1()}}</li>
</ul>
</div>
<script>
new Vue({
el: "#app",
data: {
firstname:'Michael',
lastname:'Jackson'
},
methods:{
username1(){
console.log('methods'); //执行多次 methods没缓存
return this.firstname+' '+this.lastname;
}
},
computed:{
username(){
console.log('computed');//执行一次 computed有缓存
return this.firstname+' '+this.lastname;
}
}
})
</script>
8.过滤器
8.1 全局过滤器
<div id="app">
<h3>{{price | filterMoney}}</h3>
</div>
<!-- 全局过滤器的优点 全局使用-->
<div id="app1">
<h3>{{price | filterMoney}}</h3>
</div>
<script>
// Vue.filter('过滤器名称,配置项')
//toFixed(n) 保留n位小数小数
Vue.filter('filterMoney', (val) => {
return "¥" + val.toFixed(2) + "元"
})
new Vue({
el: "#app",
data: {
price: 21.4
}
})
new Vue({
el: "#app1",
data: {
price: 6.6
}
})
</script>
8.2 局部过滤器
<div id="app">
<h3>{{price | filterMoney}}</h3>
</div>
<script>
new Vue({
el: "#app",
data: {
price:6.6
},
filters:{
filterMoney(val){
return "¥" + val.toFixed(2)+"元"
}
}
})
</script>
9.存储
9.1 永久存储
localStorage --永久存储,除非手动删除,否则不会消失
<button id="btn">点击存储</button>
<script>
localStorage.setItem("username","备备")
localStorage.setItem("age","25")
localStorage.setItem("sex","女")
localStorage.removeItem("username")
localStorage.clear()
</script>
9.2 临时存储
sessionStorage --临时存储,只要页面关闭,否则就不会再消失
btn.onclick = function(){
sessionStorage.setItem("username","羽羽")
}
9.3 cookie存储
localStorage和sessionStorage的存储空间有5M cookie的存储空间只有4k
btn.onclick = function(){
document.cookie="username=123"
}