获取网站访客qq 原理,seo网络搜索引擎优化,广州建设工程网,网页设计师相关职业前景模板#xff1a;#xff08;template#xff09;模板声明了数据和最终展现给用户的DOM之间的映射关系。初始数据#xff1a;#xff08;data#xff09;一个组件的初始数据状态。对于可复用的组件来说#xff0c;通常是私有的状态。接收外部参数#xff1a;#xff08…模板template模板声明了数据和最终展现给用户的DOM之间的映射关系。初始数据data一个组件的初始数据状态。对于可复用的组件来说通常是私有的状态。接收外部参数props组件之间通过参数来进行数据的传递和共享。参数默认是单向绑定由上至下但也可以显式声明为双向绑定。方法methods对数据的改动操作一般都在组件的方法内进行。可以通过v-on指令将用户输入事件和组件方法进行绑定。声明周期钩子函数lifecycle hooks一个组件会触发多个生命周期钩子函数比如created、attached、destroyed等。在这些钩子函数中我们可以封装一些自定义的逻辑。和传统的MVC相比这可以理解为Controller的逻辑被分散到了这些钩子函数中。 一、注册组件 全局组件局部组件 1.1全局组件注册Vue.component(didi-component,DIDIComponent) 参数1didi-component注册组件的名称即在HTML中可以使用对应名称的自定义标签来添加组件didi-component/didi-component名称除了使用中划线与html中添加自定义标签一致以外还可以使用小驼峰命名方式来定义名称同样vue内部会自动匹配到中划线的html自定义标签上即‘didi-component’同等于‘didiComponent’也有不规范的写法直接自定义任意英文字符不采用连接符中划线也不采用小驼峰命名也是可以的后面示例中会有出现。 参数2DIDIComponent注册组件的钩构造函数Function,也可以是Object。 1 //组件构造器构造组件
2 var MyComponent Vue.extent({
3 //选项...
4 })
5 //传入选项对象注册全局组件
6 Vue.component(didi-component,{
7 template:divA custom component!/div
8 }) 实例代码代码折叠 1 div idexample2 didi-component/didi-component3 /div4 script5 var DIDIComponent Vue.extend({6 template:divA custom component!/div7 })8 //注册9 Vue.component(didi-component,DIDIComponent)
10 //创建vue根实例
11 new Vue({
12 el:#example
13 })
14 /script View Code 1.2局部组件注册也可以说是在vue实例上注册组件。 1 div idexample2 didi-component/didi-component3 /div4 script 5 //注册局部组件6 var DIDIComponent Vue.extend({7 template:divi am child!/div8 });9 new Vue({
10 el:#example,
11 components:{
12 didiComponent:DIDIComponent
13 }
14 });
15 /script 所谓局部组件就是不使用Vue.component()注册组件而是直接在vue实例上通过component添加组件上面的示例中将组件构造写在实例外面也可以直接写在实例中 1 new Vue({
2 el:#example,
3 components:{
4 didiComponent:Vue.extend({
5 template:divi am child!/div
6 })
7 }
8 }); 注现在的vue中构造组件可以不用写Vue.extend()方法而是可以直接写成对象形式后面的示例中将全部省略Vue.extend()。 全局组件与局部组件除了全局组件通过Vue.component()方法注册而局部组件直接通过component添加到vue实例对象上以外。全局组件注册会始终以构造的形式被缓存而局部组件不被使用时不会被构造缓存而是在vue实例需要时才被构造。虽然说将组件构造缓存在内存中可以提高代码执行效率但是另一方面是消耗大量的内存资源。 除了上面的单个构造注册也可以直接在模板中使用引用其他局部组件 1 div idexample2 didi-component/didi-component3 /div4 script5 var Child {6 template:divi am child!/div,7 replace:false8 }9 var Parent {
10 template:div//这个包装元素现在不能使用template标签了以前可以
11 pi am parent/p
12 br/
13 child-component/child-component
14 /div,
15 components:{
16 childComponent:Child//在局部组件模板中直接引用其他局部组件
17 }
18 }
19 new Vue({
20 el:#example,
21 components:{
22 didiComponent:Parent
23 }
24 })
25 /script 二、数据传递 props组件通信slot 2.1通过props实现数据传输 通过v-bind在组件自定义标签上添加HTML特性建立数据传递通道 在组件字段props上绑定自定义标签上传递过来的数据 1 div idexample2 !--将vue实例中的数据resultsList绑定到自定义特性list上--3 didi-component :listresultsList/didi-component4 /div5 script6 //绑定数据7 var Child {8 props:[list],//通过自定义特性list获取父组件上的resultsList9 template: div
10 p
11 span姓名/span
12 span语文/span
13 span数学/span
14 span英语/span
15 /p
16 ul
17 li v-foritem in list :keyitem.name
18 span{{item.name}}/span
19 span{{item.results.language}}/span
20 span{{item.results.math}}/span
21 span{{item.results.english}}/span
22 /li
23 /ul
24 /div
25 }
26 var vm new Vue({
27 el:#example,
28 components:{
29 didiComponent:Child
30 },
31 data:{
32 resultsList:[
33 {
34 name:张三,
35 results:{language:89,math:95,english:90}
36 },
37 {
38 name:李四,
39 results:{language:92,math:76,english:80}
40 },
41 {
42 name:王五,
43 results:{language:72,math:86,english:98}
44 }
45 ]
46 }
47 });
48 /script 通过上面的示例可以了解到子组件获取父组件上的数据过程这你一定会有一个疑问props这里这有什么作用为什么需要props这个字段 a.每个组件都有自己独立的实例模型来管理自己身的属性通过props获取到父组件中自身需要的数据并使用自身属性缓存数据引用可以提高程序执行效率如果将父组件上的数据全盘接收过来对于子组件自身来说会有大量多余的数据反而降低程序执行效率。 b.通过props数据校验保证获取到正确无误的数据提高程序的可靠性。 2.2props接收数据的方式及校验处理 1 //采用数组形式接收父组件通过自定义特性传递过来的数据2 props:[data1,data2,data3...]//数组接收方式只负责数据接收并不对数据校验处理3 4 //采用对象形式接收父组件通过自定义特性传递过来的数据5 props:{6 data1:{7 type:Array,//校验接收数据类型为Arraytype的值还可以是数组添加数据可符合多种数据类型的校验8 default:[{name:我是默认参数,...}],//当data1没有接收到数据时组件就会使用默认数据渲染9 required:true,//校验必须接收到数据不然即使在有默认数据的情况下也会在控制台打印出报错提示
10 validator(value){//校验数据具体信息参数value接收到的是传递过来的数据如果方法返回false则表示数据不符合条件控制台打印出报错提示
11 return value.length 1;
12 }
13 } 采用数据校验只能保证在数据有误时在控制台打印出相对准确的错误提示并不会阻止数据渲染也不会阻塞后面的代码执行。 2.3栈内存传值与单向数据流 1 div idexample2 父级对象传值input typetext v-modelinfo.name/3 父级对象属性传值input typetext v-modelobj.name4 父级字符串传值input typetext v-modelname5 child v-bind:msg1.syncinfo v-bind:msg2obj.name v-bind:msg3name/child6 /div7 script8 new Vue({9 el:#example,
10 data:{
11 info:{
12 name:顺风车
13 },
14 obj:{
15 name:专车
16 },
17 name:快车
18 },
19 components:{
20 child:{
21 props:[msg1,msg2,msg3],
22 template: div
23 接收对象传值input typetext v-modelmsg1.name/
24 接收对象属性传值input typetext v-modelmsg2
25 接收字符串传值input typetext v-modelmsg3
26 /div
27 }
28 }
29 })
30 /script 示例效果 通过示例可以看到vue父子组件传值采用的是父级向子级的单向数据流当父级数据发生变化时子级数据会跟着变化。但同时又因为传递值的方式采用的是栈内存赋值方式如果父级传递给子级的是引用值类型数据在子级中改变数据也会引发父级数据的更改。 注在权威指南中有说可以通过给数据传递添加修饰符once和sync来控制数据的但双向绑定在2.x中测试无效但添加这两个修饰符不报错。关于个问题我想应该是版本更新优化的但不能确定毕竟我没有使用过之前的版本也没有阅读之前版本的手册和源码这个一点暂时保留意见。 由于vue父子组件传值采用了栈内存传值就没有办法保证数据的单向传递解决这个问题的办法很简单在子组件中通过克隆该数据用自身的数据引用保存下来就OK了但要注意在子组件中声明data需要使用function类型。 注即便传递的数据是原始值类型的数据也不要直接使用接收的数据虽然程序能正常运行但是vue在控制台对直接使用原始值的行为报警告所以正确的数据接收方式是通过props接收后在子组件自身的数据上再创建一个数据副本来使用。 data(){return{//自身数据引用名称接收父级传递来的引用数据的克隆数据}
} 三、组件通信 在上一节介绍了父子组件数据传递我们知道vue采用的是单向数据流这就意味着当子组件需要向父组件传值时就得需要其他手段毕竟在更多时候子组件很可能会有复用性情况所以子组件也不能直接去更改父组件的数据但总会有很多需求需要我们将子组件的计算结果传递给父组件。 Vue通过在父级作用域上定义事件然后再由子组件使用$emit来实现事件派送当派送到对应事件作用域时使用派送过来的参数数据触发事件回调函数这就是组件通信。通过组件通信可以解决子组件向父组件传值示例 1 div idexample2 !-- 通过transmitdata接收来自子组件的传输指令然后触发父组件的addComData方法 --3 comment-complate transmitdataaddComData/comment-complate4 ul5 li v-foritem in comList :keyitem.id6 div7 span classuserName{{item.userName}}/span8 span classcomDate{{item.date}}/span9 /div
10 div{{item.val}}div
11 /li
12 /ul
13 /div
14 script
15 var comment {
16 template: div
17 textarea v-modelcomVal/textarea
18 pbutton clicksubmitData提交/button/p
19 /div,
20 data(){
21 return {
22 userId:1001,
23 userName:他乡踏雪,
24 comVal:
25 }
26 },
27 methods:{
28 submitData(){
29 console.log(this.comVal a);
30 var comDate new Date();
31 let comData {
32 id:Number(this.userId comDate.getTime()),
33 userName:this.userName,
34 date:comDate.toLocaleDateString() comDate.toLocaleTimeString(),
35 val:this.comVal
36 }
37 this.$emit(transmitdata,comData);//通过$emit监听提交留言的点击事件被触发后将数据传递给自定义方法transmitdata
38 }
39 }
40 }
41 var vm new Vue({
42 el:#example,
43 components:{
44 commentComplate:comment
45 },
46 data:{
47 comList:[
48 {
49 userName:南都谷主,
50 id:1001,
51 date:2019/7/8 上午00:32:55,
52 val:2017年在长春园东南隅的如园遗址工作人员在进行
53 }
54 ]
55 },
56 methods:{
57 addComData(data){
58 //transmitdata自定义事件接收到数据传递请求后将传递过来的数据交给addComData处理
59 this.comList.unshift(data);
60 }
61 }
62 });
63 /script 一个完整子组件向父组件传值的组件通信示例 如果用来接收数据传输数据的事件是一个原生的DOM事件就不必使用$emit()来监听事件触发只需要在原生的事件声明后添加一个‘.navite’后缀就可以自动实现监听事件触发原生事件本身就是由浏览器自身监听所以不必要多余的操作。如click.navite父组件的事件监听方法。 comment-complate clickaddComData/comment-complate 四、插槽与动态组件 4.1插槽slot/slot 有时候需要在父级组件中给子组件添加一些节点内容这时候就可以在使用slot来实现并且还可以在子组件中使用具名插槽来实现指定位置插入节点。示例 1 div idapp2 child3 span{{titleName}}/span!--插入插槽--4 /child5 /div6 script7 var vm new Vue({8 el:#app,9 components:{
10 child:{
11 template: div
12 slot/slot!--定义插槽--
13 input typetext /
14 /div
15 }
16 },
17 data:{
18 titleName:邮箱
19 }
20 });
21 /script 通过上面的插槽功能就可以动态的切换输入框的标题在一些需求中有多种内容输入方式就不需要去定义多个组件来实现只需要在父级组件来切换输入标题子组件只负责输入操作就可以实现在同一个组件上实现多个输入场景。 有了多种内容输入场景就必然需要多种输入提示这种输入提示必定是需要与输入标题相配合数据必然是同样与标题内容处于父级组件上就需要多个插槽来实现这时候就需要用到具名插槽 1 div idapp2 child3 span slottitle{{titleName}}/span!--插入标题插槽--4 span slothint{{hint}}/span5 /child6 /div7 script8 var vm new Vue({9 el:#app,
10 components:{
11 child:{
12 template: div
13 slot nametitle/slot!--定义标签具名插槽--
14 input typetext /
15 slot namehint/slot!--定义提示具名插槽--
16 /div
17 }
18 },
19 data:{
20 titleName:邮箱,
21 hint:请输入正确的邮箱地址
22 }
23 });
24 /script 通过具名插槽可以将父级插入的节点插入到指定的地方当然这时候你会说可以直接在子组件上来实现这些数据切换这是肯定可行的但是使用子组件实现就必然会涉及到父子组件传值。有可能你也会想到这样的功能也可以使用一个父组件就可以实现为什么还要使用子组件呢这也当然是可以的但是这同样涉及到了另一个问题如果是复杂一点的需求呢所以没有绝对的设计优势这要看具体需求如果是在比较复杂的需求中就可以通过插槽的方式将输入操作与业务逻辑通过组件层级分离。 插槽除了上面的应用在接下来的动态组件中也会有很大作用。 4.2动态组件 所谓动态组件就是在父组件中定义一个子组件可以通过数据来切换实现引入不同的子组件这时你一定会想这不就可以通过v-if和v-else来实现吗注意v-if和v-else来配合实现只能实现两个组件切换而且需要在父组件中引入两个子组件这与动态组件只需要引入一个子组件并且可以切换多个子组件的功能来比较相差甚远。 语法component is“绑定指定的子组件”/component 示例 1 div idapp2 button clickchanegCmp切换组件/button3 component :iscmpType/component4 /div5 script6 const cmpOne {7 template: div8 span组件1/span9 input typetext /
10 /div
11 }
12 const cmpTwo {
13 template: div
14 span组件2/span
15 input typetext /
16 /div
17 }
18 const cmpThree {
19 template: div
20 span组件3/span
21 input typetext /
22 /div
23 }
24 var vm new Vue({
25 el:#app,
26 data:{
27 cmpList:[cmpOne,cmpTwo,cmpThree],
28 cmpType:cmpOne,
29 cmpPresent:0
30 },
31 components:{
32 cmpOne:cmpOne,
33 cmpTwo:cmpTwo,
34 cmpThree:cmpThree
35 },
36 methods:{
37 chanegCmp(){
38 console.log(this.cmpPresent - this.cmpList.length)
39 if( (this.cmpPresent 1) this.cmpList.length){
40 this.cmpPresent 0;
41 this.cmpType this.cmpList[this.cmpPresent];
42 }else{
43 this.cmpPresent ;
44 this.cmpType this.cmpList[this.cmpPresent];
45 }
46 }
47 }
48 });
49 /script 示例实现效果 虽然可以通过动态组件切换组件但是上面的示例可能还并不能是我们想要的因为在切换组件时并不能保留组件的状态比如我们在第一次切换组件时输入文本后第二次切换回到这个组件时输入的文本并不能不被保留也就是说重新切换回来的组件是一个全新的渲染组件并不上次的原组件 针对这种需求vue给我提供了一个标签keep-alive使用这个标签包裹component标签就可以实现保留子组件的状态了所以示例中的代码可以这样修改 1 keep-alive
2 component :iscmpType/component
3 /keep-alive 4.3作用域插槽 在前面的4.1中介绍了插槽它可以在父级来定义相对灵活的子组件在前面的示例中只是介绍了父级在子级指定为节点位置插入一些元素节点这时我想应该又引发了我们的另一个思考既然插槽可以在父级作用定义子级特定位置的节点那可不可以实现父级作用域定义子级特定的数据模板呢也就是子级不仅可以提供一个占位还可以提供数据引用来实现在父级组件中定义元素的节点和数据渲染。这个光是用文字来描述会有点绕先来看一个小示例 1 div idapp2 child :userdatauser!--获取父组件的数据user,并定义新的引用名称userdata--3 template slot-scopelist!--数据模板上通过slot-scope特性接收插槽传来的数据并定义索引名list--4 span{{list.username}} -- {{list.userCom}}/span!--通过模板接收到的数据索引取出数据并渲染到页面--5 /template6 /child7 /div8 script9 const child {
10 props:[userdata],//接收父组件的数据userdata,
11 data(){
12 return{
13 comData:child
14 }
15 },
16 template: div
17 !--通过插槽将接收到父组件的数据和子组件自身的数据传给模板--
18 !--传递数据的方式就是将数据以特性的方式传入slot标签--
19 slot
20 :usernameuserdata.name
21 :userComcomData/slot
22 input typetext/
23 /div
24 }
25 var vm new Vue({
26 el:#app,
27 data:{
28 user:{
29 name:他乡踏雪,
30 }
31 },
32 components:{
33 child:child
34 }
35 });
36 /script 这里的一个关键就是通过slot插槽标签的特性键数据传出然后通过模板特性slot-scope接收这些数据再来提供一个示例来进一步了解作用域插槽 1 div idapp2 cmp-two :listlist3 template slot-scopelist4 li{{list.item}} - {{list.index}}/li5 /template6 /cmp-two7 cmp-two :listlist8 template slot-scopelist9 li{{list.index}} - {{list.item}}/li
10 /template
11 /cmp-two
12 /div
13 script
14 const cmpTwo {
15 props:[list],
16 template:div
17 组件2input tyletext
18 ul
19 slot v-for(item,index) in list
20 :itemitem
21 :indexindex
22 /slot
23 /ul
24 /div
25 }
26 var vm new Vue({
27 el:#app,
28 components:{
29 cmpTwo
30 },
31 data:{
32 list:[1,2,3,4,5]
33 }
34 });
35 /script View Code 转载于:https://www.cnblogs.com/ZheOneAndOnly/p/11129493.html