组件(data,props属性,自定义事件)--插槽分发(slot插槽,具名插槽,插槽作用域)--动态组件(使用方式,keep-alive,refs)--数据处理--生命周期--自定义命令--过滤器
目录
三.组件
五.data
通过 data 属性指定自定义组件的初始数据,要求 data 必须是一个函数,如果不是函数就会报错。
<div id="app">
<!--使用组件-->
<my-hello></my-hello>
<my-hello></my-hello>
<my-hello></my-hello>
</div>
<script type="text/javascript">
/*定义组件需要在实例化vue之前*/
Vue.component("my-hello",{
template:"<button @click='count++'>按钮{{count}}</button>",
// 定义组件内部data: 必须通过函数定义
data:function(){
return {count:0};
}
});
new Vue({
el:"#app",
data:{
}
});
</script>
六.props属性
Props属性
组件可以嵌套使用,叫做父子组件。那么父组件经常要给子组件传递数据这叫做父子组件通信。
父子组件的关系可以总结为 props 向下传递,事件向上传递。
父组件通过 props 给子组件下发数据,子组件通过事件给父组件发送消息。
1、在父组件中定义数据
2、在使用组件时,绑定父组件中的数据
3、在子组件中通过props属性声明父组件中传递过来的参数
4、在template属性中使用父组件中的参数
<div id="app">
<!--使用组件-->
<my-hello :txt1="msg" :txt2="txt"></my-hello>
</div>
<script type="text/javascript">
/*定义组件需要在实例化vue之前*/
Vue.component("my-hello",{
// 声明父组件传递过来的参数
props:["txt1","txt2"],
template:"<div>{{txt1}}:{{txt2}}</div>"
});
new Vue({
el:"#app",
data:{
msg:"来自系统的消息",
txt:"Hello Vue!"
}
});
</script>
七.props校验
子组件在接收父组件传入数据时, 可以进行props校验,来确保数据的格式和是否必传。可以指定一下属性:
1) type: 指定数据类型 String Number Object ...注意不能使用字符串数组,只能是对象大写形式
2) required: 指定是否必输
3) default: 给默认值或者自定义函数返回默认值
4) validator: 自定义函数校验
<div id="app">
<!--使用组件-->
<my-hello class="item" style="font-size: 30px;color:pink;" ></my-hello>
</div>
<script type="text/javascript">
/*定义组件需要在实例化vue之前*/
Vue.component("my-hello",{
template:"<span class='test' style='color:red'>Vue</span>"
});
new Vue({
el:"#app"
});
</script>
八. 非props属性
引用子组件时,非定义的props属性,自动合并到子组件上,class和style也会自动合并。
<div id="app">
<!--使用组件-->
<my-hello :txt1="msg" :txt2="txt" :txt3="msg2" :txt5="money"></my-hello>
</div>
<script type="text/javascript">
/*定义组件需要在实例化vue之前*/
Vue.component("my-hello",{
// 声明父组件传递过来的参数
// props:["txt1","txt2"], // 数组不能做校验
// 对象可以做校验
props:{
// 基础类型检测 (`null` 指允许任何类型)
txt1:[String, Number], // 可以支持多个
txt2:String,
// 必传且是字符串
txt3:{
required:true,
type:String
},
// 数值且有默认值
txt4:{
type:Number,
default: 100
},
// 自定义验证函数
txt5:{
validator:function(value){
return value > 10;
}
}
},
template:"<div>{{txt1}}:{{txt2}}---{{txt3}}---{{txt4}}----{{txt5}}</div>"
});
new Vue({
el:"#app",
data:{
msg:"来自系统的消息",
txt:"Hello Vue!",
msg2:"Admin",
num:10,
money:19
}
});
</script>
九.自定义事件
父组件给子组件传值使用props属性, 那么需要子组件更新父组件时,要使用自定义事件$on和$emit:
$on监听: 不能监听驼峰标示的自定义事件, 使用全部小写(abc)或者-(a-b-c)
$emit主动触发: $emit(事件名,传入参数)
主动挂载
自定义事件不仅可以绑定在子组件,也可以直接挂载到父组件,使用$on绑定和$emit触发。
<div id="app">
<my-hello v-on:update-count="changecount()"></my-hello>
{{count}}
</div>
<script type="text/javascript">
Vue.component("my-hello",{
template:"<button v-on:click='update'>子组件Child</button>",
methods:{
update:function(){
console.log("点击...");
this.$emit("update-count","自定义事件");
}
}
});
var app = new Vue({
el:"#app",
data:{
count:0
},
methods:{
changecount:function(){
this.count++;
}
}
});
// 主动挂载自定义事件
app.$on("update-count",function(value){
console.log(value);
this.count++;
});
// 触发自定义事件
app.$emit("update-count","这是自定义事件");
</script>
四. 插槽分发
一.slot插槽
<div id="app">
<my-hello></my-hello>
<my-hello>
<h3>你好</h3>
<p>这是p元素</p>
</my-hello>
</div>
<!--使用template标签-->
<template id="tpl1">
<div>
<h4>Hello Vue</h4>
<!--插槽,占位-->
<slot>如果没有传递数据,默认显示这段文本</slot>
</div>
</template>
<script type="text/javascript">
// 自定义组件
Vue.component("my-hello",{
template:"#tpl1",
});
var app = new Vue({
el:"#app"
});
</script>
二.具名插槽
具名插槽
具名插槽slot, 就是给插槽起个名字。
在子组件定时可以定定义多个<slot>插槽,同时通过name属性指定一个名字,如:<slot name='header'>,父组件引用时使用< slot='header'>进行插槽选择。
<div id="app">
<!--<my-hello></my-hello>-->
<my-hello>
<h3 slot="header">你好</h3>
<p slot="footer">这是p元素</p>
</my-hello>
</div>
<!--使用template标签-->
<template id="tpl1">
<div>
<slot name="header">如果没有传递数据,默认显示这段文本</slot>
<div>--------------------</div>
<!--插槽,占位-->
<slot name="footer">如果没有传递数据,默认显示这段文本</slot>
</div>
</template>
<script type="text/javascript">
// 自定义组件
Vue.component("my-hello",{
template:"#tpl1",
});
var app = new Vue({
el:"#app"
});
</script>
三.插槽作用域
作用域插槽slot-scope,
父组件通过<slot>插槽混入父组件的内容, 子组件也可以通过slot作用域向插槽slot内部传入数据,使用方式:<slot text='子组件数据'>,
父组件通过<template slot-scope="props">进行引用。
例1:
<div id="app">
<!--<my-hello></my-hello>-->
<my-hello>
<template slot-scope="props">
<h3>你好----{{props.msg}}----{{props.txt}}</h3>
</template>
</my-hello>
</div>
<!--使用template标签-->
<template id="tpl1">
<div>
<div>--------------------</div>
<!--插槽,占位-->
<slot msg="你好啊" txt="Hello">如果没有传递数据,默认显示这段文本</slot>
</div>
</template>
<script type="text/javascript">
// 自定义组件
Vue.component("my-hello",{
template:"#tpl1",
});
var app = new Vue({
el:"#app"
});
</script>
例2:
<div id="app">
<!--<my-hello></my-hello>-->
<my-hello>
<h3 slot-scope="{msg,txt}">你好----{{msg}}----{{txt}}</h3>
</my-hello>
</div>
<!--使用template标签-->
<template id="tpl1">
<div>
<div>--------------------</div>
<!--插槽,占位-->
<slot msg="你好啊" txt="Hello">如果没有传递数据,默认显示这段文本</slot>
</div>
</template>
<script type="text/javascript">
// 自定义组件
Vue.component("my-hello",{
template:"#tpl1",
});
var app = new Vue({
el:"#app"
});
</script>
五.动态组件
一.使用方式
使用<component>标签的is属性,动态绑定多个组件到一个挂载点,通过改变is绑定值,切换组件。
<div id="app">
<!--3、指定导航-->
/ <a href='#' @click.prevent="page='index'">首页</a>
/ <a href='#' @click.prevent="page='news'">新闻</a>
/ <a href='#' @click.prevent="page='login'">登陆</a>
<!--2、使用component引用-->
<component :is="page"> </component>
</div>
<script type="text/javascript">
// 1、定义组件
Vue.component('index', {
template:'<h5>首页</h5>'
});
Vue.component('news', {
template:'<h5>新闻页</h5>'
});
Vue.component('login', {
template:'<h5>登陆页</h5>'
});
new Vue({
el:"#app",
data:{
page:'index'
}
});
</script>
二.keep-alive
如果把切换出去的组件保留在内存中,可以保留它的状态或避免重新渲染。为此可以添加一个 keep-alive 指令。
<div id="app">
<!--3、指定导航-->
/ <a href='#' @click.prevent="page='index'">首页</a>
/ <a href='#' @click.prevent="page='news'">新闻</a>
/ <a href='#' @click.prevent="page='login'">登陆</a>
<!--2、使用component引用-->
<keep-alive>
<component :is="page"></component>
</keep-alive>
</div>
<script type="text/javascript">
// 1、定义组件
Vue.component('index', {
template:'<h5>首页</h5>',
// 当组件挂载时,触发(钩子函数)
mounted: function () {
console.log('挂载...首页');
}
});
Vue.component('news', {
template:'<h5>新闻页</h5>',
mounted: function () {
console.log('挂载...新闻页');
}
});
Vue.component('login', {
template:'<h5>登陆页</h5>',
mounted: function () {
console.log('挂载...登陆页');
}
});
new Vue({
el:"#app",
data:{
page:'index'
}
});
</script>
三.refs
使用ref 给每个组件起一个固定的名字,方便后续直接引用操作,在父组件中使用$refs访问子组件
<div id="app">
<index ref="ind"></index>
</div>
<script type="text/javascript">
// 1、定义组件
Vue.component('index', {
template:'<div>{{count}}</div>',
data:function(){
return {count:0};
}
});
var app = new Vue({
el:"#app",
});
// 通过refs属性得到指定的自定义组件,修改对应的组件中的值
app.$refs.ind.count=10;
</script>
六.数据处理
一.watch属性
使用 watch 属性来监听数据的变化,同时可以指定监听那个属性。
<div id="app">
{{name}}
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data:{
name:"Tony"
},
// 监听数据的变化
watch:{
name:function(v1,v2) {
console.log(v1,v2)
}
}
});
</script>
二.watch实例
例1:
<div id="app">
<p>
firstName:
<input type="text" :value="firstName" @input="changeFirstName($event)">
</p>
<p>
lastName:
<input type="text" :value="lastName" @input="changeLastName($event)" >
</p>
<h4>{{fullName}}</h4>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data:{
firstName:"Hello",
lastName:"Kitty",
fullName:"Hello Kitty"
},
methods:{
changeFirstName:function(e){
console.log(e.target.value);
this.firstName = e.target.value;
},
changeLastName:function(e){
this.lastName = e.target.value;
}
},
watch:{
firstName:function(newValue,oldValue){
this.fullName = newValue + " " + this.lastName;
},
lastName:function(newValue,oldValue){
this.fullName = this.firstName + " " + newValue;
}
}
});
</script>
例2:
<div id="app">
<p>
firstName:
<input type="text" v-model="firstName">
</p>
<p>
lastName:
<input type="text" v-model="lastName" >
</p>
<h4>{{fullName}}</h4>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data:{
firstName:"Hello",
lastName:"Kitty",
fullName:"Hello Kitty"
},
watch:{
firstName:function(newValue,oldValue){
this.fullName = newValue + " " + this.lastName;
},
lastName:function(newValue,oldValue){
this.fullName = this.firstName + " " + newValue;
}
}
});
</script>
三.$watch
$watch第一个参数是需要监听的属性,第二个是回调函数用法和watch一样。需要取消监听只需拿到监听对象的引用,这个引用是返回一个函数对象,执行该对象就可以取消监听。
同时监听多个属性,可以不指定属性:
<div id="app">
{{firstName}} {{lastName}}
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data:{
firstName:"Hello",
lastName:"Kitty"
}
});
// 监听指定属性
/*app.$watch("firstName",function(newVal,oldVal){
console.log(newVal,oldVal);
});*/
// 监听所有属性
app.$watch(function(){
return this.firstName + " " + this.lastName;
},function(newVal,oldVal){
console.log(newVal,oldVal);
});
</script>
四.computed属性
computed计算属性用于定义比较复杂的属性计
computed和methods区别:
1.计算属性使用computed定义, 方法使用methods定义
2.计算属性使用时不加括号执行符
3.计算属性是基于它们的依赖进行缓存的,计算属性只有在它的相关依赖发生改变时才会重新求值。否则返回之前计算好的值,性能更高!
<script type="text/javascript">
var app = new Vue({
el:"#app",
data:{
firstName:"Hello",
lastName:"Kitty"
},
computed:{
fullName:function(){
return this.firstName + " " +this.lastName;
}
}
});
</script>
五.setter和getter
以指定 setter 进行数据更新,指定getter获取数据
<script type="text/javascript">
var app = new Vue({
el:"#app",
data:{
firstName:"Hello",
lastName:"Kitty"
},
computed:{
fullName:{
// getter 得到fullName的值
get:function(){
return this.firstName + " " + this.lastName;
},
set:function(val){
var arr = val.split(" ");
this.firstName = arr[0];
this.lastName = arr[1];
}
}
}
});
</script>
七.生命周期
常用的生命周期钩子函数有:
1) created: 实例创建完成后被立即调用
2) mounted: 实例挂载完成后被立即调用
3) beforeUpdate: 实例需要渲染之前调用
4) updated: 实例更新后调用
5) destroyed: Vue 实例销毁后调用
<script>
var vm = new Vue({
el:'#root',
data:{
name:'Tim'
},
created: function () {
console.log('实例创建...');
},
mounted:function () {
console.log('实例挂载...');
},
beforeUpdate:function () {
console.log('实例将要更新...');
},
updated:function () {
console.log('实例已更新...');
},
destroyed:function(){
console.log('实例卸载...');
}
});
//改变name
// vm.name = 'Cat';
// vm.$destroy();//卸载
</script>
八.自定义指令
一.自定义使用
全局指令
局部指令
使用directive定义,第一个参数为指令名,使用时加上v-前缀才能生效。
inserted属性指当绑定元素插入到DOM时调用。
<div id="root">
<input type="text" v-focus />
<input type="text" v-focus2 />
</div>
<script>
//自定义全局指令v-focus
Vue.directive('focus',{
//当绑定元素插入到DOM调用
inserted: function (el) {
//元素获取焦点
el.focus();
}
});
var vm = new Vue({
el:'#root',
directives:{
focus2:{
inserted: function (el) {
//元素获取焦点
el.focus();
}
}
}
});
</script>
二.钩子函数
钩子函数的参数有三个:
1)el:当前指令绑定元素
2)binding:当前指令绑定的所有信息对象,有以下属性:
name:指令名,不包括 v- 前缀。
value:指令的绑定值,例如:v-my-directive="1 + 1", value 的值是 2。
oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
expression:绑定值的字符串形式。例如 v-my-directive="1 + 1" ,expression 的值是 "1 + 1"。
arg:传给指令的参数。例如 v-my-directive:foo,arg 的值是 "foo"。
modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar, 修饰符对象 modifiers 的值是 { foo: true, bar: true }。
3)vnode:Vue 编译生成的虚拟节点
4)oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
<div id="root">
<input type="text" v-demo:str.a.ab="1+1"/>
</div>
<script>
//自定义全局指令v-focus
Vue.directive('demo',{
bind: function (el,binding) {
console.log(el);
console.log(binding);
}
});
var vm = new Vue({
el:'#root'
});
</script>
三.图片懒加载
<div id="root">
<div class="item" v-for="img in imgs" v-img="img.url"></div>
</div>
<script>
//定义全局自定义指令v-img
Vue.directive('img',{
bind: function (el,binding) {
//生成随机颜色
var color = parseInt(Math.random()*0xFFFFFF).toString(16);
//设置当前元素的背景,提前进行占位等待图片加载
el.style.background = '#'+color;
//setTimeout模拟图片加载的延时情况
setTimeout(function () {
//创建图片对象
var img = new Image();
//通过binding对象获取真实的图片url
img.src = binding.value;
//将图片元素插入DOM结构
el.appendChild(img);
//随机延时
},Math.random()*3000+500);
}
});
var vm = new Vue({
el:'#root',
data:{
//定义模拟数据
imgs:[
{url:'../img/01.jpg'},
{url:'../img/02.jpg'},
{url:'../img/03.jpg'},
{url:'../img/04.jpg'}
]
}
});
</script>
九.过滤器
Vue允许自定义过滤器,可被用作一些常见的文本格式化。
过滤器可以用在两个地方:mustache 插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持)。
过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符指示:
div id="app">
{{msg | uppercase | length}}
<br />
{{msg | test("<--","--<")}}
</div>
<script type="text/javascript">
// 全局过滤器
Vue.filter("uppercase",function(val){
return val.toUpperCase();
});
var app = new Vue({
el:"#app",
data:{
msg:"hello"
},
// 定义局部过滤器
filters:{
length:function(val){
return val + " " + val.length;
},
test:function(val,a,b){
return a + val + b;
}
}
});
</script>
上一篇: Optional避免空指针的用法
下一篇: C语言 不常见用法汇总(自整理)