vue组件知识整理

此文章,是我在看vue教程时整理的组件部分知识,其中包括网上找的一些案例,有转载意思,只是我进行了编译,如有维权,请联系。

1.组件分为全局注册局部注册

全局组件注册:必须在new之前注册。
局部组件注册:可以在作用域内使用componentsd 

data 必须是函数

报错:

<body>
    <div id="app">
    	<my-component></my-component>
    </div>
    <script>
    	Vue.component('my-component', {
			template: '<span>{{ message }}</span>',
			data:function() {
				message: 'hello'
			}
		})
    	var vm = new Vue({
    		el:'#app'
    	})
    </script>
</body>

[Vue warn]: Property or method "message" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option.
found in
---> <MyComponent>

       <Root>

VU.M.JS:435(VUE警告):属性或方法“消息”不是在实例上定义的,而是在渲染期间引用的。请确保在数据选项中声明无功数据属性。

修改成

<div id="app">
	<my-component></my-component>
</div>
<script>
	Vue.component('my-component', {
		template: '<span>{{ message }}</span>',
		data:function() {
			return{
				message: 'hello'
			}
		}
	})
	var vm = new Vue({
		el:'#app'
	})
</script>

或者:

<div id="app">
	<my-component></my-component>
</div>
<script>
	var x = { message: 'hello' }
	Vue.component('my-component', {
		template: '<span>{{ message }}</span>',
		data:function() {
			return x
		}
	})
	var vm = new Vue({
		el:'#app'
	})
</script>
什么是prop(支柱)

实际就是,你自定义的标签属性,想传递给替换标签时,使用。


<body>
	<div id="app">
		<blog-post title="my name is dinghongli"></blog-post>
		<blog-post title="my name is dingxiang"></blog-post>
		<blog-post title="my name is dingleiying"></blog-post>
	</div>
	<script>
		Vue.component('blog-post',{
			template:'<h3>{{ title }}</h3>',
			props:['title']
		})
		new Vue({
			el:'#app'
		})
	</script>
</body>
<body>
	<div id="app">
		<blog-post
			v-for="post in posts"
			v-bind:key = 'post.id'
			v-bind:title = "post.title"
		></blog-post>
	</div>
	<script>
		Vue.component('blog-post',{
			template:'<h3>{{ title }}</h3>',
			props:['title']
		})
		new Vue({
			el:'#app',
			data:{
				posts:[
					{ id:1, title:'my name is dinghongli'},
					{ id:2, title:'my name is dingxiang'},
					{ id:3, title:'my name is dingleiying'}
				]
			}
		})
	</script>
</body>

在组件上使用 v-model

<body>
	<div id="blog-posts-events-demo">
	  	<custom-input
		  	v-bind:value="searchText"
		  	v-on:input="searchText = $event"
		></custom-input>
	</div>
	<script>
		Vue.component('custom-input', {
			props: ['value'],
  			template: `
			    <input
				    v-bind:value="value"
				    v-on:input="$emit('input', $event.target.value)"
			    >
  			`
		})
		new Vue({
			el: '#blog-posts-events-demo',
			data:{
				searchText:'dfksjfksfj'
			}


		})
	</script>
</body>
通过插槽分发内容
 
<body>	
	<div id="app">	    
		<alert-box> fdkjfsjfskfjskfjkfjkf </alert-box>	
	</div>	
	<script>		
		Vue.component('alert-box',{			
			template:`<div class="demo-alert-box">				    
						<strong>Error!</strong>      				    
						<slot></slot>			
					</div>`		
		
		})		
		new Vue({			
			el:'#app'		
		})	
	</script>
</body>
动态组件

让多个组件使用同一个挂载点,并动态切换,这就是动态组件。

通过使用保留的 <component> 元素,动态地绑定到它的 is 特性,可以实现动态组件

