vue基础篇---vue组件
vue模块第一篇,因为公司马上要用到这vue开发。早就想好好看看vue了。只有实际工作中用到才会进步最快。vue其他的简单指令就不多讲了,没啥意思,网上一大堆。看w3c就ok。
组件这个我个人感觉坑蛮多的,所以特地记录一下。
简单总结一下:
父组件给子组件传值:
父向子可以传属性,方法,和父对象的本身,很简单,需要2步即可。
1,父组件调用子组件的时候 绑定动态属性 <v-header :title="title" :homemsg='msg' :run="run" :home="this"></v-header> 分别是属性,方法,父本身
2,在子组件里面通过 props接收父组件传过来的数据 props:['title','homemsg','run','home'] js调用的时候就this.title即可 页面直接{{title}}即可
父组件主动获取子组件的数据和方法
1.调用子组件的时候定义一个ref <v-header ref="header"></v-header>
2.在父组件里面通过 this.$refs.header.属性 this.$refs.header.方法
子组件主动获取父组件的数据和方法
this.$parent.数据
this.$parent.方法
非父子组件传值 (利用广播实现的,麻烦,在项目中一般用vuex实现)
1、新建一个js文件 然后引入vue 实例化vue 最后暴露这个实例VueEmit
2、在要广播的地方引入刚才定义的实例
3、通过 VueEmit.$emit('名称','数据')
4、在接收收数据的地方通过 $om接收广播的数据
VueEmit.$on('名称',function(){
})
全局组件
/*全局組件*/ Vue.component("to-do",{ template:"<li>111</li>" })
这样就声明了一个全局组件,然后你在html中直接引用 <to-do></to-do> 这个你自定义的标签就ok。注意:一定要在你声明的el中引用。
问题1:全局组件如何引用变量呢?
<!--html中引用的全局組件 content这个属性是你自定义的 --> <to-do v-for="(item,index) in list" :key="index" :content="item"></to-do> /*全局組件*/ Vue.component("to-do",{ props:["content"], // props這個属性来声明接收变量 template:"<li>{{content}}</li>" })
问题2:子组件和父组件之间如何通信呢?
这里特别强调说明一下,每一个vue实例就是一个组件,每个组件都是vue实例。这里要清楚!!!
也就是说,你自定义一个组件,组件里面也可以也date,methods这类的属性。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/vue/2.4.2/vue.min.js"></script> </head> <body> <div id="app"> <input type="text" v-model="v1"> <button @click="add">提交</button> <!--html中引用的全局組件 content index 这2个属性是你自定义的 @del 是监听del这个自定义的事件,就执行hadleDelete这个方法--> <to-do v-for="(item,index) in list" :key="index" :content="item" :index="index" @del="hadleDelete"></to-do> </div> </body> <script type="text/javascript"> /*全局組件*/ Vue.component("to-do",{ props:["content","index"], // props這個属性来声明接收变量 template:"<li @click='click_li'>{{content}}</li>", methods:{ click_li:function(){ this.$emit("del",this.index) //意思是点击子组件的li标签的话,会向外发布一条del事件。后面携带的值 } } }) new Vue({ el: "#app", data: { v1: "", list: [] }, methods: { add: function () { this.list.push(this.v1); this.v1 = ""; }, hadleDelete:function(index){ this.list.splice(index,1) //执行这个方法,告诉父组件 把list里面的数据删掉 } } }) </script> </html>
要清楚,父组件何如向子组件通信。子组件如何向父组件通信。
局部组件
<script type="text/javascript"> /*全局組件*/ Vue.component("to-do",{ template:"<li>111</li>" }) /*局部組件*/ var xixi={ template:"<li>xxxxx</li>" } new Vue({ el: "#app", components:{ xixi:xixi }, data: { v1: "", list: [] }, methods: { add: function () { this.list.push(this.v1); this.v1 = ""; } } }) </script>
他和全局组件的区别在于,全局可以直接引用,他不可以,如果想用,必须在自己new Vue({})中声明才可以。然后你在html中直接引用 <xixi></xixi> 这个你自定义的标签就ok
在子组件中如何引用父组件的方法
<div id="vue_det"> <child content="Dell" @click.native="xx"></child> <child content="Mark"></child> </div>
xx方法写在父组件的methods中。引用的时候用.native即可。 如果子组件本身有方法。会先执行子组件的方法,然后再执行父组件的方法。
卡槽
卡槽的作用:平常我们父组件给子组件传值,我们都用自定义属性的方式,然后在子组件中接收,但是,如果我们从父组件中传的值是html这种呢?难道还要这样写么?岂不是很蛋疼?虽然能做到,但是不够美观,而且还得转义。所以,我们需要卡槽这个特性。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>卡槽</title> <script src="https://cdn.bootcss.com/vue/2.4.2/vue.min.js"></script> </head> <body> <div id="vue_det"> <child> <div slot="header">header</div> <!--header,footer是自定义的名字。方便子组件引用--> <div slot="footer">footer</div> </child> </div> <script type="text/javascript"> Vue.component('child',{ template:` <div> <slot name="header"></slot> <h1>主题</h1> <slot name="footer"></slot> </div> ` }) var vm = new Vue({ el: '#vue_det' }) </script> </body> </html>
利用vuex实现不同的组件之间传递数据
cnpm install vuex --save 安装
在项目中src下创建一个专门的文件夹存放vuex的store
src/store/index.js
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) //使用vuex插件 export default new Vuex.Store({ //创建仓库 state :{
city:'北京'
},
actions:{
changeCity(ctx,city){ // ctx 是上下文环境,必须调用commit来实现改变state中的值
ctx.commit('changeCity',city)
}
} mutations:{
changeCity(state,city){
state.city=city
}
} })
在main.js中引入
import store from './store' new Vue({ el: '#app', router, store, /把store加进根元素 components: { App }, template: '<App/>' })
然后可以在其他组件中引用
{{this.$store.state.city}}
如何改变仓库的值呢?
第一种方法:
在点击事件中添加这样的一句话 , 意思是触发changeCity事件,将city带过去 ,changeCity这个方法再vuex中写
this.$store.dispatch('changeCity',city)
第二种方法: 直接省略掉actions了,直接调用commit方法也是可以的。
this.$store.commit('changeCity',city)
循环递归组件
<template> <div> <div class="item" v-for="(item, index) of list" :key="index" > <div class="item-title border-bottom"> <span class="item-title-icon"></span> {{item.title}} </div> <div v-if="item.children" class="item-chilren"> <detail-list :list="item.children"></detail-list> </div> </div> </div> </template> <script> export default { name: 'DetailList', props: { list: Array } } </script>