vue学习篇--04单文件组件,vue脚手架工具,父子组件传值,非父子组件传值

本文深入探讨Vue.js中的组件化开发,包括组件的创建、维护及通信方式,如父子组件间的数据传递与事件触发,以及非父子组件间的通信策略。通过具体示例,解析如何利用Vue提升代码复用性和可维护性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

组件

正常情况下 项目页面有很多部分组成,逻辑非常多,维护相对来说较困难
组件系统是vue的另一个重要概念,可以使用小型,独立和通常可复用的组件构建大型应用,提高代码的可维护性和复用性

组件传值:v-bind 内部用props接收,组件内部使用$emit触发外部绑定事件并传值

    css:
        .todo-item{width:100px;height:100px;border:1px solid #ccc}
        .todo-item p{color:cyan}
    1. html:
        <div id='#app'>
            <todo-item></todo-item>
        </div>
    2. js:
        <script src='vue.js'></script>
        <script>
            Vue.component('todo-item',{
                template:'<div class='todo-item'><p>{{message}}</p><button @click='btnAction'>点击</button></div>',
                data:function(){
                    return {
                        message:'hello',
                    }
                },
                methods:{
                    btnAction:function(){
                        alert(this.message)
                    }
                }
            })
        </script>

单文件组件

以上的组件创建可读性不高,维护起来比较费劲,创建.vue文件,将html css js分为三个模块

    test.vue:
        <template>
            <div class='todo-item'>
                <p>{{message}}</p><button @click='btnAction'>点击</button>
            </div>
        </template>
        <script>
            export default {
                data:function(){
                    return {
                        message:'hello',
                    }
                },
                methods:{
                    btnAction:function(){
                        alert(this.message)
                    }
                }
            }
        </script>
        <style>
            .todo-item{width:100px;height:100px;border:1px solid #ccc}
            .todo-item p{color:cyan}
        </style>
在这只需要将这个.vue文件引入,然后再声明这个组件即可:Vue.component('todo-item')
但是浏览器无法识别.vue格式的文件(html,css,js,图片),无法直接引入,
所以需要使用(官网)vue loader这个工具对.vue进行编译 成.js文件

vue cli3: vue脚手架工具

安装:npm install @vue/cli -g
创建项目:vue create 项目名称
选择哪种工具:default(ababel,eslint)  Manually select features自定义选择  上下箭头选择 enter选择
    空格选中:Babel(将es6语法编译成浏览器可以正常编译的语法) Router Vuex css预编译工具
            Linter(语法检查)  单元测试 端对端测试
    enter => 
        将以上的工具配置到独立文件当中还是配置在package.json文件中,一般选择配置在package.json
    enter => 
        是否将以上配置保存为将来可以用的备用预配置 => no,选择yes,需要给这个配置设置一个名字
    enter => 进行安装配置
进入项目:cd 项目名称
运行项目:npm run serve
main.js文件:
是vue脚手架工具创建好项目的入口文件,创建vue实例对象 管理html页面中id为app的div结构,
vue实例的dom结构由组件App提供
解读main.js:
        <!-- 等价于 var Vue = require('vue') 这是Common.js规范模块开发,下面是ES6 -->
        import Vue from 'vue'  
        import App from './App.vue'
        <!-- 设置生产模式的提示为false,即为开发模式,无压缩,包含警告之类的,设置为true则为生产模式,压缩版,删除警告 -->
        Vue.config.productionTip = false

        new Vue({
        render: h => h(App),
        }).$mount('#app')

        <!-- 上面的new Vue部分等价于下面 -->
        const vm = new Vue({
            <!-- 引入App,然后component声明局部组件App,然后template可以使用这个组件 -->
            <!-- template:'</App>',
            component:{
                App:App
            }, -->
            <!-- render函数是替换template的方式:等价于上面的template和component
                h参数是一个形参,相当于createElement方法,能够读出App中template中的dom结构
                然后将读取出的dom返回
            -->
            render:function(createElement){
                let dom = createElement(App)
                return dom
            }
        })
        <!-- 以上在生命周期中的顺序会走到判断是否有el,没有,要都明天vm.$mount('#app') 
            动态将vm实例挂载到dom结构上,再执行render()
        -->
        vm.$mount('#app')
脚手架创建的单文件组件
data属性对应的是函数与this指向
        <template>
            <!-- template声明组件结构,只能有一个根标签:由一个div包含所有标签, -->
            <div id="app">
                <h2>{{message}</h2>
                <button @click='btnAction'>点击</button>
            </div>
        </template>
        <script>
            <!-- script提供组件的数据和逻辑处理 -->
            <!-- export default{}等价于commonjs规范中module.exports={} -->
            export defaule {
                <!-- data是组件的属性,是vue实例的data属性一样,但是配置项中对应的是函数而不是对象-->
                data:function(){
                    return {
                        message:'hello vue'
                    }
                },
                methods:{
                    btnAction(){
                        <!-- this指向组件对象 -->
                        alert(this.message)
                    }
                }
            }
        </script>
        <style>
            #app{background:cyan}
            #app h2{color:red}
        </style>
vscode中vue工具:Vetur,快捷方式快速创建vue文件:scf+enter
声明全局组件
        1. Wrap.vue: 
            <template>
                <div class='wrap'>
                    <h2>Wrap组件</h2>
                </div>
            </template>
            <script>
                export defaule {
                    data:function(){
                        return {
                            message:'hello vue'
                        }
                    },
                    methods:{
                        btnAction(){
                            <!-- this指向组件对象 -->
                            alert(this.message)
                        }
                    }
                }
            </script>
            <style>
                .wrap{
                    color:bule
                }
            </style>
        2. 在main.js中引入Wrap并且声明全局组件
            import Wrap from './Wrap.vue'
            Vue.component('wrap',Wrap)
        3. App.vue: 使用Wrap
            <template>
                <!-- 单标签,也可以使用双标签 -->
                <wrap />
            </template>
        
        4. wrap中的h2样式会被App中的样式同化,可以给style标签添加一个属性 scoped,表示样式仅作用于当前组件
            <style scoped>
            </style>
声明局部组件
     1. App.vue:在App组件中使用wrap组件,可以将wrap声明局部组件
  
         <script>
             import Wrap from './Wrap.vue'
             export default {
                 ...,
                 <!-- 声明局部组件 -->
                 componnets:{
                     wrap:Wrap
                 }
             }
         </script>
单文件组件方式进行父子组件通信:
父=>子:v-bind:值名称,子组件中用props接受这个值名称,然后可以使用这个值显示在子组件上
子=>父:子组件使用$emit触发事件,并传值,这个事件需要在父组件中 使用的子组件标签中接收=> 
    父组件中的子组件标签:@事件名称='事件处理函数',然后父组件methods执行这个事件处理函数,可以接收子组件传来的值
  1. App.vue: 先在App组件中引入父组件
        1. html:
            <div id='app'>
                <Father>
            </div>
        2. js:
            import Father from './Father'
            export default {
                components:{
                    Father
                }
            }
  1. Father.vue:创建父组件
       1. html:
           <div class='father'>
               <p>父组件</p>
               <p>接受到子组件的信息:{{Sonmessage}}</p>
               <input type="text" v-model="message">
               <button @click="FatherSend">发送</button>
               <Son v-bind:Fathermessage='Fathermessage' @send='hanldeSend' />
           </div>
       2. js:
           import Son from './Son'
           export default {
               components:{
                   Son
               },
               data(){
                   message:'',
                   Fathermessage:''
                   Sonmessage:''
               },
               methods:{
                   FatherSend(){
                       this.Fathermessage = this.message
                   },
                   hanldeSend(Sonmessage){
                       this.Sonmessage = Sonmessage
                   }
               }
           }
       3. css:
           .father{width:300px;height:300px;background:cyan}
  1. Son.vue: 创建子组件
        1. html:
            <div class='son'>
                <p>子组件</p>
                <p>接受到父组件的信息:{{Fathermessage}}</p>
                <input type='text' v-model='Sonmessage' />
                <button @click='sendAction'>发送</button>
            </div>
        2. js:
            import Son from './Son'
            export default {
                <!-- 接收父组件传入的属性,v-bind绑定的是什么值,这里就接受什么值 -->
                props:['Fathermessage'],
                data(){
                    Sonmessage:''
                },
                methods:{
                    sendAction(){
                        this.$emit('send',this.Sonmessage)
                    }
                }
            }
        3. css:
            .son{background:blue}
非父子组件传值:

创建一个空实例 作为非关系组件中的中转:采用$on $emit => 多对多的关系,可以有多个监听 多个触发
后期学习vuex,可以使用vuex来进行数据状态管理。

    1. pubsub.js: 创建空实例
    
        import Vue from 'vue'
        const pubsub = new Vue()
        <!-- 
            先监听后触发!!!
            监听事件 等价于标签中的@send绑定事件:@send='事件函数' 
            参数一:监听事件名称,参数二:监听到事件的回调函数
        -->
        pubsub.$on('send',()=>{
            console.log('监听事件执行')
        })
        <!-- 触发事件:只有$emit触发事件了,才可以执行监听中的事件函数 -->
        pubsub.$emit('send')

        export default pubsub

    2. main.js:引入pubsub.js
        import './pubsub'

    3. One.vue: One组件传值给Two组件:在one组件中触发事件,执行pubsub.$emit(),传输数据
        1. html:
            <div class='One'>
                <h1>One组件</h1>
                <input type='text' v-model='value' />
                <button @click='btnAction'>发送</button>
            </div>
        2. js:
            import pubsub from './pubsub'
            export defualt {
                data(){
                    return {
                        value:''
                    }
                },
                methods:{
                    btnAction(){
                        pubsub.$emit('send',this.value)
                    }
                }
            }
        3. css:
            .One{background:cyan}

    4. Two.vue: One组件传值给Two组件:在two组件中监听事件,,执行pubsub.$on(),接收数据
        1. html:
            <div class='Two'>
                <h1>Two组件</h1>
                <p>接收到One组件传来的数据:{{OneDate}}</p>
            </div>
        2. js:
            import pubsub from './pubsub'
            export default {
                data(){
                    return {
                        OneDate:''
                    }
                },
                create(){
                    <!-- 这里的回调函数必须使用箭头函数,因为要使用this,如果不使用箭头函数,this将指向pubsub -->
                    pubsub.$on('send',(value)=>{
                        this.OneData = value
                    })
                }
            }
        3. css:
            .Two{background:red}

    5. App.vue: 声明两个局部组件
        1. html:
            <One />
            <hr />
            <Two />
        2. js:
            import One from './One'
            import Two from './Two'
            export default {
                components:{
                    One,
                    Two
                }
            }

为什么 组件中 data属性对应的是函数,而实例中的data是对象?

原因是:组件是可以复用的,每次调用组件都是获取一个新的data属性,如果data是一个对象,在复用时所有组件都会共用一个对象,会干扰其他组件的data。data是函数,在被复用这个组件时,不会干扰到这自身组件中的data

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

CCC1115

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

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

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

打赏作者

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

抵扣说明:

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

余额充值