12.vue属性.监听.组件

Posted zhongchao666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了12.vue属性.监听.组件相关的知识,希望对你有一定的参考价值。

1.计算属性

https://cn.vuejs.org/v2/guide/computed.html

new Vue({
    computed:{//定义
         show(){
         
         }
    }
})
++计算属性1.html:++
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
<script src="vue.js"></script>
<script>
window.onload = function(){
    let vm = new Vue({
        el:"#app",
        data:{
            msg:"abc",
            msg2:"msg2"
        },
        methods:{//没有缓存
            reverse(){
                console.log("methods");
                return this.msg.split("").reverse().join("")
            }
        },
        computed:{//有缓存
            reverse2(){//只关心自己
                console.log("computed");
                return this.msg.split("").reverse().join("")
            }   
        }   
    });
};
</script>
</head>

<body>
<div id="app">
    <input v-model="msg" type="text" value=""/><br />
    <input v-model="msg2" type="text" value=""/><br />
    
   {{msg2}}<br />
   {{msg}}<br />
   {{reverse()}}<br />
   {{reverse2}}<br />
</div>
</body>
</html>

res:

只要data中的内容改变,methods就运行,computed只有与其相关的data发生变化才运行.
技术分享图片
技术分享图片

++计算属性2.html:(get,set)++
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
<script src="vue.js"></script>
<script>
//计算属性的名字不出出现在 data/methods中 会有冲突
window.onload = function(){
    vm = new Vue({
        el:"#app",
        data:{
            msg:"abc",  
        },
        computed:{
            /*reverse(){// get
                return this.msg.split("").reverse().join("")
            }   */
            reverse:{
                get(){
                    return this.msg.split("").reverse().join("")
                },
                set(value){
                    console.log("set:",value);  
                    this.msg = value;
                }   
            }
        }   
    });
};
</script>
</head>

<body>
<div id="app">
    <input v-model="msg" type="text" value=""/><br /> 
    <input v-model="reverse" type="text" value=""/><br /> 
    {{msg}}<br />
    {{reverse}}<br />
</div>
</body>
</html>

res:
技术分享图片

使用

{{show}}

注意事项:

1、名字:data/methods里面不能出现, 会有冲突
2、计算属性可以修改 前提条件—— 必须有set
3、方法可以调用计算属性 计算属性页可以调用方法
4、==计算属性必须有返回值 使用的时候不带括号!==

show(){}

show:{
    get(){},
    set(value){...}
}
++计算属性3.html:++

方法调用计算属性 计算属性页可以调用方法;
计算属性必须有返回值 使用的时候不带括号!

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
<script src="vue.js"></script>
<script>
//方法调用计算属性   计算属性页可以调用方法
window.onload = function(){
    vm = new Vue({
        el:"#app",
        data:{
            a:12,
            b:5 
        },
        methods:{
            sum(){
                return this.sum2;   
                //return this.sum2();//不能带括号    
            }   
        },
        computed:{
            sum2(){
                return parseInt(this.a) + parseInt(this.b);
            } 
        }   
    });
};
</script>
</head>

<body>
<div id="app">
    <input v-model="a" type="text" value=""/><br /> 
    <input v-model="b" type="text" value=""/><br /> 
    {{sum()}}<br />
    {{sum2}}<br />
</div>
</body>
</html>

res:
技术分享图片


2.监听 watch

let vm = new Vue({

    watch:{
          wd(){},
          wd:"方法名 show",
          wd:[fn1,fn2....],
          ["json.wd"](){}
          json:{
          handler: function (val, oldVal) { /* ... */ },
          deep: true//深度监听
          immediate: true//立即执行
        },
    }
});

vm.$watch
https://cn.vuejs.org/v2/api/#vm-watch

++监听1.html:++
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
<script src="vue.js"></script>
<script src="vue-resource.js"></script>
<script>
window.onload = function(){
    let url = "https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su";
    let vm = new Vue({
        el:"#app",
        data:{
            wd:"abc",
            arr:[1,2,3] 
        },
        methods:{
            show(){
                console.log("methods");
                this.$http.jsonp(url,{params:{wd:this.wd},jsonp:"cb"}).then(res=>{
                    this.arr = res.data.s;  
                }); 
            } 
        },
        watch:{
            /*wd(){
                this.show();
            }   */
            wd:"show"
        }
         
    });
};
</script>
</head>

<body>
<div id="app">
    <input v-model="wd" type="text" value=""/><br /> 
    <ul>
        <li v-for="item in arr">{{item}}</li>
    </ul>
</div>
</body>
</html>

res:
技术分享图片