<body>
	<div id="example">
		<button @click="change">切换页面</button>
		<component  v-bind:is="currentView"></component>
	</div>
	<script>
		var home = { template:'<div>我是主页</div>'};
		var post = { template:'<div>我是提交页</div>'};
		var archive = { template:'<div>我是存档页</div>'};
		new Vue({
			el:'#example',
			components:{
				home,
				post,
				archive
			},
			data:{
				index:0,
				arr:['home','post','archive']
			},
			computed:{
				currentView:function(){
					return this.arr[this.index];
				}
			},
			methods:{
				change:function(){
					this.index = (++this.index)%3;
				}
			}
		})
	</script>
</body>
直接绑定到组件对象上
<body>
	<div id="example">
		<button @click="change">切换页面</button>
		<component :is="currentView"></component>
	</div>
	<script>
		new Vue({
		  	el: '#example',
			data:{
			    index:0,
			    arr:[
			      {template:`<div>我是主页</div>`},
			      {template:`<div>我是提交页</div>`},
			      {template:`<div>我是存档页</div>`}
			    ],
			},
		  	computed:{
			    currentView(){
			        return this.arr[this.index];
			    }
		  	},
		  	methods:{
			    change(){
			      this.index = (++this.index)%3;
			    }
		  	}
		})
</script>
解析DOM模板时的注意事项

固定的标签结构,需用is特性来标识

<body>
<div id="app">
    <table>
        <tr is="my-row"></tr>
    </table>
</div>
<script>
    Vue.component('myRow', {
        template: '<tr>行元素</tr>'
    });
    new Vue({
        el: '#app'
    });
</script>
</body>
组件注册

1.1组件名大小写

驼峰命名,要在标签里替换成短横杠命名

<body>
<div id="app">
    <my-component-name></my-component-name>
</div>
<script>
    Vue.component('myComponentName',{
    template:'<div>哈哈哈哈哈哈哈</div>'
    })
    new Vue({
        el: '#app'
    });
</script>
</body>
全局组件注册:必须在new之前注册。

局部组件注册:可以在作用域内使用components 对于 components 对象中的每个属性来说,其属性名就是自定义元素的名

<body>
	<div id="app">
		<component-a></component-a>
		<component-b></component-b>
		<component-c></component-c>
	</div>
	<script>
		var componentA = { template:'<div>你好</div>'};
		var componentB = { template:'<div>哈哈</div>'};
		var componentC = { template:'<div>嘿嘿</div>'};
	    new Vue({
	        el: '#app',
	        components:{
	        	'component-a':componentA,
	        	'component-b':componentB,
	        	'component-c':componentC
	        }
	    });
	</script>
</body>
注意局部注册的组件在其子组件中不可用。例如,如果你希望 
ComponentA
 在 
ComponentB
 中可用,则你需要这样写:
var ComponentA = { /* ... */ }

var ComponentB = {
  components: {
    'component-a': ComponentA
  },
  // ...
}
传入一个对象的所有属性
<body>
	<div id="app">
	    <blog-post v-bind ="info"></blog-post>
	</div>
	<script>
	    Vue.component('blog-post',{
		props:['vBind'],
		template:'<div>{{ vBind }}</div>'
	    })
	    new Vue({
	        el: '#app',
	        data:{
		    post: {
		        id: 1,
		        likes: 'My Journey with Vue',
		        currentUserFavorited:false,
		        favorited:'',
		        commentIds:'dinghongli'
		    },
		    info:{
			            id: 1,
					        title: 'My Journey with Vue'
				    }
		    }
	    });
	</script>
</body>

vue.js将一个对象的所有属性作为prop进行传递

1.方法一:使用不带参数的v-bind写 :v-bind中没有参数,而组件中的props需要声明对象的每个属性

<body>
	<div id="app">
  		<child v-bind="todo"></child>
	</div>
	<script>
		Vue.component('child', {
			props: ['text','isComplete'],
			template: '<span >{{ text }}  {{isComplete}}</span>'
		})
		new Vue({
			el: '#app',
		  	data: {
			    todo: {
			      text: 'Learn Vue',
			      isComplete: false
			    }
		  	}
		})
	</script>
