Vue 组件化

全局组件和局部组件

全局组件写法

// MyComponent.vue
<template>
    <div>{{ name }}</div>
</template>
<script>
export default {
    data() {
        return {
            name: 'crj'
        };
    }
}
</script>
import Vue from 'vue'
import App from './App.vue'
import MyComponent from '@/components/MyComponent.vue'; // 导入自己写的组件文件
Vue.use(MyComponent); // 自定义全局组件的时候需要Vue.use();
Vue.component('my-component', MyComponent); //初始化组件
new Vue({
  render: h => h(App)
}).$mount('#app')
// 使用
<template>
    <div class="contentViews">
        <my-component/>
    </div>
</template>

局部组件写法

<template>
    <div class="contentViews">
        <childZJ/>
    </div>
</template>
<script>
import childZJ from "./childZJ.vue"
export default {
    components: {
        childZJ
    }
}
</script>

父组件 => 子组件

属性 props

父组件:parentZJ

<template>
    <div class="contentViews">
        <childZJ msg="crj" />
    </div>
</template>
<script>
import childZJ from "./childZJ.vue"
export default {
    components: {
        childZJ
    }
}
</script>

子组件:childZJ

<template>
    <div>
        {{ msg }}
    </div>
</template>
<script>
export default {
    props: {
        msg: {
            type: String,
            default: "c",
            required: true
        }
    }
    or
    props: ['msg']
}
</script>
引用 refs、子元素 children

父组件:parentZJ

<template>
    <div class="contentViews">
        <!--用ref给子组件起个名字-->
        <childZJ ref="childZJRef" />
    </div>
</template>
<script>
import childZJ from "./childZJ.vue"
export default {
    components: {
        childZJ
    },
    mounted() {
        // 取得子组件的属性,childZJRef是上边ref起的名字,crj是子组件的属性,方法同理。
        this.$refs.childZJRef.crj = 'meng'
        this.$children[0].crj = 'chen'
    }
}
</script>

子组件:childZJ

<template>
    <div>
        {{ crj }}
    </div>
</template>
<script>
export default {
    data() {
        return {
            crj: 'cheng'
        };
    }
}
</script>
自定义组件在使用 v-model

父组件:parentZJ

<template>
    <div class="contentViews">
        <!-- 允许一个自定义组件在使用 v-model 时定制 prop 和 event。
             默认情况下,一个组件上的 v-model 会把 value 用作 prop 且把 input 用作 event,
             但是一些输入类型比如单选框和复选框按钮可能想使用 value prop 来达到不同的目的。
             使用 model 选项可以回避这些情况产生的冲突。 
        -->
        <childZJ v-model="crj"/>
    </div>
</template>
<script>
import childZJ from "./childZJ.vue"
export default {
    components: {
        childZJ
    },
    data() {
        return {
            crj: 'cheng'
        };
    }
}
</script>

子组件:childZJ

<template>
    <div>
        <el-input @input="handleChange" :value="currentValue" />
    </div>
</template>
<script>
export default {
    props: ['value'],
    data() {
        return {
            currentValue: this.value
        }
    },
    watch: {
        value: {
            handler(newVal) {
                this.currentValue = newVal;
            },
            // 代表在wacth里声明了a这个方法之后立即先去执行handler方法,如果设置了false,那么效果和上边例子一样
            immediate: true,
            deep: true
        }
    },
    methods: {
        handleChange(value) {
            this.currentValue = value;
            this.$emit('input', this.currentValue)
        }
    }
}
</script>

子组件 => 父组件:自定义事件

父组件:parentZJ

<template>
    <div class="contentViews">
        <childZJ ref="childZJRef" @add="cartAdd"/>
        <!--父组件中通过监测add事件执行一个方法cartAdd,然后取到子组件中传递过来的值-->
    </div>
</template>
<script>
import childZJ from "./childZJ.vue"
export default {
    components: {
        childZJ
    },
    methods: {
        cartAdd(e, crj) {
            console.log(e, crj);
        }
    }
}
</script>

子组件:childZJ

<template>
    <div>
        <div @click="$emit('add', $event, crj)">点击</div>
        <div @click="handleAdd($event)">点击</div>
    </div>
</template>
<script>
export default {
    data() {
        return {
            crj: 'cheng'
        };
    },
    methods: {
        handleAdd(e) {
            // 通过按钮的点击事件触发方法,然后用$emit触发一个add的自定义方法,传递this.crj数据。
            this.$emit('add', e, this.crj)
        }
    }
}
</script>

兄弟组件:通过共同祖辈组件

父组件:parentZJ

<template>
    <div class="contentViews">
        <childZJ/>
        <childZJTwo/>
    </div>
