一、插入内容
{ {Mustache}} 、 v-cloak
{
{Mustache}}
:
{
{Mustache}}
的 Mustache 可以是文本也可以是表达式,同一个标签中也可以有多个{
{Mustache}}
;
示例如下:
<div id="app">
<h2>{
{
name}}</h2>
<h2>{
{
hello}}{
{
name}}</h2>
<h2>{
{
hello + '!' + name}}</h2>
<h2>{
{
count + 1}}</h2>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
name: '张三',
hello: 'hello',
count: 10,
num: 1,
}
});
</script>
效果如下:
当然,在我们网络不佳的时候使用{
{Mustache}}
插入内容时,由于渲染不及时,会发现先出现的是Vue的源代码,然后才是渲染后的视图(html页面);我们可以利用浏览器的一个模拟网速不佳的工具来模拟效果,如下图所示:
很明显,当页面在刷新时显示的是 Vue 的源代码,那么由此 Vue 也提供了一种指令v-cloak
解决这种问题。
v-cloak
使用方法如下:
<style>
[v-cloak]{
display: none;
}
</style>
</head>
<body>
<div id="app" v-cloak>
<h2>{
{
name}}</h2>
<h2>{
{
hello}}{
{
name}}</h2>
<h2>{
{
hello + '!' + name}}</h2>
<h2>{
{
count + 1}}</h2>
</div>
只需在 style 标签对中设置 display: none;
且在使用了{
{Mustache}}
的标签中加入指令v-cloak
即可。
效果如下:
v-text
v-text
和原生中的 innerText
的作用是一样的,都是插入文本内容的方法;
示例如下:
<div id="app">
<h2 v-text='name'></h2>
<h2 v-text='hello + name'></h2>
<h2 v-text='hello + "!" + name'></h2>
<h2 v-text='count + num'></h2>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
name: '张三',
hello: 'hello',
count: 10,
num: 1,
}
});
</script>
效果如下:
注: 单引号中不能包含单引号,双引号中不能包含双引号,不然浏览器识别不了。
v-html
v-html
的用法也和原生 js 中的 innerHTML
的作用是一样的,不仅仅可以添加文本内容,还可以添加标签内容并在浏览器中渲染出来;
示例如下:
<div id="app">
<h2 v-html='dom1'></h2>
<h2 v-html='dom2'></h2>
<h2 v-html='name'></h2>
<h2 v-html='hello + name'></h2>
<h2 v-html='hello + "!" + name'></h2>
<h2 v-html='count + num'></h2>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
dom1: `
<div>hello world</div>
`,
dom2: `
<a href="http://baidu.com">百度一下,你就知道</a>
`,
name: '张三',
hello: 'hello',
count: 10,
num: 1,
}
});
</script>
效果如下:
v-pre
v-pre
会使当前元素及其子元素跳过 Vue 源代码的编译,使其内容直接显示在页面上;
示例如下:
<div id="app">
<h2 v-pre>{
{
name}}
<div>{
{
hello + '!' + name}}</div>
</h2>
<h2 v-pre v-text='hello + name'></h2>
<h2 v-pre>{
{
hello + '!' + name}}</h2>
<h2 v-pre>{
{
count + 1}} 李四</h2>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
dom1: `
<div>hello world</div>
`,
dom2: `
<a href="http://baidu.com">百度一下,你就知道</a>
`,
name: '张三',
hello: 'hello',
count: 10,
num: 1,
}
});
</script>
效果如下:
v-once
v-once
会使当前元素及其子元素或者组件只渲染一次,之后的数据更新并重新渲染会跳过设置了该指令的元素及其子元素或者组件;
示例如下:
<div id="app">
<h2 v-once>{
{
name}}
<div>{
{
hello + '!' + name}}</div>
</h2>
<h2 v-text='hello + name'></h2>
<h2 v-html='dom1'></h2>
<h2>{
{
count + 1}} 李四</h2>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
dom1: `
<div>hello world</div>
`,
dom2: `
<a href="http://baidu.com">百度一下,你就知道</a>
`,
name: '张三',
hello: 'hello',
count: 10,
num: 1,
}
});
</script>
效果如下:
二、条件判断
v-if、 v-else 、 v-else-if
会使当前元素及其子元素或者组件不会被渲染出来;
v-if
示例如下:
<div id="app">
<h2 v-if='bool'>{
{
name}}
<div>{
{
hello + '!' + name}}</div>
</h2>
<h2 v-if='!bool' v-html='dom1'></h2>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
dom1: `
<div>hello world</div>
`,
name: '张三',
hello: 'hello',
bool: true,
}
});
</script>
效果如下:
v-else 、 v-else-if
示例如下:
<div id="app">
<h2 v-if='score >= 90'>优秀</h2>
<h2 v-else-if='score >= 80'>良好</h2>
<h2 v-else-if='score >= 70'>一般</h2>
<h2 v-else-if='score >= 60'>较差</h2>
<h2 v-else='score < 60'>不及格</h2>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
score: 85,
}
});
</script>
效果如下:
从以上示例中,我们可以发现 v-if、 v-else 、 v-else-if
和原生js的条件判断类似,都可以进行判断语句执行相应的操作,但是,当指令后面的条件不成立或者值为 false 时,对应的元素及其子元素或者组件不会被渲染出来,而是销毁了,简单理解就是对应的元素及其子元素或者组件不会出现在Dom中。
v-show
v-show
会使当前元素及其子元素或者组件不会被渲染出来;和v-if、 v-else 、 v-else-if
的使用方法很类似;
示例如下:
<div id="app">
<h2 v-show='!bool'>{
{
name}}
<div>{
{
hello + '!' + name}}</div>
</h2>
<h2 v-show='bool'>{
{
name}}
<div>{
{
hello + '!李四'}}</div>
</h2>
<h2 v-show='bool' v-html='dom1'></h2>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
dom1: `
<div>hello world</div>
`,
name: '张三',
hello: 'hello',
bool: true,
}
});
</script>
效果如下:
那么,v-show
与v-if、 v-else 、 v-else-if
的区别在哪儿呢?从上述图中我们可以发现当其指令的值为false时,v-if、 v-else 、 v-else-if
是将当前元素及其子元素或者组件销毁,而v-show
则是将当前元素及其子元素或者组件设置了 display: none;
;于是在实际开发中我们可以考虑假设频繁切换显示或者隐藏时,就使用v-show
,假设只是切换一次的话,使用v-if、 v-else 、 v-else-if
即可;因为如果频繁切换显示或者隐藏使用v-if、 v-else 、 v-else-if
的话,就会经常性的对当前元素及其子元素或者组件渲染 => 销毁 => 渲染 => 销毁 =>……无疑,这样非常的消耗性能的。
三、遍历循环
v-for
当循环数组时:
示例如下:
打印循环时的 item 的值
<body>
<div id="app">
<div>打印循环时的 item 的值</div>
<div v-for='(item, index) in arr' :key='index' v-text='item'></div>
<br>
<div v-for='(item, index) in objArr' :key='item.id' v-text='item'></div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
arr: [ 1, 2, 3, 4, 5, 6, 6],
objArr: [
{
id: 0011, name: "张三"},
{
id: 0021, name: "李四"},
{
id: 0031, name: "王五"},
]
}
});
</script>
</body>
</html>
效果如下:
打印循环时的 index 的值
<div id="app">
<div>打印循环时的 index 的值</div>
<div v-for='(item, index) in arr' :key='index' v-text='index'></div>
<br>
<div v-for='(item, index) in objArr' :key='item.id' v-text='index'></div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
arr: [ 1, 2, 3, 4, 5, 6, 6],
objArr: [
{
id: 0011, name: "张三"},
{
id: 0021, name: "李四"},
{
id: 0031, name: "王五"},
]
}
});
</script>
</body>
</html>
效果如下:
当循环对象时
示例如下:
<div id="app">
<div>打印循环时的 val 的值</div>
<div v-for='(val, key, index) in obj' :key='key' v-text='val'></div>
<br>
<div>打印循环时的 key 的值</div>
<div v-for='(val, key, index) in obj' :key='key' v-text='key'></div>
<br>
<div>打印循环时的 index 的值</div>
<div v-for='(val, key, index) in obj' :key='key' v-text='index'></div>
<br>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
obj: {
id: 001,
name: '张三',
job: '前端攻城狮',
},
}
});
</script>
效果如下:
如上述所示:
- 当循环数组时:item 的值为 数组中的每一项数据;index 的值则为数组的下标;
- 当循环对象时:val 的值为 对象的键值; key 的值为 对象的键名; index 的值则为对象的下标;
- 当循环的数组中的每一个数据的值为对象时:item 的值为 该数组中的每一个对象,对应的通过item的值就可以获取数组中对象的键值;index 的值则为数组的下标;
- 另外,在循环的时候,官方推荐我们给对应的元素或者组件添加一个
:key
属性;该属性会给渲染的节点添加一个唯一的标识,和 id 值的唯一性一个意思;方便 Diff 算法可以正确的辨识此节点,也可以尽可能的保证在正确的位置插入新的节点;归根结底,添加一个:key
属性是为了能够更高效的更新虚拟Dom。
四、动态绑定属性
v-bind
v-bind
指令可简写为 :
;
该指令可动态绑定属性,什么是动态绑定?其实就是希望该指令绑定的属性值是变动的,可以通过外部传入然后改变属性值,实现某种效果;比如动态改变 class 选择器的值,也就是通过不同的 class 值来改变对应元素的样式;再比如动态传入 a 标签的 href 的值,以及 img 标签的 src 的值等等……
示例如下:
<style>
a{
text-decoration: none;
}
.show{
color: red;
font-weight: bolder;
}
.on{
font-size: 24px;
}
.divBox1{
width: 100px;
height: 50px;
background: #f5f5f5;
text-align: center;
line-height: 50px;
}
.divBox2{
border: 1px solid red;
}
</style>
<div id="app">
<div v-bind:class="{'show': !bool}">hello world</div>
<a v-for='item in urlArr' :key='item.id' v-bind:href="item.aUrl">切换{
{
item.name}}网站 </a>
<div v-bind:class='{"show": !bool, "on": !bool}'>张三</div>
<div v-bind:class='[box1, box2]'>李四</div>
</div>
<!-- 简写之后 -->
<div id="app">
<div :class="{'show': !bool}">hello world</div>
<a v-for='item in urlArr' :key='item.id' :href="item.aUrl">切换{
{
item.name}}网站 </a>
<div :class='{"show": !bool, "on": !bool}'>张三</div>
<div :class='[box1, box2]'>李四</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
bool: false,
urlArr: [
{
id: 1, aUrl: 'https://www.baidu.com/', name: '百度'},
{
id: 2, aUrl: 'https://www.taobao.com/', name: '淘宝'},
{
id: 3, aUrl: 'https://www.jd.com/', name: '京东'},
],
box1: 'divBox1',
box2: 'divBox2',
},
});
</script>
效果如下:
五、事件绑定
v-on
v-on
指令可简写为 @
该指令可动态绑定事件或者自定义事件;
示例如下:
<div id="app">
<div :class="{'show': !bool}">hello world</div>
<button v-on:click='changeHandle'>切换 hello world 与 李四 的样式属性</button>
<!-- v-on 简写之后 -->
<button @click='changeHandle'>(简写)切换 hello world 的样式属性</button>
<br>
<a v-for='item in urlArr' :key='item.id' :href="item.aUrl">切换{
{
item.name}}网站 </a>
<div :class='{"show": !bool, "on": !bool}'>张三</div>
<div :class='[box1, box2]'>李四</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
bool: false,
urlArr: [
{
id: 1, aUrl: 'https://www.baidu.com/', name: '百度'},
{
id: 2, aUrl: 'https://www.taobao.com/', name: '淘宝'},
{
id: 3, aUrl: 'https://www.jd.com/', name: '京东'},
],
box1: 'divBox1',
box2: 'divBox2',
},
methods: {
changeHandle: function(){
if(!this.bool){
this.bool = true;
} else {
this.bool = false;
}
}
}
});
</script>
效果如下:
六、v-model
v-model
指令能使 表单元素 与 数据 两者双向绑定;
v-model的初体验
示例如下:
<div id="app">
<div>
<input type="checkbox" id="f1" v-model='user' value='1'>
<label for="f1">敲代码</label>
<input type="checkbox" id="f2" v-model='user' value="2">
<label for="f2">读书</label>
<input type="checkbox" id="f3" v-model='user' value="3">
<label for="f3">跑步</label>
</div>
<div>
<textarea cols="50" rows="10" v-model='msg' style='resize:none;'></textarea>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
user: [1],
msg: '请输入您的个人介绍',
},
});
</script>
通过双向绑定动态修改 input 框的值为2,效果如下:
v-model 在复选框中的使用
示例如下:
<div id="app">
<div>
<span v-for='fav in favarr' :key='fav.id'>
<input type="checkbox" :value='fav.id' :id='fav.id' v-model='user'>
<label :for="fav.id" v-text='fav.name'></label>
</span>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
user: [1, 2],
favarr: [
{
id: 1, name: 'zhangsan'},
{
id: 2, name: 'lisi'},
{
id: 3, name: 'wangwu'},
{
id: 4, name: 'zhaoliu'},
],
},
});
</script>
效果如下:
如上述:复选框中的 v-model
与 value
是双向绑定的,只要 v-model
的值 user
中(因为是复选,所以是多个数据,所以是数据数组)包含 value
值(value
的值也就是fav.id
)就会默认选中;
v-model 在单选框中的使用
示例如下:
<div id="app">
<div>
<span>请选择你的学历:</span>
<span v-for='item in radioarr' :key='item.id'>
<input type="radio" :id='"f" + item.id' v-model='level' :value='item.id'>
<label :for="'f' + item.id" v-text='item.name'></label>
</span>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
level: 1,
radioarr:[
{
id: 1, name: "高中"},
{
id: 2, name: "大专"},
{
id: 3, name: "本科"},
{
id: 4, name: "硕士"},
],
},
});
</script>
效果如下:
如上述:单选框中 中的 v-model
与 value
是双向绑定的,只要 v-model
中的值 level
(因为是单选所以只需要一个数据就可以,所以是单个数据,而不是数组)包含 value
值(item.id
)就会默认选中;
v-model 在单选下拉选框中的使用
示例如下:
<div id="app">
<div>
<span>单选下拉选框循环:</span>
<select v-model='pro'>
<option v-for="item in list" :key='item.id' :value="item.id" v-text="item.name"></option>
</select>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
pro: 1,
list: [
{
id: 1, name: "广东省"},
{
id: 2, name: "广西省"},
{
id: 3, name: "江西省"},
{
id: 4, name: "河南省"}
],
},
});
</script>
效果如下:
如上述:单选下拉选框中 select
中的 v-model
与 option
中的 value
关联(双向绑定), 这里实现的是 单选 的默认选项,所以 pro
的数据就是一个数字或者字符串;
v-model 在多选下拉选框中的使用
示例如下:
<div id="app">
<div>
<span>多选下拉选框循环:</span>
<select multiple v-model='proList'>
<option v-for="item in proarr" :key='item.id' :value="item.id" v-text="item.name"></option>
</select>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
proList: [1, 2, 3],
proarr: [
{
id: 1, name: "深圳市"},
{
id: 2, name: "惠州市"},
{
id: 3, name: "广州市"},
{
id: 4, name: "东莞市"}
],
},
});
</script>
效果如下:
如上述:多选下拉选框中,下拉选框中 select
中的 v-model
与 option
中的 value
关联(双向绑定), 这里这里实现的是 多选 的默认选项,所以 proList
的数据是数据数组,multiple
是选择(上传)多个的意思;
v-model 的修饰符
lazy
修饰符:表单元素与数据默认是双向绑定的,实时更新视图与数据模型;使用此修饰符后可让视图失去焦点或者回车之后更新;number
修饰符:表单元素默认的输入值的数据类型是string
字符串类型的,如果希望输入值的数据类型为数字则可以使用此修饰符;trim
修饰符:在表单元素中输入内容的前后有很多空格时也会实时更新视图与数据模型,通产我们希望将多余的空格去除,使用此修饰符则可以将其首尾的空白空格自动过滤掉;
示例如下:
<div id="app">
<div>
<!-- lazy 修饰符 -->
<input type="text" v-model.lazy='str1'>
<div v-text='"您输入的是:"+ str1'></div>
<br>
<!-- number 修饰符 -->
<input type="text" v-model.number='count'>
<div v-text='count + " 为 " + typeof count'></div>
<br>
<!-- trim 修饰符 -->
<input type="text" v-model.trim='str2'>
<div v-text='"您输入的是:"+ str2'></div>
<br>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
count: 1,
str1: '',
str2: '',
},
});
</script>
效果如下:
七、组件
什么是组件?组件就是可复用的 vue 实例,例如我们写的 let vm = new Vue()
,这个 vm 就是一个 vue 实例,我们把这个vm 实例称之为 根组件;
局部组件的创建
<div id="app">
<my-zujian1></my-zujian1>
<my-zujian1></my-zujian1>
<my-zujian1></my-zujian1>
</div>
</body>
</html>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el: "#app",
components: {
// 创建了一个局部组件,该局部组件名为 my-zujian1
'my-zujian1': {
template: `
<div>
<h1 v-text='msg'></h1>
<button>点击</button>
<hr>
</div>
`,
data: function(){
return {
msg: '局部组件',
}
},
}
}
});
如代码所示,创建了一个局部组件,该局部组件名为 my-zujian1,在调用组件的时候,可以进行复用;
值得注意的是:局部组件只能在创建局部组件的组件中使用
如下图所示:
全局组件的创建
<div id="app">
<my-hello></my-hello>
<my-hello></my-hello>
</div>
</body>
</html>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 创建了一个全局组件,该全局组件名为my-hello
Vue.component("my-hello", {
template: `
<div>
<h1 v-text='msg'>my-hello</h1>
<button @click='changeMsg'>点击</button>
<hr>
</div>
`,
data: function(){
return {
msg: 1
}
},
mounted: function(){
console.log("my-hello,mounted" );
},
methods:{
changeMsg: function(){
this.msg++;
if(this.msg == 5){
this.msg = 0;
}
}
}
});
let vm = new Vue({
el: '#app'
)
</script>
如代码所示,创建了一个全局组件,该全局组件名为my-hello;
值得注意的是创建的全局组件必须放在根组件的前面,不然会报错:
效果如下:
随之而来的是组件之间的传值问题;
父组件向子组件传值
首先,解释一下什么是父组件与子组件,let vm = new Vue()
这个 vm 是根组件,自然而然的就是所有组件的父组件,甚至是爷爷辈的组件……反之,则为子组件,后代组件,而全局组件,顾名思义则可以在任何需要用到全局组件的地方都能使用,那么父组件如何向子组件传值呢?
父组件向子组件传值使用 props 接收
在 props 中可以给传过来的值指定类型以及是否为必传值;
示例如下:
<div id="app">
<my-zujian1 :bbb="msg" :ccc="foo" ddd="123" @shijian="eventHandle"></my-zujian1>
<h2 v-text="msg"></h2>
</div>
</body>
</html>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component('my-zujian1', {
props: {
aaa: {
type: String, // 指定传过来的值为 String 类型,
required: false // 指定为可选值
},
bbb: {
type: String,
required: false
},
ccc: {
type: Number,
required: false
},
ddd: {
type: String, // 指定传过来的值为 String 类型,
required: true // 指定为必传值
}
},
template: `
<div>
<h2 v-text='aaa'></h2>
<h2 v-text='bbb'></h2>
<h2 v-text='ccc'></h2>
<h2 v-text='ddd'></h2>
<button @click='clickHandle'>点击</button>
<hr>
</div>
`,
methods: {
clickHandle: function(){
this.$emit('shijian'); // 触发当前实例中为 shijian 事件名的事件
}
}
});
var app = new Vue({
el: "#app",
data: {
msg: "组件",
foo: 100
},
methods: {
eventHandle: function(){
this.foo += 10
}
}
});
</script>
效果如下:
子组件向父组件传值
那么子组件如何向父组件传值呢?
子组件向父组件传值使用 vm实例的方法: $emit
。
示例如下:
<body>
<div id="app">
<my-language :value='order' :list="arr" @change='changeHandle'></my-language>
<h1>您选择了:<span v-text='arr[order-1].title'></span></h1>
</div>
</body>
</html>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component('my-language', {
props: {
list: {
type: Array,
required: true,
},
value: {
type: Number,
required: false,
default: 1, // 因为设置了false,意思是可选属性,所以如果没有传递该属性时,设置 1 为默认属性值
}
},
template: `
<div class='language'>
<span
v-for='lan in list'
:class='{"on" : lan.id == value}'
@click='change(lan)'
v-text='lan.title'>
</span>
</div>
`,
mounted: function(){
console.log(this.value);
},
methods: {
change: function(lan){
this.$emit("change", lan);
}
}
});
var app = new Vue({
el: '#app',
data: {
arr:[
{
id: 1, title: "中文"},
{
id: 2, title: "英语"},
{
id: 3, title: "法语"},
{
id: 4, title: "日语"},
{
id: 5, title: "德语"},
],
order: 1,
},
methods: {
changeHandle: function(lan){
console.log('这是子组件发送过来的数据', lan);
this.order= lan.id;
}
}
});
</script>
其实,上述代码还可以利用 v-model 的原理 v-model = v-bind:value v-on:input
来进一步的简化代码;
但是在子组件中必须有一个 value 的数据来符合 v-model 的原理
<style>
.box span{
display: inline-block;
height: 40px;
line-height: 40px;
padding: 0 15px;
border: 1px solid #ccc;
cursor: pointer;
}
.box .on{
color: blue;
}
</style>
<body>
<div id="app">
<my-language :list='arr' v-model='order'></my-language>
<h1>您选择的是:<span v-text='arr[order - 1].name'></span></h1>
</div>
</body>
</html>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component("my-language", {
props: {
list: {
type: Array,
required: true,
},
value: {
type: Number,
required: false,
default: 1,
}
},
mounted: function(){
console.log(this.value);
},
template: `
<div class="box">
<span
v-for='(item, index) in list'
v-text='item.name'
:value='item.id'
:class='{"on": item.id == value}'
@click="$emit('input', item.id)"
></span>
</div>
`,
});
var app = new Vue({
el: "#app",
data: {
arr: [
{
id: 1, name: "中文"},
{
id: 2, name: "英语"},
{
id: 3, name: "法语"},
{
id: 4, name: "德语"},
{
id: 5, name: "日语"},
],
order: 1,
},
});
</script>
效果如下:
兄弟组件的传值
兄弟组件传值也就是属于同一层次关系的组件传值,是通过创建一个 Vue 实例作为媒介,使用Vue 实例方法 $emit
发送数据以及$on
监听数据(接收)来实现兄弟组件之间的传值;
示例如下:
<style>
.box{
display: flex;
}
.box>div{
flex: 1;
}
</style>
</head>
<body>
<div id="app">
<div class="box">
<child-a></child-a>
<child-b></child-b>
</div>
</div>
</body>
</html>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var bus = new Vue();
// 兄弟组件通过 bus.$emit()发送数据
// bus.$on() 监听数据
Vue.component("child-a", {
data: function(){
return {
msg: '',
html: '',
}
},
template: `
<div>
<input type="text" v-model='msg'>
<button @click='send'>➡</button>
<div v-html='html'></div>
</div>
`,
mounted: function(){
var that = this;
bus.$on('chan2', function(value){
// bus.$on() 监听数据
that.html += '<div>张三说:' + value + '</div>'
});
},
methods: {
send: function(){
bus.$emit("chan1", this.msg); // 兄弟组件通过 bus.$emit()发送数据
this.msg = '';
}
}
});
Vue.component("child-b", {
data: function(){
return {
msg: '',
html: '',
}
},
template: `
<div>
<input type="text" v-model='msg'>
<button @click='send'>➡</button>
<div v-html='html'></div>
</div>
`,
mounted: function(){
var that = this;
bus.$on("chan1", function(value){
// bus.$on() 监听数据
that.html += '<div>李四说:' + value + '</div>'
});
},
methods: {
send: function(){
bus.$emit("chan2", this.msg); // 兄弟组件通过 bus.$emit()发送数据
this.msg = '';
}
}
});
var vm = new Vue({
el: "#app",
});
</script>
效果如下:
八、组件的计算属性与监听属性
计算属性
计算属性:computed
当页面中的某些数据需要依赖其他数据进行变动的时候,可以考虑使用计算属性;
示例如下:
<body>
<div id="app">
<span>单价:</span><input type="text" v-model.number='price'>
<span>数量:</span><input type="text" v-model.number='count'>
<h2>合计:<span v-text='total'></span></h2>
<hr>
</div>
</body>
</html>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el: "#app",
data: {
price: '',
count: '',
},
computed: {
total: function(){
return this.price * this.count;
}
},
});
</script>
效果如下:
监听属性
监听属性:watch
当需要实时监听页面中的某些数据,并且当数据变动的时候进行某些操作的时候,可以考虑使用监听属性;
下面就让我们来对比一下 computed 和 watch 的区别;
示例如下:
<body>
<div id="app">
<span>单价:</span><input type="text" v-model.number='price1'>
<span>数量:</span><input type="text" v-model.number='count1'>
<h2>合计:<span v-text='total1'></span></h2>
<hr>
<span>姓:</span><input type="text" v-model.string="surname1">
<span>名:</span><input type="text" v-model.string="name1">
<h2>全名:<span v-text='fullName1'></span></h2>
</div>
</body>
</html>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el: "#app",
data: {
price1: '',
count1: '',
total1: '',
surname1: "",
name1: "",
fullName1: '',
},
watch: {
price1: function(newVal, oldVal){
console.log(newVal, oldVal);
this.total1 = newVal + this.count1;
},
count1: function(newVal, oldVal){
this.total1 = this.price1 + newVal;
},
surname1: function(newVal, oldVal){
this.fullName1 = newVal + this.name1;
},
name1: function(newVal, oldVal){
this.fullName1 = this.surname1 + newVal;
}
}
});
</script>
效果如下:
可以看出,当数据在实时变动的时候,也会实时展现出来数据;
九、插槽
插槽 v-slot
:该指令的缩写为 # ;
当对应组件中的 slot
没有取名时,默认default
;
当对应组件中的 slot
定义了名字时,就是具名插槽;
示例如下:
<body>
// v-slot 的缩写是#
<div id="app">
<el-child>
// 当对应组件中的slot没有取名时,默认default ,default后面的值 scope 的名是自己取的,scope 的值是对应的组件中 slot 标签的属性键值对所组成的对象({ "value": "2001" })
<template v-slot:default='scope'> // scope这个名取什么无所谓
<div>成功:<h3 v-text="scope.value"></h3></div> // 打印的值是组件中定义的 msg 的值
</template>
// 具名插槽
// 当对应组件中的slot定义了名字时,就是具名插槽, 名字就是对应组件中取得名 juming ,juming后面对应的值也是对应的组件中 slot 标签的属性键值对所组成的对象({ "html"": "2020" })
<template #juming='scope'> // scope这个名取什么无所谓
<div>失败:<h3 v-text='scope.html'></h3></div> // 打印的值是组件中定义了 val 的值
</template>
</el-child>
</div>
</body>
</html>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component("el-child", {
template: `
<div id="box">
<header>温馨提示</header>
<main>
<slot :value='msg'></slot>
<slot name='juming' :html="val"></slot>
</main>
<footer>
<span>取消</span>
<span>确定</span>
</footer>
</div>
`,
data: function(){
return {
msg: "2001",
val: '2020',
}
}
});
var vm = new Vue({
el: "#app",
});
</script>
效果如下:
好的,以上就是本人对Vue 的基础知识的汇总 ,如有不足之处,望大神们不吝指出,谢谢!