</body>

2.方法二:使用带参数的v-bind写法

v-bind后跟随参数todo,组件中的props需要声明该参数,组件变可以通过todo来访问对象的属性
 
<body>	
	<div id="app">  		
		<child v-bind:todo = "todo" ></child>	
	</div>	
	<script>		
		Vue.component('child', {  			
			props: ['todo'],  			
			template: '<span >{{ todo.text }}{{ todo.isComplete }}</span>'		
		})		
		new Vue({		    
			el: '#app',		  	
			data: {			    
				todo: {			      
					text: 'Learn Vue',			      
					isComplete: false			    
				}		  	
			}		
		)	
	</script>
</body>
prop验证
<body>
	<div id="app">
  		<my-child
  			:num = "100"
  			:msg = "'sdf'"
  			:object = "{a:'a'}"
  			:cust = "100"
  		></my-child>
	</div>
	<script>
		Vue.component('my-child',{
			props:{
				num: Number,
				propB: [String,Number],
				msg:{
					type:String,
					required:true
				},
				num1:{
					type:Number,
					default: 1000
				},
				object:{
					type:Object,
					default:function(){
						return { message:'hello' }
					}
				},
				cust:{
					validator:function (value){
						return value > 10
					}
				}
			},
			template:`<div>
				<p>{{ num }}</p>
			        <p>{{ msg }}</p>
				<p>{{ num1 }}</p>
				<p>{{ object }}</p>
				<p>{{ cust }}</p>
			`
		})
		new Vue({
			el:'#app'
		})
	</script>
</body>
替换合并己有的特性
class  和  style   会合并,class 和 style 特性会稍微智能一些,即两边的值会被合并起来,
<body>
	<div id="app">
  		<bootstrap-date-input
			data-date-picker="activated"
			class="date-picker-theme-dark"
		></bootstrap-date-input>
	</div>
	<script>
		Vue.component('bootstrap-date-input',{
			template:'<input type="date" class="form-control">',
			props:['']
		})
		new Vue({
			el:'#app'
		})
	</script>
</body>
结果:

禁用特性继承 (无案例)

自定义事件

自定义事件的主要作用是,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。 也就是相互通知

这里推荐 :https://blog.csdn.net/hayre/article/details/60572435   讲的很明白。

<body>
	<div id="counter-event-example">
		<p>{{ total }}</p>
		<button-counter v-on:increment="incrementTotal"></button-counter>
		<button-counter v-on:increment="incrementTotal"></button-counter>
	</div>
	<script>
		Vue.component('button-counter', {
			template: '<button v-on:click="increment">{{ counter }}</button>',
		  	data: function () {
			    return {
			    	counter: 0
			    }
		  	},
		  	methods: {
			    increment: function () {
				    this.counter += 1
				    this.$emit('increment')
			    }
		  	}
		})
		new Vue({
			el: '#counter-event-example',
			data: {
				total: 0
			},
		  	methods: {
			    incrementTotal: function () {
			      this.total += 1
			    }
		  	}
		})
	</script>
</body>

自定义组件的v-model     

转载自:https://www.cnblogs.com/bldf/p/6645225.html

<input v-model="something">

v-model指令其实是下面的语法糖包装而成:

<input
  :value="something"
  @:input="something = $event.target.value">

在一个组件上使用 v-model 时,会简化为:

<custom-input
  :value="something"
  @input="value => { something = value }">
</custom-input>

因此,对于一个带有 v-model 的组件,它应该如下:

  • 接收一个 value prop
  • 触发 input 事件,并传入新值

利用 $emit 触发 input 事件:

this.$emit('input', value);

组件1:

复制代码
Vue.component('my-component', {
  template: `<div>
  <input type="text" :value="currentValue" @input="handleInput"/>
  </div>`,
  data: function () {
    return {
      currentValue: this.value 
    }
  },
  props: ['value'], //接收一个 value prop
  methods: {
    handleInput(event) {
      var value = event.target.value;
      this.$emit('input', value); //触发 input 事件,并传入新值
    }
  }
});
复制代码
currentValue: this.value 
上面是将prop属性绑定到data里,以便修改 prop 数据(Vue不允许直接修改prop属性的值)#查看原理#

组件2:

复制代码
Vue.component("my-counter", {
  template: `<div>
  <h1>{{value}}</h1>
  <button @click="plus">+</button>
  <button @click="minu">-</button>
  </div>`,
  props: {
    value: Number //接收一个 value prop
  },
  data: function() {
    return {
      val: this.value
    }
  },
  methods: {
    plus() {
      this.val = this.val + 1
      this.$emit('input', this.val) //触发 input 事件,并传入新值
    },
    minu() {
      if(this.val>0){
        this.val = this.val-1
        this.$emit('input', this.val) //触发 input 事件,并传入新值
      }
    }
  }
});
复制代码
案例:
 
 
<body>	
	<div id="app">     	
		<!-- <price-input v-model="price"></price-input> -->
    	<!-- 手动实现了v-model双向绑定 -->    	
    	<!-- 3、父组件的input事件被触发,将传来的值赋给父组件的变量price -->    	
    	<!-- 4、父组件value的值绑定到price -->      	
    	<price-input :value="price" @input="onInput"></price-input>      	
    	<p>{{price}}</p> 	
	</div>	
	<script>		
		Vue.component('price-input', {		    
			// 5、将父组件的value值通过props传递给子组件		    
			// 1、当有数据输入时触发了该组件的input事件		    
			template: '<input :value="value" @input="updateVal($event.target.value)" type="text">',		    
			props: ["value"], 		    
			methods: {		         
				updateVal: function(val) {		            
					// 2、手动触发父组件的input事件并将值传给父组件		            
					this.$emit('input', val);  		         
				}		    
			}		
		});		
		var app = new Vue({		     
			el: '#app',		     
			data: {		         
				rice: ''		     
			},		     
			methods: {		          
				onInput: function(val) {		               
					this.price = val;		          
				}		      
			}		
		});	</script>
</body>

将原生事件绑定到组件上,使用native修饰符

我们引入一个原生标签(div、li、p......)的概念,那么原生事件(存在于标准当中的如'click', 'mouseover')应该绑定到原生标签上。自定义组件上应该绑定自定义事件。
如果我们想给自定义组件标签(注意是标签,不是内部元素)绑定原生事件(使原生事件生效于组件template的root element上)怎么办,加.native修饰符。

<body>
	<div id="app">
		<my-ding @click.native = "doThis"></my-ding>
		<div @click = 'doThis'>你好吗???</div>
	</div>
	<script>
		Vue.component('my-ding',{
			template:'<div>开心每一天</div>'
		});
		new Vue({
			el:'#app',
			methods:{
				doThis:function(){
					console.log('我是丁红丽')
				}
			}
		})
	</script>
</body>

.sync修饰符

<body>
	<div id="app">
  		<div>{{bar}}</div>
  		<my-comp :foo.sync="bar"></my-comp>
  		<!-- <my-comp :foo="bar" @update:foo="val => bar = val"></my-comp> -->
	</div>
	<script>
	 	Vue.component('my-comp', {
		    template: '<div @click="increment">点我+1</div>',
		    data: function() {
		      return {copyFoo: this.foo}
		    },
		    props: ['foo'],
		    methods: {
		      increment: function() {
		        this.$emit('update:foo', ++this.copyFoo);
		      }
		    }
	  	});
	  	new Vue({
		    el: '#app',
		    data: {bar: 0}
	  	});
	</script>
</body>




 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值