++监听2.html:++
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
<script src="vue.js"></script>
<script src="vue-resource.js"></script>
<script>
window.onload = function(){
    let url = "https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su";
    let vm = new Vue({
        el:"#app",
        data:{
            json:{wd:"abc"},
            arr:[1,2,3] 
        },
        methods:{
            show(){
                console.log("methods");
                this.$http.jsonp(url,{params:{wd:this.json.wd},jsonp:"cb"}).then(res=>{
                    this.arr = res.data.s;  
                }); 
            } 
        },
        watch:{
        /*  ["json.wd"](){
                this.show();
            },  */
            //深度监听
            json:{
              handler: function () {
                this.show();  
              },
              deep: true,
              immediate: true
            },
        }
         
    });
};
</script>
</head>

<body>
<div id="app">
    <input v-model="json.wd" type="text" value=""/><br /> 
    <ul>
        <li v-for="item in arr">{{item}}</li>
    </ul>
</div>
</body>
</html>

res:
技术分享图片


3.组件:模板 template 标签

全局组件、局部组件

全局组件
Vue.component("组件的名称、标签名",选项);

选项 options
{template:<div>内容</div>}
exp:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
<script src="vue.js"></script>
<script>
//全局组件
//Vue.component(组件名称,选项);
Vue.component("mycomponent",{
    template:`<div>全局组件</div>`  
});

window.onload = function(){
    let vm = new Vue({
        el:"#app",
        
    });
};
</script>
</head>

<body>
<div id="app">

<mycomponent></mycomponent>
<div is="mycomponent"></div>
<component is="mycomponent"></component>

</div>
</body>
</html>

局部组件

new Vue({
    components:{
            组件的名称、标签名:选项
    }
})

exp:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
<script src="vue.js"></script>
<script>
window.onload = function(){
    let vm = new Vue({
        el:"#app",
        components:{
            mycomponent:{
                template:`<div>局部组件</div>`  
            }   
        }
    });
};
</script>
</head>

<body>
<div id="app">

<mycomponent></mycomponent>

</div>
</body>
</html>
显示三种:
<组件的名称></组件的名称>   
<div is="组件的名称"></div> 
<component is="组件的名称"></component>

==注意事项==:

1、组件必须定义在vue实例化之前
2、推荐使用双标签 单标签慎用,最好不要使用单标签
3、模板里面只能有一个父元素,不能有兄弟节点

==组件的命名规范==:

Component names can only contain alphanumeric characters and the hyphen,
and must start with a letter.
组件名称只能包含【字母】【数字】和【连字符】,并且必须以字母开头。

1、==不能使用中文==
2、==不能使用系统html里面已经存在的标签名==
3、==连字符: 中横线和下划线==
4、==驼峰标识 优先级 my-componen > myComponen > MyComponent==,
页面上使用: ++++

组件可以循环 :必须带上key---> ++:key="id"++

Vue.component("mycomponent",{
    template:`<div>mycomponent组件</div>` 
});

<mycomponent v-for="item in 3" :key="item"></mycomponent>

is:规范标签的写法!
<ul>
    <li>li</li>
    <div>div</div>
    <p>p</p>
</ul>


<table>
    <tbody>
        <tr><td> tr--->td</td></tr>
        /*tr标签为空,div和p标签在table上面*/
        <tr><div>div</div></tr>
        <tr><p>p</p></tr>
    </tbody>
</table>

Vue.component("mytr",{
    template:`<tr><td> tr--->td</td></tr>`  
});
<table>
    <tbody>
          <mytr></mytr>错误写法
          <tr is="mytr"></tr>正确的写法
    </tbody>

</table>

组件通信:vuex

1、父传子 props :子组件的属性="父组件的data"
//通信是单向的 父组件到子组件,子传父自定义事件

2、子传父 this.$emit(自定义事件,数据);
@自定义事件="父组件的函数名"

子组件,data必须是一个函数
props里面的属性不能出现在data中 反之亦然

exp:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
<script src="vue.js"></script>
<script>
//通信是单向的 父组件到子组件
Vue.component("mycomponent",{
    props:["msg"],
    template:`<div>子组件:<input v-model="wd" @input="show" type="text" value=""/>
         {{msg}}------{{wd}}
    </div>`,
    data(){
        return {
            wd:this.msg
        }   
    },
    methods:{
        show(){
            //this.msg = this.wd;
            //console.log(this.wd); 
            this.$emit("abc",this.wd);
        }   
    }
});
window.onload = function(){
    let vm = new Vue({
        el:"#app",
        data:{
            msg:"abc"   
        },
        methods:{
            fn(data){
                console.log("fn:",data);
                this.msg = data;
            }   
        }
    });
};
</script>
</head>

<body>
<div id="app">
    父组件:<input v-model="msg" type="text" value=""/> {{msg}}
    <hr />
    <mycomponent :msg="msg" @abc="fn"></mycomponent>
</div>
</body>
</html>

res:
父传子:
技术分享图片
子传父:
技术分享图片


==props命名规则==

1、props:["props-name"] {{propsName}} :props-name="xxxx"
2、props:["props_name"] {{props_name}} :props_name="xxxx"
3、props:["propsName"] {{propsName}} :props-name="xxxx"
4、props:["PropsName"] {{PropsName}} :props-name="xxxx"
5、props:["AAA"] {{AAA}} :a-a-a="xxxx"