</template>
<script>
import childZJ from "./childZJ.vue"
import childZJTwo from "./childZJTwo.vue"
export default {
    components: {
        childZJ,
        childZJTwo
    }
}
</script>

子组件一:childZJ

<template>
    <div>
        <div @click="handleAdd">点击</div>
    </div>
</template>
<script>
export default {
    data() {
        return {
            crj: 'cheng'
        };
    },
    methods: {
        handleAdd() {
           this.$parent.$emit('add', this.crj)
        }
    }
}
</script>

子组件二:childZJTwo

<template>
    <div>{{ name }}</div>
</template>
<script>
export default {
    data() {
        return {
            name: ''
        };
    },
    created() {
        this.$parent.$on('add', (crj) => {
            this.name = crj;
        })
    }
}
</script>

祖先和后代之间

父组件:parentZJ

<template>
    <div>
        <h3>当前主题色为{{ theme }}</h3>
        <button @click="changeTheme('blue')">蓝色</button>
        <button @click="changeTheme('green')">绿色</button>
        <button @click="changeTheme('red')">红色</button>
        <hr>
        <childZJ></childZJ>
    </div>
</template>
<script>
import childZJ from './childZJ.vue'
export default {
    components: {
        childZJ
    },
    provide() {
        return {
            theme: this.theme,
            changeTheme: this.changeTheme
        }
    },
    data() {
        return {
            theme: 'blue'
        }
    },
    methods: {
        changeTheme(theme) {
            this.theme = theme
        }
    }
}
</script>

子组件:childZJ

<template>
    <div>
        <childZJTwo />
    </div>
</template>
<script>
import childZJTwo from './childZJTwo.vue'
export default {
    components: {
        childZJTwo
    }
}
</script>

孙组件:childZJTwo

<template>
    <div>
      <h3>我是子组件</h3>
      <p>当前主题色为:{{theme}}</p>
      <button @click="changeTheme1('blue')">蓝色</button>
      <button @click="changeTheme1('green')">绿色</button>
      <button @click="changeTheme1('red')">红色</button>
    </div>
  </template>
  <script>
  export default {
    inject: ['theme', 'changeTheme'],
    mounted() {
      console.log(this.theme) // blue
    },
    methods: {
      changeTheme1(theme) {
        this.changeTheme(theme)
      }
    }
  }
  </script>

任意两个组件之间:事件总线 或 vuex

main.js

import Vue from 'vue'
import App from './App.vue'
//关闭Vue的生产提示
Vue.config.productionTip = false
//创建vm
new Vue({
	el:'#app',
	render: h => h(App),
	// beforeCreate中模板未解析,且this是vm
	beforeCreate(){
		Vue.prototype.$bus = this	//安装全局事件总线
	}
})

TestA.vue:

<template>
  <div>
    <h2>姓名:{{name}}</h2>
    <button @click="sendName">给TestB组件传递数据</button>
  </div>
</template>

<script>
    export default {
        name:'TestA',
        data(){
          return{
            name:'路飞'
          }
        },
        methods:{
          // 触发事件,事件名不能重复
          sendName(){
            this.$bus.$emit('lufei', this.name);
          }
        },
    }
</script>

TetsB.vue:

<template>
  <div>
    <h2>籍贯:{{native}}</h2>
    <h2>家庭住址:{{adress}}</h2>
  </div>
</template>

<script>
    export default {
        name:'TestB',
        data(){
          return{
            native:'东海',
            adress:'东海风车村',
          }
        },
        mounted(){
          // 绑定事件
          this.$bus.$on('lufei', (data)=>{
            console.log('我是TestB组件,收到了数据', data);
          })
        },
        // 销毁对应自定义事件
        beforeDestroy(){
          this.$bus.$off('lufei')
        }
    }
</script>
方法二

自定义:eventBus.js

// 模拟vuex
import Vue from 'vue'
const eventBus = new Vue()
export default eventBus

或者
// Bus :事件派发、监听和回调管理
class Bus {
    constructor() {
        this.callbacks = {}
    }
    $on(name,fn) {
        this.callbacks[name] = this.callbacks[name] || []
        this.callbacks[name].push(fn)
    }
    $emit(name,args) {
        if (this.callbacks[name]) {
            this.callbacks[name].forEach(cb => cb(args));
        }
    }
}
export default Bus

main.js

import EventBus from './components/eventBus.js'
Vue.prototype.$bus = new EventBus()

TestA.vue

this.$bus.$on('foot', this.handle)
methods: {
    handle(val) {
        console.log(val);
    }
}

TetsB.vue

this.$bus.$emit('foot', '11233')
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端全栈分享站

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值