插槽
基本使用
插槽就是子组件中的提供给父组件使用的一个占位符,用slot表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的slot标签.
<body>
<div id="root">
<child>
<p>你好!</p>
</child>
</div>
<script>
Vue.component('child',{
template: `<div>
<p>Hello</p>
<slot></slot>
</div>`
})
var vm = new Vue({
el: "#root"
})
</script>
</body>
传递的内容就能正常显示出来,出现“hello 你好!”
slot插槽也可以定义默认值 父组件如果不传递内容,子组件所传递的slot插槽内容就会被显示;
<div id="root">
<child>
</child>
</div>
<script>
Vue.component('child',{
props: ['content'],
template: `<div>
<p>Hello</p>
<slot>默认内容</slot> //重点在这
</div>`
})
</script>
具名插槽
具名插槽其实就是给插槽取个名字。一个子组件可以放多个插槽,而且可以放在不同的地方,而父组件填充内容时,可以根据这个名字把内容填充到对应插槽中。
在组件中,我给插槽起个名字,一个名字叫"girl",一个名字叫"boy",还有一个不起名字。
然后再child-component内,slot属性对应的内容都会和组件中name一一对应。
没有名字的就是默认插槽!
<div id="app">
<child-component>
<template slot="girl">
漂亮、美丽、购物、逛街
</template>
<template slot="boy">
帅气、才实
</template>
<div>
我是一类人,
我是默认的插槽
</div>
</child-component>
</div>
<script>
Vue.component('child-component',{
template:`
<div>
<h4>这个世界不仅有男人和女人</h4>
<slot name="girl"></slot>
<div style="height:1px;background-color:red;"></div>
<slot name="boy"></slot>
<div style="height:1px;background-color:red;"></div>
<slot></slot>
</div>
`
})
let vm = new Vue({
el:'#app',
data:{
}
})
</script>
作用域插槽
作用域插槽其实就是带数据的插槽,即带参数的插槽,简单的来说就是子组件提供给父组件的参数,该参数仅限于插槽中使用,父组件可根据子组件传过来的插槽数据来进行不同的方式展现和填充插槽内容。
何时使用:如果子组件中的某一部分的数据,每个父组件都会有自己的一套对该数据的不同的呈现方式,这时就需要用到作用域插槽。
<body>
<div id="root">
<child>
<template slot-scope="props">
<h1>{{props.item}}</h1>
</template>
</child>
</div>
<script>
Vue.component('child', {
data: function(){
return {
list: [1, 2, 3, 4]
}
},
template: `<div>
<ul>
<slot
v-for="item of list"
:item=item
></slot>
</ul>
</div>`
})
var vm = new Vue({
el:'#root'
})
</script>
</body>
子组件向父组件插槽里传数据,如 :item=item
父组件接收数据并需在外层使用 作用域插槽(必须用)template,同时声明属性名 接收子组件传递的数据,如 slot-scope="props" , 然后在dom标签使用该数据,通常用插值表达式接收具体数据。
自 2.6.0 起有所更新。已废弃的使用 slot-scope attribute 的语法
为了让 user 在父级的插槽内容中可用,我们可以将 user 作为 slot 元素的一个 attribute 绑定上去:
<slot v-bind:user="user">
{{ user.lastName }}
</slot>
</span>
绑定在 slot 元素上的 attribute 被称为插槽 prop。现在在父级作用域中,我们可以使用带值的 v-slot 来定义我们提供的插槽 prop 的名字:
<current-user>
<template v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</template>
</current-user>
在这个例子中,我们选择将包含所有插槽 prop 的对象命名为 slotProps,但你也可以使用任意你喜欢的名字。
混入 (mixin)
Mixins一般有两种用途:
在你已经写好了构造器后,需要增加方法或者临时的活动时使用的方法,这时用混入会减少源代码的污染。
很多地方都会用到的公用方法,用混入的方法可以减少代码量,实现代码重用。
Mixins的基本用法
从执行的先后顺序来说,都是混入的先执行,然后构造器里的再执行,需要注意的是,这并不是方法的覆盖,而是被执行了两边。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="../assets/js/vue.js"></script>
<title>Mixins Option Demo</title>
</head>
<body>
<h1>Mixins Option Demo</h1>
<hr>
<div id="app">
<p>num:{{ num }}</p>
<P><button @click="add">增加数量</button></P>
</div>
<script type="text/javascript">
//额外临时加入时,用于显示日志
//在构造器里我们也加入了updated的钩子函数
var addLog={
updated:function(){
console.log("数据放生变化,变化成"+this.num+".");
}
}
var app=new Vue({
el:'#app',
data:{
num:1
},
methods:{
add:function(){
this.num++;
}
},
mixins:[addLog]//混入
})
</script>
</body>
</html>
这时控制台输出的顺序是:
mixins数据放生变化,变化成2.
构造器里的updated方法。
当混入方法和构造器的方法重名时,混入的方法无法展现,也就是不起作用。
全局API混入方式
我们也可以定义全局的混入,这样在需要这段代码的地方直接引入js,就可以拥有这个功能了。
Vue.mixin({
updated:function(){
console.log('我是全局被混入的');
}
})
全局混入的执行顺序要前于混入和构造器里的方法。
自定义指令
我们要定义一个v-color的指令,作用就是让文字变成绿色。
Vue.directive('color',function(el,binding,vnode){
el.style='color:'+binding.value;
});
<div v-color="green" id="demo">
{{num}}
</div>
el: 指令所绑定的元素,可以用来直接操作DOM。
binding: 一个对象,包含指令的很多信息。
vnode: Vue编译生成的虚拟节点。
自定义指令的生命周期
// bind:只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个绑定时执行一次的初始化动作。
bind:function(){//被绑定
console.log('1 - bind');
},
// inserted:被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于document中)
inserted:function(){//绑定到节点
console.log('2 - inserted');
},
// update:被绑定于元素所在的模板更新时调用,而无论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新。
update:function(){//组件更新
console.log('3 - update');
},
// componentUpdated:被绑定元素所在模板完成一次更新周期时调用。
componentUpdated:function(){//组件更新完成
console.log('4 - componentUpdated');
},
// unbind:只调用一次,指令与元素解绑时调用。
unbind:function(){//解绑
console.log('5 - unbind');
}
Vue.set全局操作
Vue.set 的作用就是在构造器外部操作构造器内部的数据、属性或者方法。比如在vue构造器内部定义了一个count为1的数据,我们在构造器外部定义了一个方法,要每次点击按钮给值加1.就需要用到Vue.set。
//在构造器外部声明数据
var outData={
count:1,
goodName:'car'
};
var app=new Vue({
el:'#app',
//引用外部数据
data:outData
})
在外部改变数据的三种方法:
- 用Vue.set改变
function add(){
Vue.set(outData,'count',4);
}
- 用Vue对象的方法添加
app.count++;
- 直接操作外部数据
outData.count++;
为什么要有Vue.set的存在?
由于Javascript的限制,Vue不能自动检测以下变动的数组。
当你利用索引直接设置一个项时,vue不会为我们自动更新。
当你修改数组的长度时,vue不会为我们自动更新。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="../assets/js/vue.js"></script>
<title>Vue.set 全局操作</title>
</head>
<body>
<h1>Vue.set 全局操作</h1>
<hr>
<div id="app">
<ul>
<li v-for=" aa in arr">{{aa}}</li>
</ul>
</div>
<button onclick="add()">外部添加</button>
<script type="text/javascript">
function add(){
console.log("我已经执行了");
app.arr[1]='ddd';
//Vue.set(app.arr,1,'ddd');
}
var outData={
arr:['aaa','bbb','ccc']
};
var app=new Vue({
el:'#app',
data:outData
})
</script>
</body>
</html>
这时我们的界面是不会自动跟新数组的,我们需要用Vue.set(app.arr,1,’ddd’)来设置改变,vue才会给我们自动更新,这就是Vue.set存在的意义。