Vue一些指令和成员变量以及组件一点
表单指令
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>表单指令</title>
</head>
<body>
<div id="app">
<form action="">
<!--属性指令:v-model="变量",v-model绑定的变量控制的是表单元素的value值 -->
<!--普通表单元素,用v-model直接绑定变量控制value值-->
<input type="text" v-model="v1">
<input type="text" v-model="v1">
<textarea name="" id="" cols="30" rows="10" v-model="v1"></textarea>
<p>{{ v1 }}</p>
<hr>
<!--单一复选框-->
同意:
<input type="checkbox" name="agree" v-model="v2">
<hr>
<!--多个复选框-->
男:<input type="checkbox" name="hobbies" value="male" v-model="v3">
女:<input type="checkbox" name="hobbies" value="female" v-model="v3">
哇塞:<input type="checkbox" name="hobbies" value="wow" v-model="v3">
<p>{{ v3 }}</p>
<hr>
<!--单选框-->
中午吃啥:<br>
肉肉:<input name="food" type="radio" value="rourou" v-model="v4">
饭饭:<input name="food" type="radio" value="fanfan" v-model="v4">
<p>{{ v4 }}</p>
<hr>
<button type="submit">提交</button>
</form>
</div>
</body>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
v1: '',
v2: false, // false
v3: ['male', 'wow'],
v4: 'rourou',
}
})
</script>
</html>
v-model 的作用就是form表单中 input 框的value值,变量值会随着你的输入而变化,如果是 checkbox这种点击的东西,那就会直接添加你这个input的value进变量里边去。变量是一个数组。
斗篷指令
因为这个代码会从上往下渲染的,所以最开始根本就不知道你的被Vue控制着,所以会渲染出没有 vue 控制时候的样式,然后读到vue之后就把全部被控制的重新渲染。导致画面一瞬间有闪烁的效果。可以取消这种效果。
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>斗篷指令</title>
<style>
[v-cloak] {
display: none;
}
</style>
</head>
<body>
<div id="app" v-cloak>
<p>{{ msg }}</p>
<p>{{ msg }}</p>
<p>{{ msg }}</p>
<p>{{ msg }}</p>
<p>{{ msg }}</p>
<p>{{ msg }}</p>
<p>{{ msg }}</p>
<p>{{ msg }}</p>
</div>
</body>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
msg: 12345
}
})
</script>
</html>
条件指令
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app">
<!--条件指令:
v-if="true|false",为假时,在页面上不渲染,可以隐藏标签中的信息
v-show="true|false",为假时,在页面中用display:none渲染,虽然没展示,但是任在页面结构中
-->
<p v-if="false">if指令</p>
<p v-show="false">show指令</p>
<!-- v-if是一个家族
v-if
v-else-if
v-else
1、上分支成立,下分支会被屏蔽
2、else分支只要在所有上分支都为假时显示,且不需要条件
-->
<p v-if="v1 === '1'">if分支</p>
<p v-else-if="v1 === '2'">elif分支1</p>
<p v-else-if="v1 === '3'">elif分支2</p>
<p v-else>else分支</p>
<hr>
</div>
</body>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
v1: '2'
}
})
</script>
</html>
条件指令的案例
三个按钮点击后 小方框里面的颜色分别变成 红 黄 绿,并且浏览器会记住最后一次点击的结果,下一次登上去还是上一次的结果。
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>条件指令案例</title>
<style>
.box {
width: 400px;
height: 200px;
}
.r { background-color: red }
.y { background-color: yellow }
.g { background-color: green }
.action {
background-color: pink;
}
</style>
</head>
<body>
<div id="app">
<p>
<button @click="changeC('red')" :class="{action: c === 'red'}">红</button>
<!--<button @click="changeC('red')" :class="c === 'red'? 'action': ''">红</button>-->
<button @click="changeC('yellow')" :class="{action: c === 'yellow'}">黄</button>
<button @click="changeC('green')" :class="{action: c === 'green'}">绿</button>
</p>
<div class="wrap">
<div class="box r" v-if="c === 'red'"></div>
<div class="box y" v-else-if="c === 'yellow'"></div>
<div class="box g" v-else></div>
</div>
</div>
</body>
<script src="js/vue.js"></script>
<script>
// sessionStorage的生命周期与页面标签绑定,当标签页被关闭,数据库被清空
// localStorage是前台永久数据库
// sessionStorage.name = '123';
// localStorage.name = 'xyz';
// localStorage.clear();
new Vue({
el: '#app',
data: {
// 页面重新刷新加载,可以从数据库中获取缓存,如果没有,再取默认值
// c: 'red',
c: localStorage.c ? localStorage.c : 'red',
},
methods: {
changeC(color) {
this.c = color;
// 每一次改变c的值,将值同步到前台数据库
localStorage.c = color; // 存
}
}
})
</script>
</html>
这里引出新的概念 :
sessionStorage :的生命周期与页面标签绑定,当标签页被关闭,数据库被清空
localStorage:是前台永久数据库,需要手动去删除数据,不然就算你重启也还存在
循环指令
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app">
<!--循环指令:
v-for=""
语法:
v-for="成员 in 容器"
-->
<!--1、字符串循环渲染: 可以只遍历值,也可以遍历值与索引-->
<p>
<span v-for="v in title">{{ v }}</span>
</p>
<p>
<span v-for="(v, i) in title">
<span v-if="i != 0"> | </span>
{{ v }}
</span>
</p>
<!--2、数组循环渲染: 可以只遍历值,也可以遍历值与索引-->
<div>
<p v-for="(v, i) in arr">第{{ i }}元素:{{ v }}</p>
</div>
<!--3、对象循环渲染: 可以只遍历值,也可以遍历值与键,还可以遍历值、键与索引-->
<div>
<p v-for="v in people">{{ v }}</p>
</div>
<div>
<p v-for="(v, k) in people">{{ k }}:{{ v }}</p>
</div>
<div>
<p v-for="(v, k, i) in people">{{ i }}-{{ k }}:{{ v }}</p>
</div>
<br>
<div>
<div v-for="(stu, i) in stus">
<hr v-if="i != 0">
<p v-for="(v, k) in stu">{{ k }}:{{ v }}</p>
</div>
</div>
</div>
</body>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
title: '循环指令',
arr: [1, 4, 2, 5, 3],
people: {
name: '兔子',
color: '粉白',
price: 6.66,
},
stus: [
{
name: "Bob",
age: 18
},
{
name: "Tom",
age: 17
},
{
name: "Jerry",
age: 19
}
]
}
})
</script>
</html>
字典确实是没有顺序的,所以它存储起来会特别快,比列表块,他找到有空的内存就放数据进去,但是他的 key 是有顺序的,所以可以取到他的索引。
循环指令案例
一个输入框,可以输入留言,然后在下面直接按顺序展示出来,点击哪条留言就删除哪条。
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app">
<input type="text" v-model="msg">
<button @click="send_comment">留言</button>
<ul>
<li v-for="(v, i) in comments" @click="deleteMsg(i)">{{ v }}</li>
</ul>
</div>
</body>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
msg: '',
comments: []
},
methods: {
send_comment() {
// 数组的增
// push pop unshift shift splice
// this.comments.unshift(this.msg);
// this.comments.splice(0,0,0);
if (this.msg) {
this.comments.push(this.msg); // 留言
this.msg = ''; // 留言后清空输入框
}
},
deleteMsg(index) {
this.comments.splice(index, 1);
}
}
})
</script>
<script>
// 数组操作万能方法,可以完成增删改
let arr = [1, 2, 3];
// 参数:开始索引,操作长度,操作的结果们
arr.splice(2, 0, 100);//索引为2的地方操作0个,替换成100,就是在2和3之间插入100.
arr.splice(1, 1);//索引为1的地方操作一个,也就是2,替换为空,就是删除2。
console.log(arr);
</script>
</html>
分隔符成员
分隔符成员 delimiters 就是一个Vue的成员变量。
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>分隔符</title>
</head>
<body>
<div id="app">
<p>{{ num }}</p>
<!--<p>{[ num ]}</p>-->
<p>{ num ]}</p>
</div>
</body>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
num: 100
},
// 用来修改插值表达式符号
// delimiters: ['{[', ']}'],
delimiters: ['{', ']}'],
})
</script>
</html>
这个成员变量的作用就是用来自定义 {{}} 这个的。但是有一些形式不行,比如 {[ } 这个就不行。
计算属性成员
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app">
<input type="text" v-model="v1">
+
<input type="text" v-model="v2">
=
<button>{{ res }}</button>
</div>
</body>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
v1: '',
v2: '',
// res: '结果',
},
// 1、computed中定义的是方法属性,data中定义的也是属性,所以不需要重复定义(省略data中的)
// 2、方法属性的值来源于绑定的方法的返回值
// 3、方法属性必须在页面中渲染后,绑定的方法才会被启用(调用)
// 4、方法中出现的所有变量都会被监听,任何变量发生值更新都会调用一次绑定的方法,重新更新一下方法属性的值
// 5、方法属性值不能手动设置,必须通过绑定的方法进行设置,比如说你在前面自己就设置<input type="text" v-model="res">,这样你的输入就会直接改变res的值,这是不被允许的,直接报错。
computed: {
res () {
console.log('该方法被调用了');
return this.v1 && this.v2 ? +this.v1 + +this.v2 : '结果';
}
}
})
</script>
<script>
console.log(1 + '2');
console.log(1 - '2');
console.log(+'2');
</script>
</html>
属性的监听
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>属性的监听</title>
</head>
<body>
<div id="app">
<p>
姓名:<input type="text" v-model="full_name">
</p>
<p>
姓:<span>{{ first_name }}</span>
</p>
<p>
名:<span>{{ last_name }}</span>
</p>
</div>
</body>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
full_name: '',
first_name: '',
last_name: '',
},
watch: {
// 1、watch中给已有的属性设置监听方法
// 2、监听的属性值一旦发生更新,就会调用监听方法,在方法中完成相应逻辑
// 3、监听方法不需要返回值(返回值只有主动结束方法的作用)
full_name() {
if (this.full_name.length === 2) {
k_v_arr = this.full_name.split('');
this.first_name = k_v_arr[0];
this.last_name = k_v_arr[1];
}
}
}
})
</script>
</html>
这里有一个疑问,那就是它是对data里面的属性值进行监听的,这些属性值一旦改变就可以自己做一些逻辑操作,但是本来这些属性值变化的时候,别的调用了这个属性的地方也会改变,那要这个成员变量有什么用呢?
因为你不监听的话,只能自己对自己影响,别的用到这个属性的地方确实会因为这个属性值的改变而改变,但是不能对别的属性进行改变,而watch 可以,看上面逻辑就知道了,他因为 full_name 的变化,而改变了 first_name 和 last_name 的值。
vue组件
- 组件:由html、css、js三部分组成的独立单位,可以类似于变量,重复使用,就相当于是一个已经写好了的模板。
- 组件其实就是vue实例(对象),一个组件就是一个vue实例(对象)
- new Vue()产生的也是实例(对象),所以也是组件,我们称之为 根组件,一个页面建议只出现一个根组件(项目开发模式下,一个项目建议只出现一个根组件)
- 组件的html页面结构有 template 实例成员提供
* template提供的html结构是用来构虚拟DOM
* 真实DOM最终会被虚拟DOM替换
* 根组件一般不提供template,就由挂载点el来提供构建虚拟DOM的页面结构,根组件如果提供了template,还需要设置挂载点作为替换占位
* template模板有且只有一个根标签
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app">
{{ msg }}
</div>
</body>
<script src="js/vue.js"></script>
<script>
let c1 = '';
new Vue({
el: '#app',
data: {
msg: '12345',
c1: 'red'
},
template: `
<div id="app">
<p :style="{color: c1}">{{ msg }}</p>
<p @click="clickAction">{{ msg }}</p>
</div>
`,
methods: {
clickAction() {
console.log(this.msg)
}
}
})
</script>
</html>
就是说 ,如果没有写template成员变量的话,就会把挂载点当做模板,如果有写这个成员变量,并且不是空,有内容的话,会自动取代挂载点,成为渲染这个template里面的内容。
子组件
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>子组件</title>
</head>
<body>
<!--根组件的template-->
<div id="app">
<!--在根组件template中加载的组件,称之为根组件的子组件-->
<my-tag></my-tag>
<my-tag></my-tag>
<my-tag></my-tag>
<tag></tag>
</div>
</body>
<script src="js/vue.js"></script>
<script>
// 1、定义组件
// 2、注册组件
// 3、使用组件
// 如何定义子组件:组件就是一个普通对象,内部采用vue语法结构,被vue注册解释后,就会成为vue组件,如何注册,就是把这个对象丢进vue对象的components里面,就注册好了。
let myTag = {
template: `
<div>
<h3>子组件</h3>
<p>我是自定义的子组件</p>
</div>
`,
};
// 了解:全局组件,不要注册就可以直接使用,不建议使用,因为很乱。
Vue.component('tag', {
template: `
<div>
<h3>全局组件</h3>
<p>我是自定义的全局组件</p>
</div>
`,
});
new Vue({
el: '#app',
components: {
// 'my-tag': myTag,
// myTag: myTag,
myTag,
//在html中不支持大小写,所以这里的驼峰体就相当于my-tag,所以上面可以直接用my-tag来调用这个子组件
}
})
</script>
</html>