exp:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
<script src="vue.js"></script>
<script>
Vue.component("mycomponent",{
    props:["AAA"],
    template:`<div>组件{{AAA}}</div>`,//不能是中划线
    
});
window.onload = function(){
     
    let vm = new Vue({
        el:"#app", 
        data:{
            msg:"Vue msg"+Math.random()
        }   
    });
};
</script>
</head>

<body>
<div id="app">
    <mycomponent :a-a-a="msg"></mycomponent>
</div>
</body>
</html>

案例

组件通信:
1、自增:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
<script src="vue.js"></script>
<script>
//this.$emit(sEv,data)
Vue.component("mycomponent",{
    props:["count"],
    template:`<div><input @click="handleClick" type="button" value="点我"> {{count}}</div>`,
    methods:{
        handleClick(){
            //this.count++;
            this.$emit("plus",this.count+1);
        }   
    }
});
window.onload = function(){
    let vm = new Vue({
        el:"#app",
        data:{
            count:0
        },
        methods:{
            add(data){
                console.log(1111,data);
                this.count = data;
            }   
        }
    });
};
</script>
</head>

<body>
<div id="app">
    {{count}}
    <hr />
    <mycomponent :count="count" @plus="add"></mycomponent>
</div>
</body>
</html>

res:
技术分享图片

2、百度下拉索引
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
<script src="vue.js"></script>
<script src="vue-resource.js"></script>
<script>

Vue.component("baidu-input",{
    template:`<input v-model="wd" type="text" value=""/>`,  
    data(){
        return {wd:""}
    },
    watch:{
        wd(){
            this.$emit("jsonp",this.wd);    
        }   
    }
});
Vue.component("baidu-list",{
    props:["arr"],
    template:`
        <ul>
            <li v-for="item in arr">{{item}}</li>
        </ul>`, 
});


window.onload = function(){
    let url = "https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su";
    let vm = new Vue({
        el:"#app", 
        data:{
            arr:[],
        },
        methods:{
            baiduJsonp(wd){
                this.$http.jsonp(url,{params:{wd},jsonp:"cb"}).then(res=>{
                    this.arr = res.data.s;  
                }); 
            }   
        }
    });
};
</script>
</head>

<body>
<div id="app">
    <baidu-input @jsonp="baiduJsonp"></baidu-input>
    <baidu-list :arr="arr"></baidu-list>
</div>
</body>
</html>

res:
技术分享图片

3、选项卡

方法一:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
<script src="vue.js"></script>
<script src="vue-resource.js"></script>
<style>
input.active{background:pink;}
</style>
<script>
Vue.component("tab",{
    template:`
        <div>
            <input @click="tab(index)" 
                   :class="{active:iNow==index}"
                   v-for="item,index in title" 
                   type="button" :value="item"/>
            <div>{{content[iNow]}}</div>
        </div>
    `,
    data(){
        return {
            iNow:0,
            title:["aaa","bbb","ccc"],
            content:["aaa","bbb","ccc"],     
        }   
    },
    methods:{
        tab(index){
            this.iNow = index;  
        }   
    }   
});
window.onload = function(){
     
    let vm = new Vue({
        el:"#app", 
        
        
    });
};
</script>
</head>

<body>
<div id="app">
    <tab></tab>
</div>
</body>
</html>

方法二:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
<script src="vue.js"></script>
<script src="vue-resource.js"></script>
<style>
input.active{background:pink;}
</style>
<script>
Vue.component("tab",{
    props:["iNow","title","content"],
    template:`
        <div>
            <input @click="tab(index)" 
                   :class="{active:iNow==index}"
                   v-for="item,index in title" 
                   type="button" :value="item"/>
            <div>{{content[iNow]}}</div>
        </div>
    `,
    methods:{
        tab(index){
            this.$emit("abc",index);    
        }   
    }
    
});
window.onload = function(){
     
    let vm = new Vue({
        el:"#app", 
        data:{
            iNow:0,
            title:["aaa","bbb","ccc"],
            content:["aaa","bbb","ccc"],     
        },
        methods:{
            tab(index){
                this.iNow = index;  
            }   
        }   
    });
};
</script>
</head>

<body>
<div id="app">
    <tab :i-now="iNow" :title="title" :content="content" @abc="tab"></tab>
</div>
</body>
</html>

res:
技术分享图片





































以上是关于12.vue属性.监听.组件的主要内容,如果未能解决你的问题,请参考以下文章

Unity 基础 之 代码动态监听UI交互组件汇总

Unity 基础 之 代码动态监听UI交互组件汇总

JavaFX窗口拖动

vue如何在组件挂载完成之后在监听data中对象或属性的变化

Vue子组件(deep)深度监听props对象属性无效的解决办法

2020-09-13 浅谈: Vue watch监听deep、immediate属性