精华内容
下载资源
问答
  • vue组件化开发
    2022-02-03 23:22:45

    vue组件化开发

    在vue中开发,都是用的组件化的思想开发的,一般在都会在搭建项目的时候,都会先建立组件的模板,把架子搭起来。也就是在组件中定义好<template>视图层,<script>逻辑层,<style>css样式层。

    一般在项目src中创建一个components文件夹存放我们自定义的组件,在需要的页面中导入并注册后,通过标签的形式使用。

    1.第一步:在页面中引入子组件,(假设在components文件下有一个myHeader.vue组件)
    import myHeader from '@/components/myHeader.vue'
    2.第二步:注册子组件
    components:{
    	myHeader
    }
    3.第三步:作为标签使用
    <myHeader />
    或者
    <myHeader></myHeader>
    

    使用组件的好处

    • 组件是可以复用性的
    • 易于维护
    • 封装性,易于使用
    • 大型项目中降低组件之间重复

    组件的分类

    组件分为:全局组件和局部组件
    全局组件

    import Loading from '@/components/myLoading.vue'
    Vue.component('loading',Loading)
    

    局部组件

    <script>
    import Loading from '@/components/myLoading.vue'
    export default {
    	data() {
    		return {}
    	},
    	components:{
    		Loading,
    	}	
    }
    </script>
    

    组件之间的通讯方式

    父传子

    父组件:<list :my-list="list"></list>
    // props接收过来的数据和data类似 可以直接像data一样使用
    # 第一种方法
    父组件给子组件绑定一个属性,子组件通过props来接收数据
    子组件:
    props:["myList"]	//利用数组接收
    props:{			//利用对象接收
        list:Array, //对象接收的简写方式
        list:{		
            type:Array,	
            default:()=>{
                return []
            },
            required:true //定义该属性是否必须传递
        }
    }
    # 第二种方法
    使用provide/inject
    provide vue官方建议使用在高阶组件中 provide提供的数组 在它的任意后代组件中都可以使用 inject接收 可以使用数组的方法接收数据
    # 第三种方法
    使用$parent
    子组件中可以通过this.$parent找到父组件 从而找到父组件的所有数据和方法
    # 第四种方法
    使用vuex
    

    总结:
    1.对于第一种方法:
    在vue2中: 引用数据类型(数组、对象)的默认值需要通过一个函数返回才能使用,默认值当属性值为undefined或者不传属性才会生效
    2.子组件接受父组件的值分为–引用类型和普通类型两种
    普通类型:string,number,boolean,null
    引用类型:array(数组),object(对象) 子组件不能自行修改

    prop

    所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样是为了防止子组件意外修改父组件的值,从而造成文档数据流混乱。

    在组件中修改 prop 传递过来的数据 Vue 会发出警告,所以有两种常见的用法去修改 prop 传递过来的值

    export default {
        props:["msg"],
        data() {
            return {
            	// 本地data中定义属性,并将 prop 作为初始值(第一种)
                message:this.msg
            }
        },
        computed:{
        	// 使用computed 将prop 的值进行处理(第二种)
            message() {
                return this.msg + '哈哈哈'
            }
        }
    };
    
    prop验证
    props: {
        // 基础的类型检查 (null 匹配任何类型)
        propA: Number,
        // 多个可能的类型
        propB: [String, Number],
        propC: {
            type: String,
            required: true,	// 必填的字符串
            default: 'uu盘'	// 默认值
        },
        // 自定义验证函数
        propD: {
            validator: function (value) {
                // 这个值必须匹配下列字符串中的一个
                return ['success', 'warning', 'danger'].indexOf(value) !== -1
            }
        }
    }
    

    子传父

    # 第一种方法
    父组件给子组件绑定一个自定义事件,子组件通过this.$emit('自定义事件名',参数)发送数据
    子组件:
    <button @click="add"></button>
    <script>
        data(){
        return {},
        methods:{
            add(){
                // 参数一:父组件定义的方法[事件名称]
                // 参数二:可选,子组件向父组件传递的数据,可以是多个
                this.$emit("add",this.name)
            }
        }
    }
    </script>
    父组件:
    <list @add="add"></list>
    <script>
        data(){
        return{},
        methods:{
            add(i){
                console.log(i)	// 子组件向父组件传递的数据
    		}
        }
    }
    </script>
    # 第二种方法
    使用this.$children获取到组件的所有子组件
    # 第三种方法
    使用vuex
    

    总结:
    对于第一种方法:
    1.子组件中需要以某种方式例如点击事件的方法来触发一个自定义事件
    2.将需要传的值作为$emit的第二个参数,该值将作为实参传给响应自定义事件的方法
    3.在父组件上绑定子组件$emit自定义的方法

    兄弟之间

    # 首先在main.js中给全局挂在一个bus对象
    import Vue from 'vue'
    import App from './App.vue'
    import router from './router'
    Vue.config.productionTip = false
    Vue.prototype.$bus = new Vue()
    new Vue({
        router,
        render: h => h(App)
    }).$mount('#app')
    
    # 在需要传递数据的组件中
    <template>
        <div @click="sendData">这是组件一</div>
    </template>
    <script>
    export default {
        data() {
            return {
                money: "我又五毛,买不起辣条"
            }
        },
        methods: {
            sendData() {
                // console.log(this);
                this.$bus.$emit('getData', this.money)
            }
        }
    }
    </script>
    // 在需要接收数据的组件中
    <template>
        <div>{{msg}}</div>
    </template>
    <script>
    export default {
        data() {
            return {
                msg: ''
            }
        },
        created() {
            $on监听方法  他的第一个参数是要监听的函数的函数名 第二个是回调函数
            this.$bus.$on('getData', (data) => {
                this.msg = data
            })
            // 关闭监听事件的方法是 this.$bus.$off('事件名')
        }
    }
    </script>
    

    总结:
    通过main.js初始化一个全局的$bus,在发送事件的一方通过this.$bus.$emit(“事件名”,传递的参数信息)发送,在接收事件的一方通过this.$bus.$on("事件名",参数)接收传递的事件

    组件样式穿透

    为了让组件中的样式不影响其他组件的样式,只在当前组件起作用,我们会加上scoped

    <style lang='scss' scoped></style>
    

    有时候我们想让某个样式影响子组件,这时候我们就可以使用操作符

    css中
    <style scoped>
    	>>> .active {}
    </style>
    sass中
    <style lang='scss' scoped>
    	/deep/ .active {}
    </style>
    
    更多相关内容
  • Vue组件化开发

    2021-06-21 10:28:38
    本课程基于ES6来学习Vue的整个API,其中包含Vue基础API、Vue组件化开发、Vue组件通信、官 方脚手架Vue-cli3的使用、Vue-devtools的使用 、element-ui第三 方组件的使用、手把手带你打造自己的表单组件、Vue核心插件...
  • Vue 组件化开发

    千次阅读 2021-12-07 00:21:40
    模块化(组件化)开发 按照功能(或按照复用性)把一个页面拆成各个板块(模块),每一个模块都是一个单独的文件(单独的组件),最后把各个模块(组件)拼在一起即可!! 目的 :方便团队协作开发 实现复用 组件分类 功能型...

     模块化(组件化)开发

    按照功能(或按照复用性)把一个页面拆成各个板块(模块),每一个模块都是一个单独的文件(单独的组件),最后把各个模块(组件)拼在一起即可!!

    目的 :方便团队协作开发 实现复用

    组件分类

    功能型组件「UI组件库中提供的一般都是功能型组件:element/iview/antdv/vant/cube..」

    •     + 一般UI组件库提供的功能组件就够用了
    •     + 偶尔UI组件库中不存在的,才需要自己封装「难点」
    •     + 我们经常会把功能型组件进行二次封装(结合自己项目的业务逻辑)「特殊亮点」

    业务型组件

    •   + 通用业务型组件「好多页面都需要用到的,我们把其封装成为公共的组件」
    •   + 普通组件

    以后开发项目,拿到设计稿的第一件事情:划分组件「按照功能版块划分、本着复用性原则,拆的越细越好(这样才能更好的实现复用)」

    组件的创建及使用

    创建一个 Xxx.vue 就是创建一个vue组件{局部组件、私有组件},组件中包含:结构、样式、功能

     结构:基于template构建        

           + 只能有一个根元素节点(vue2)
         + vue的视图就是基于template语法构建的(各种指令&小胡子...),最后vue会把其编译为真实的DOM插入到页面指定的容器中
          首先基于 vue-template-compiler 插件把template语法编译为虚拟DOM「vnode」
          其次把本次编译出来的vnode和上一次的进行对比,计算出差异化的部分「DOM-DIFF」
          最后把差异化的部分变为真实的DOM放在页面中渲染
     

    样式:基于style来处理

    • + lang="less" 指定使用的CSS预编译语言「需要提前安装对应的loader」
    • + scoped 指定当前编写的样式是私有的,只对当前组件中的结构生效,后期组件合并在一起,保证样式之间不冲突

     功能:通过script处理

        + 导出的这个对象是VueComponent类的实例(也是Vue的实例):对象 -> VueComponent.prototype -> Vue.prototype
        + 在对象中基于各种 options api 「例如:data、methods、computed、watch、filters、生命周期函数...」实现当前组件的功能
           + 在组件中的data不再是一个对象,而是一个“闭包”
           + 各个组件最后会合并在一起渲染,为了保证组件中指定的响应式数据是“私有的”,组件之间数据即使名字相同,也不会相互污染...所以需要基于闭包来管理

    注意;App.vue页面入口相当于首页,写好的组件都导入到这个里面

    <template>
      <div class="box">
        {{ msg }}
      </div>
    </template>
    
    <script>
    export default {
      name: "Test",
      data() {
        return {
          //编写响应式数据
          msg: "你好,世界",
        };
      },
    };
    </script>
    
    <style lang="less" scoped>
    .box {
      font-size: 20px;
      color: red;
    }
    </style>

    私有组件(使用的时候首先进行导入,然后注册,这样视图中就可以调用组件进行渲染了)

    • 需要使用私有组件的时候,需要先导入import Test from "./Test.vue";

    • 然后注册:这样就可以调用组件进行渲染了

    <template>
      <div id="app">
          //3.使用组件:可以使用单闭合或双闭合
          
        <Test></Test>
          <Test>
      </div>
    </template>
    
    
    <script>
    //1、导入组件
    import Test from "./Test.vue";
    export default {
      name: "App",
      components:{
        //2、注册使用的组件
        Test,
      }
    };
    </script>

    创建全局组件

    1. 创建一个局部组件 

    <template>
      <div>{{ msg }}</div>
    </template>
    
    <script>
    export default {
      name: "Vote",
      data() {
        return {
          msg: "今夜阳光明媚",
        };
      },
    };
    </script>
    

    @2 在main.js入口中,导入局部组件Vote,把其注册为全局组件

    import Vote from './Vote.vue';
    Vue.component('Vote', Vote)

    @3 这样在任何组件(视图中),无需基于components注册,直接可以在视图中调用

    <template> <Vote></Vote></template>

    插槽

    调用组件的方式

    调用组件的时候,可以使用:

    双闭合 <Test></Test>

    双闭合的方式可以使用插槽slot

     @1 在封装的组件中,基于 <slot> 标签预留位置
     @2 调用组件的时候,基于双闭合的方式,把要插入到插槽中的内容写在双闭合之间


      单闭合 <Test/>

    组件的名字可以在“kebab-case”和“CamelCase”来切换:官方建议组件名字基于CamelCase命名,渲染的时候基于kebab-case模式使用!

     插槽的作用

    • 让组件具备更高的复用性(或扩展性)
    • 我们封装好一个组件,把核心部分都实现了,但是我们期望用户调用组件的时候,可以自定义一些内容,防止在已经封装好的组件内部:

    插槽分为了默认插槽、具名插槽、作用域插槽

    默认插槽:只需要在调用组件<Test><Test>内插入我们想要的插入的html代码,会默认放到组件源代码的<slot name="default"></slot>插槽中

    组件内部
    slot预留位置  默认name:default
    <slot></slot>
    调用组件的时候
    //只有一个的时候可以不用template包裹
    <Test>
    <div class="top">头部导航</div>
    </Test>

    具名插槽:组件中预设好多插槽位置,为了后期可以区分插入到哪,我们把插槽设置名字

    • 在调用组件<Test><Test>内自己写的代码,我们用template包裹代码,并把v-slot:xxx写在template上,这时就会将xxx里面的代码,包裹到组件源代码的<slot name=”xxx“></slot>的标签中
    • ==组件内部:== <slot name="xxx"> 默认名字是default
    • ==调用组件:==需要把v-slot写在template上
      组件内部
          <slot name="xxx">
          默认名字是default
        调用组件:需要把v-slot写在template上
          <template v-slot:xxx>
             ...
          </template>
          <template>
             ...
          </template>
        v-slot可以简写为#:#xxx
    

       作用域插槽:把组件内部定义的数据,拿到调用组件时候的视图中使用

            组件中data内的数据只能在本模块中使用,如果想让调用组件的插槽也能获取数据,就需要对组件内对的slot做bind绑定数据,调用组件的template标签做#top="AAA",获取数

       ==组件内部==: <slot name="top" :list="list" :msg="msg"></slot>

    • 把组件中的list赋值给list属性,把msg赋值给msg属性,插槽中提供了两个作用域属性:list/msg

    ==调用组件==: <template #top="AAA"></template>

    • 定义一个叫做AAA的变量,来接收插槽中绑定的所有数据(对象格式)
    • 如果插槽名是default则使用v-slot="AAA":default="AAA"获取数据
     组件内部
          <slot name="top" :list="list" :msg="msg"></slot>
          把组件中的list赋值给list属性,把msg赋值给msg属性,插槽中提供了两个作用域属性:list/msg
    
        调用组件
          <template #top="AAA"></template>
          定义一个叫做AAA的变量,来接收插槽中绑定的数据
          AAA={
            list:[...],
            msg:...
          }

    组件传参 

    调用组件的时候

    每创建一个组件其实相当于创建一个自定义类,而调用这个组件就是创建VueCommponent(或者Vue)类的实例

    • 实例(this)->VueComponent.prototype->Vue.prototype->Object.prototype
    • 当前实例可以访问Vue.prototype上的一些公共属性和方法

    组件中的script中存在的状态值和属性值?

    • ==状态值==:data中的数据值称为状态值
    • ==属性值==:props中的数据值称为属性值
    • 状态值和属性值是直接挂载到_vode对象的私有属性中(所以状态值和属性值名字不能重复)
    • 我们在视图template标签中调用状态值和属性值,不需要加this,直接调用状态名或属性名
    • 我们在功能script标签中调用状态值和属性值,需要加this调用
    • ==computed(计算属性)==:也是挂载实例上的,所以他们三个都不能重名

    vue中的单向数据流

    父子组件传递数据时,只能由父组件流向子组件,不能由子组件流向父组件。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。

    组件传参的分类7种:

    • 父组件向子组件传参:props
    • 子组件向父组件传参:发布订阅(@xxx给子组件标签自定义事件、$emit)
    • 组件相互传参(兄弟):发布订阅(on、emit)【2和3传参是一种】
    • 祖先向后代传参(provide[提供],inject[接收])
    • vue实例属性传参(parent、children[n]、root、refs)
    • vuex
    • localStorage sessionStorage

    1.父组件向子组件传参

    父组件向子组件传参:props

    • 我们传给组件的值,默认是==字符串类型==的,比如msg
    • 如果想传==数字类型==的,则需要调用v-bind或冒号的形式传值
    • 我们每调用一次coma,都会生成一个独立的VueComponent的实例

    第一步:父组件在组件调用标签中自定义属性

    //如果想把data中的状态值传递过去需要v-bind绑定
    <coma msg="hello" :num="num"></coma>

    注意 如果想把data中的状态值传递过去需要v-bind绑定

    第二步:子组件通过props接收(数组,对象)

    • props中的属性是只读的,子组件不能修改这些值,否则会报错
    • 解决只读问题:用自定义变量接收传递过来的值,页面使用自定义变量
    • props可以是对象或数组类型,对象可以对数据做校验,数组不能
        // props的值是只读的 能改,会报错
        <input type="text" v-model="num" />
        //数组格式
        props:["msg","num"]
        //对象格式
         props: {
        msg: {
          //传参类型必须是字符串
          type: String,
          //必须传参
          required: true,
        },
        num: {
          type: Number,
          //如果不传参默认是102
          default: 102,
        },
      },
        //----------------------------------------
        //用自定义变量numa接收num,然后页面使用numa(解决只读问题)
        <h1>我是子组件 coma------{{ msg }}----{{ numa }}</h1>
        <input type="text" v-model="numa" />
        props: ["msg", "num"],
          data() {
            return {
            numa: this.num,
           };
         },    

    2.子组件向父组件传参

    子组件向父组件传参,基于==发布订阅(@xxx给子组件标签自定义事件、$emit)==

    第一步:父组件在调用子组件的标签上需要自定义一个事件,这个事件及绑定的方法就会添加到子组件的事件池中:底层实质上是调用了this.$on("myEvent",fn)

    <Coma @myEvent="getData"></Coma>
     methods: {
        getData() {},
      },

    第二步:子组件用this.$emit()接受(this.$emit(myEvent,参数1,参数2)), 参数可以是子组件的,顺便传给父组件,实现子组件向父组件传值

      <button @click="goParentData">向父组件发送数据</button>
     data() {
        return {
          flag: "你很美",
          n: 101,
        };
      methods: {
        goParentData() {
          //执行父组件自定义的事件
          this.$emit("myEvent", this.flag, this.n);
        },
      },

    第三步:父组件使用传递过来的数据

     data() {
        return {
          n: 0,
          flag: "",
        };
      },
      methods: {
        getData(...parans) {
          console.log(parans);
          //传递过来的是数组
          this.n = parans[0];
          this.flag = parans[1];
        },
      },

    3.组件之间相互传参    原生事件法  (发布订阅)

    b--->c发送数据

    • c向事件池中添加方法(自定义方法):$on
    • b执行方法把参数传过去:$emit

    第一步:全局的main.js中创建一个全局的EventBus,挂载 vue的原型上  this.$bus

    • 作用:将EventBus看作定义在公有属性上的事件池(事件公交),之后基于这个$bus.$on()绑定的事件函数,在哪个vue实例上都可以基于$bus.$empty()执行,还可以传值
    //创建一个全局的 Eventbus
    let Eventbus=new Vue();
    //挂载 vue的原型上  后期基于this.$bus
    Vue.prototype.$bus=Eventbus;

    第二步:comc向事件池中绑定事件:this.$bus.$on("事件名",函数)

      created() {
        //向事件池中添加方法
        this.$bus.$on("myEvent", () => {});
      },

    第三步:comb从事件池中获取事件函数并执行:this.$bus.$emit("事件名",想传的参数)

        <button @click="send">发送数据给comc</button>
          data() {
            return {
              msg: "我是comb",
        };
        methods: {
        send() {
          //执行事件池中的方法,并且传参
          this.$bus.$emit("myEvent", this.msg);
        },

    第四步 comc使用传递过来的数据

       <h1>组件 comc----{{ msg }}</h1>
         data() {
            return {
              msg: "",
          };
      //创建之后的钩子函数向事件池中添加方法
     created() {
        //向事件池中添加方法
        this.$bus.$on("myEvent", (value) => {
          console.log(value);
          this.msg = value;
        });
      },

    4.祖先和后代相互传参

    • 第一步:祖先要使用provide方法传参,不是写在methods里面,与methods同级
     data() {
        return {
          title: "我是about祖先",
        };
      },
      provide() {
        return {
          title: this.title,
        };
      },

    第二步:后代使用inject属性接受祖先中的参数,inject是data中的数据,是数组类型

      inject: ["title"],因为inject是数组类型,所以它符合如果数据项不是对象类型,则不做劫持,如果数据项是对象,则这个对象中的属性会做劫持。

      data() {
        return {
          title: "我是about祖先",
        };
      },
    //祖先 传递的title是非响应式
      provide() {
        return {
          title: this.title,
        };
      },
    //------------------------------
      data() {
        return {
          //obj非响应式
          obj: {
            //title是响应式
            title: "我是about祖先",
          },
        };
      },
      //祖先 传递的参数失去响应式,但里面的值会是响应式
      provide() {
        return {
          obj: this.obj,
        };
      },

    vue实例属性传参

    vue的实例中存在一些属性能够获取不同关系的元素,获取之后就可以基于这个元素获取其中的数据或方法了:

    • $parent 获取父元素的数据/方法  获取父元素的整个vm实例
    • 子组件可以在任何生命周期函数中获取父元素【父子组件的生命周期
      created() {
        console.log(this.$parent.title);
      },
    •  $children  获取子元素的数据/方法(mounted钩子函数,要有下标)
    • this.$children[n]:获取第n个子元素的vm实例
    • 父组件只能在mounted生命周期函数里或之后获取子元素【父子组件的生命周期
      mounted() {
        console.log(this.$children[0].msg);
      },
    • $root获取根组件的数据/方法
    • this.$root:获取根元素的vm实例(main.js中new 的Vue实例)
    et mv = new Vue({
      router,
      data() {
        return {
          rootmsg: "我是草根"
        }
      },
      render: h => h(App)
    }).$mount('#app')
    ---------------------
      mounted() {
        console.log(this.$root.rootmsg);
      },
    • this.$refs:this的子元素中需要定义ref属性:比如ref="xxx"
    • ==如果ref定义在DOM标签中==:this.$refs.xxx获取的是DOM对象
    • ==如果ref定义在子组件标签中==:this.$refs.xxx获取的是子组件的vm实例
      //获取的是dom元素
      <p ref="one">11111</p>
       mounted() {
        console.log(this.$refs.one);
      },
    -----------------------------------
    获取的是组件
      <comb ref="b"></comb>
      mounted() {
        console.log(this.$refs.b);
      },
    //如果不是组件获取的就是dom元素,如果是组件,获取的就是组件的实例

    父子组件的生命周期

    重点:父组件更新默认不会触发子组件更新,但是**==如果子组件中绑定调用了父组件的数据aaa,父组件的aaa数据更新触发重新渲染时,使用aaa数据{{$parent.aaa}}的子组件也会触发更新==**

    一、父子组件生命周期执行过程

    • 父->beforeCreated
    • 父->created
    • 父->beforeMount
    •         子->beforeCreate
    •        子->created
    •         子->beforeMount
    •         子->mounted
    • 父->mounted

    二、子组件更新过程:

    • 父->berforeUpdate
    •         子->berforeUpdate
    •        子->updated
    • 父->updated

    三、父组件更新过程:

    • 父->berforeUpdate
    • 父->updated

    四、父组件销毁过程:

    • 父->beforeDestory
    •         子beforeDestory
    •         子destoryed
    • 父->destoryed

    扩展------------------------

    父组件绑定在子组件标签中的事件,是无法触发的,如何解决?

    @xxx.native: 监听组件根元素的原生事件。

    • 例子<my-component @click.native="onClick"></my-component>

    • 原理:在父组件中给子组件绑定一个==原生(click/mouseover...)==的事件,就将子组件变成了普通的HTML标签,不加'. native'父组件绑定给子组件标签的事件是无法触发的

    虚拟DOM

    虚拟DOM对象:_vnode,作用:

    第一步:vue内部自己定义的一套对象,基于自己规定的键值对,来描述视图中每一个节点的特征:

    • tag标签名
    • text文本节点,存储文本内容
    • children:子节点
    • data:属性
    • 第二步:基于vue-template-compiler去渲染解析 template 视图,最后构建出上述的虚拟DOM对象
    • 第三步:组件重新渲染,又重新生成一个 _vnode
    • 第四步:对比两次的 _vnode. 获取差异的部分
    • 第五步:把差异的部分渲染为真实的DOM

    组件库

    • element-ui:饿了么
    • antdv :蚂蚁金服
    • iview :京东

    如何在项目中使用功能性组件?

    ==第一步==:安装element-ui:$npm i element-ui -s

    ==第二步==:导入:

    完整导入:整个组件库都导入进来,想用什么直接用Vue.use(xxx)即可

    缺点:如果我们只用几个组件,则无用的导入组件会造成项目打包体积变大[不好],所以项目中推荐使用按需导入

    按需导入

    1、需要安装依赖$ npm install babel-plugin-component

    样式私有化

    在Vue中我们基于scoped设置样式私有化之后:

    • 会给组件创建一个唯一的ID(例如:data-v-5f109989)

    • 在组件视图中,我们编写所有元素(包含元素调用的UI组件),都设置了这个ID属性;但是我们调用的组件内部的元素,并没有设置这个属性!!

       <div data-v-5f1969a9 class="task-box">
          <button data-v-5f1969a9 type="button" class="el-button el-button--primary">
            <span>新增任务</span>
          </button>
        </div>

    而我们编写的样式,最后会自动加上属性选择器:

     .task-box {
          box-sizing: border-box;
          ...
        }
    ---------编译后成为:---------
        .task-box[data-v-5f1969a9]{
          box-sizing: border-box;
        }
    • ==组件样式私有化的原理==:设置唯一的属性(组件ID)、组件内部给所有样式后面都加上该属性选择器
    • ==问题==:组件内部的元素没有设置这个属性,但是我们编写的样式是基于这个属性选择器在css设置的选择器,
    • ==解决==:在组件内部的元素选择器前加/deep/:
        /deep/.el-textarea__inner,
        	/deep/.el-input__inner{
       		 border-radius: 0;
     		 }

    API

    • 在真实项目中,我们会把数据请求和axios的二次封装,都会放到src/api路径下进行管理

    //main.js
    	import api from '@/api/index';
    	// 把存储接口请求的api对象挂载搭配Vue的原型上:
        后续在各个组件基于this.$api.xxx()就可以发送请求了,无需在每个组件中再单独导入这个api对象。
    	Vue.prototype.$api=api;

    展开全文
  • Vue基础知识总结 4:vue组件化开发

    千次阅读 多人点赞 2021-07-21 23:37:50
    和过程编程相比,函数式编程里函数的计算可随时调用。 filter函数自动过滤对象的所有元素,返回true才会存入指定对象; Reduce函数对数组内部的所有元素进行汇总; 2、代码实例 <!DOCTYPE

    🍅 作者简介:哪吒,CSDN2021博客之星亚军🏆、新星计划导师✌、博客专家💪

    🍅 哪吒多年工作总结:Java学习路线总结,搬砖工逆袭Java架构师

    🍅 关注公众号【哪吒编程】,回复1024,获取Java学习路线思维导图、大厂面试真题、加入万粉计划交流群、一起学习进步

    目录

    一、函数式编程

    1、函数式编程简介

    2、代码实例

    二、v-model

    1、v-model双向绑定

    2、v-model和radio结合使用

    3、v-model和CheckBox单选框结合使用

    4、v-model和CheckBox多选框结合使用

    5、v-model结合select使用

    6、v-for值绑定

    7、v-model修饰符的使用

    三、组件化开发

    1、全局组件

    2、局部组件

    3、父子组件

    4、组件化语法糖写法

    5、组件模板抽离写法

    四、组件可以访问Vue实例数据吗?

    1、简介

    2、代码实例

    3、效果展示 

    五、父子组件通信

    1、父子组件通信简介

    2、父传子代码实例

    3、父传子效果展示 

    4、props中的驼峰标识

    5、子传父(自定义事件方式)

    6、子传父代码实例

    7、子传父效果展示


    一、函数式编程

    1、函数式编程简介

    函数式编程是种编程方式,它将电脑运算视为函数的计算。函数编程语言最重要的基础是λ演算(lambda calculus),而且λ演算的函数可以接受函数当作输入(参数)和输出(返回值)。

    和指令式编程相比,函数式编程强调函数的计算比指令的执行重要。

    和过程化编程相比,函数式编程里函数的计算可随时调用。

    filter函数自动过滤对象的所有元素,返回true才会存入指定对象;

    Reduce函数对数组内部的所有元素进行汇总;

    2、代码实例

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Title</title>
    </head>
    <body>
    <div id="app">
      {{totalPrice()}}
    </div>
     
    <script src="../js/vue.js"></script>
    <script>
      const app = new Vue({
        el: '#app',
        data: {
          message: '你好'
        },
        methods :{
          totalPrice(){
            const nums = [10,9,21,16,7]
            let total = nums.filter(x => x<10).map(x => x*2).reduce((pre,n)=>pre+n);
            console.log(total)
            return total
          }
        }
      })
    </script>
    </body>
    </html>

    二、v-model

    vue中经常使用到<input>和<textarea>这类表单元素,vue对于这些元素的数据绑定和我们以前经常用的jQuery有些区别。vue使用v-model实现这些标签数据的双向绑定,它会根据控件类型自动选取正确的方法来更新元素。

    1、v-model双向绑定

    <input type="text" v-model="message">

    v-model动态双向绑定实现原理,本质上包含两个操作:

    (1)v-bind绑定一个value属性

    (2)v-on指令给当前元素绑定input事件

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Title</title>
    </head>
    <body>
    <div id="app">
      <!-- <input type="text" :value="message" v-on:input="valueChange"> 
      <input type="text" :value="message" @input="valueChange"> -->
      <input type="text" :value="message" @input="message = $event.target.value">
      {{message}}
    </div>
     
    <script src="../js/vue.js"></script>
    <script>
      const app = new Vue({
        el: '#app',
        data: {
          message: '哪吒'
        },
        methods: {
          valueChange(event){
            this.message = event.target.value;
          }
        }
      })
    </script>
    </body>
    </html>

    2、v-model和radio结合使用

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Title</title>
    </head>
    <body>
    <div id="app">
      <label for="male">
        <!-- <input type="radio"id="male" name="sex" value="男"
               v-model="sex">男
        <input type="radio"id="female" name="sex" value="女"
               v-model="sex">女 -->
        <input type="radio"id="male" value="男" v-model="sex">男
        <input type="radio"id="female" value="女" v-model="sex">女
      </label>
      <h3>您选择的是:{{sex}}</h3>
    </div>
     
    <script src="../js/vue.js"></script>
    <script>
      const app = new Vue({
        el: '#app',
        data: {
          message: '你好',
          sex: '女'
        }
      })
    </script>
    </body>
    </html>

    3、v-model和CheckBox单选框结合使用

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Title</title>
    </head>
    <body>
    <div id="app">
      <!-- checkbox单选框 -->
      <label for="license">
        <input type="checkbox"id="license" v-model="isAgree">同意协议
      </label>
      <h3>您选择的是:{{isAgree}}</h3>
      <button :disabled="!isAgree">下一步</button>
    </div>
     
    <script src="../js/vue.js"></script>
    <script>
      const app = new Vue({
        el: '#app',
        data: {
          message: '你好',
          isAgree: false
        }
      })
    </script>
    </body>
    </html>

    4、v-model和CheckBox多选框结合使用

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Title</title>
    </head>
    <body>
    <div id="app">
      <!-- checkbox多选框 -->
      <input type="checkbox" value="比比东" v-model="girls">比比东
      <input type="checkbox" value="千仞雪" v-model="girls">千仞雪
      <input type="checkbox" value="美杜莎" v-model="girls">美杜莎
      <input type="checkbox" value="云韵" v-model="girls">云韵
      <input type="checkbox" value="雅妃" v-model="girls">雅妃
      <h3>您选择的是:{{girls}}</h3>
    </div>
     
    <script src="../js/vue.js"></script>
    <script>
      const app = new Vue({
        el: '#app',
        data: {
          message: '你好',
          girls: []
        }
      })
    </script>
    </body>
    </html>

    5、v-model结合select使用

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Title</title>
    </head>
    <body>
    <div id="app">
      <!-- 选择一个 -->
      <select name="abc" v-model="girl">
        <option value="云韵">云韵</option>
        <option value="比比东">比比东</option>
        <option value="雅妃">雅妃</option>
        <option value="千仞雪">千仞雪</option>
        <option value="美杜莎">美杜莎</option>
      </select>
      <h3>您的选择是:{{girl}}</h3>
    </div>
     
    <script src="../js/vue.js"></script>
    <script>
      const app = new Vue({
        el: '#app',
        data: {
          message: '你好',
          girl: '云韵'
        }
      })
    </script>
    </body>
    </html>

    6、v-for值绑定

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Title</title>
    </head>
    <body>
    <div id="app">
      <label v-for="item in beautyGirls" :for="item">
        <input type="checkbox" :value="item"
               :id="item" v-model="girls">{{item}}
      </label>
      <h3>您的选择是:{{girls}}</h3>
    </div>
     
    <script src="../js/vue.js"></script>
    <script>
      const app = new Vue({
        el: '#app',
        data: {
          message: '你好',
          girls: [],//多选框
          beautyGirls: ["云韵","比比东","雅妃","纳兰嫣然","美杜莎"]
        }
      })
    </script>
    </body>
    </html>

    7、v-model修饰符的使用

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Title</title>
    </head>
    <body>
    <div id="app">
      <!-- lazy懒加载,失去焦点时触发 -->
      <input type="text" v-model.lazy="message">
      <h2>{{message}}</h2>
     
      <!-- number:表示数字类型 -->
      <input type="number" v-model.number="age">
      <h2>{{age}} --> {{typeof age}}</h2>
     
      <!-- 去掉左右两边的控股 -->
      <input type="text" v-model.trim="name">
      <h2>{{name}}</h2>
    </div>
     
    <script src="../js/vue.js"></script>
    <script>
      const app = new Vue({
        el: '#app',
        data: {
          message: '哪吒',
          age: 0,
          name: '哪吒'
        }
      })
    </script>
    </body>
    </html>

    三、组件化开发

    组件是Vue.js​中重要思想

    • 它提供了一种抽象, 我们可以开发出一个独立可复用的小组件来构造我们的应用组件
    • 可以扩展 HTML 元素,封装可重用的代码
    • 组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树

    组件化思想应用 

    • 有了组件化的思想, 我们之后开发中就要充分的利用它
    • 尽可能将页面拆分成一个个小的, 可复用的组件
    • 这样让我们代码更方便组织和管理, 并且扩展性也强

    1、全局组件

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Title</title>
    </head>
    <body>
    <div id="app">
      <my-cpn></my-cpn>
    </div>
     
    <script src="../js/vue.js"></script>
    <script>
     
      //1.创建组件化构造器对象
      const cpnC = Vue.extend({
        template: `
          <div>
            <h2>我是标题</h2>
            <p>我是CSDN哪吒</p>
          </div>
          `
      })
     
      //2.注册组件
      Vue.component('my-cpn',cpnC)
     
      const app = new Vue({
        el: '#app',
        data: {
          message: '你好'
        }
      })
    </script>
    </body>
    </html>

    2、局部组件

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Title</title>
    </head>
    <body>
    <div id="app">
      <cpn></cpn>
    </div>
     
    <script src="../js/vue.js"></script>
    <script>
     
      //1.创建组件化构造器对象
      const cpnC = Vue.extend({
        template: `
          <div>
            <h2>我是标题</h2>
            <p>我是CSDN哪吒</p>
          </div>
          `
      })
     
      const app = new Vue({
        el: '#app',
        data: {
          message: '你好'
        },
        components: {
          cpn: cpnC
        }
      })
    </script>
    </body>
    </html>

    3、父子组件

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Title</title>
    </head>
    <body>
    <div id="app">
      <cpn2></cpn2>
    </div>
     
    <script src="../js/vue.js"></script>
    <script>
     
      //1.创建组件化构造器对象
      const cpnC1 = Vue.extend({
        template: `
          <div>
            <h2>我是标题1</h2>
            <p>我是CSDN哪吒</p>
          </div>
          `
      })
     
      const cpnC2 = Vue.extend({
        template: `
          <div>
            <h2>我是标题2</h2>
            <p>我是博客专家</p>
            <cpn1></cpn1>
          </div>
          `,
        components: {
          cpn1: cpnC1
        }
      })
     
      const app = new Vue({
        el: '#app',
        data: {
          message: '你好'
        },
        components: {
          cpn2: cpnC2
        }
      })
    </script>
    </body>
    </html>

    4、组件化语法糖写法

    vue为了简化注册组件的过程,提供了语法糖的写法,主要是省去了调用Vue.extend()的步骤,直接使用一个对象替代。

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Title</title>
    </head>
    <body>
    <div id="app">
      <my-cpn></my-cpn>
    </div>
     
    <script src="../js/vue.js"></script>
    <script>
      //注册组件语法糖写法
      Vue.component('my-cpn',{
        template: `
          <div>
            <h2>我是标题</h2>
            <p>我是CSDN哪吒</p>
          </div>
          `
      })
     
      const app = new Vue({
        el: '#app',
        data: {
          message: '你好'
        }
      })
    </script>
    </body>
    </html>

    5、组件模板抽离写法

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Title</title>
    </head>
    <body>
     
    <div id="app">
      <cpn></cpn>
      <cpn></cpn>
      <cpn></cpn>
    </div>
     
    <!--1.script标签, 注意:类型必须是text/x-template-->
    <!--<script type="text/x-template" id="cpn">-->
    <!--<div>-->
    <!--<h2>我是标题</h2>-->
    <!--<p>我是CSDN哪吒</p>-->
    <!--</div>-->
    <!--</script>-->
     
    <!--2.template标签-->
    <template id="cpn">
      <div>
        <h2>我是标题</h2>
        <p>我是CSDN哪吒</p>
      </div>
    </template>
     
    <script src="../js/vue.js"></script>
    <script>
     
      // 1.注册一个全局组件
      Vue.component('cpn', {
        template: '#cpn'
      })
     
      const app = new Vue({
        el: '#app',
        data: {
          message: '你好啊'
        }
      })
    </script>
     
    </body>
    </html>

    四、组件可以访问Vue实例数据吗?

    1、简介

    实验发现,组件不能访问Vue实例数据,而且即便可以访问,如果将所有的数据都放在Vue实例中,Vue实例就会变得非常臃肿。

    Vue组件应该有自己保存数据的地方。

    组件自己的数据存放在哪里?

    • 组件对象也有一个data属性(也有method等属性);
    • 只是这个data属性必须是一个函数;
    • 而且这个函数返回一个对象,对象内部保存着数据;

    2、代码实例

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Title</title>
    </head>
    <body>
     
    <div id="app">
      <cpn></cpn>
    </div>
    <template id="cpn">
      <div>
        <h2>{{title}}</h2>
        <p>我是热门</p>
      </div>
    </template>
     
    <script src="../js/vue.js"></script>
    <script>
     
      // 1.注册一个全局组件
      Vue.component('cpn', {
        template: '#cpn',
        data() {
          return {
            title: '哪吒必胜'
          }
        }
      })
     
      const app = new Vue({
        el: '#app',
        data: {
          message: '你好',
          // title: '我是标题'
        }
      })
    </script>
     
    </body>
    </html>

    3、效果展示 

    五、父子组件通信

    1、父子组件通信简介

    在开发中,往往一些数据确实需要从上层传递到下层:

    比如在一个页面中,我们从服务器请求到了很多的数据。

    其中一部分数据,并非是我们整个页面的大组件来展示的,而是需要下面的子组件进行展示。

    这个时候,并不会让子组件再次发送一个网络请求,而是直接让大组件(父组件)将数据传递给小组件(子组件)。

    如何进行父子组件间的通信呢?Vue官方提到:

    通过props向子组件传递数据

    通过事件向父组件发送消息

    在组件中,使用选项props来声明需要从父级接收到的数据。

    props的值有两种方式:

    方式一:字符串数组,数组中的字符串就是传递时的名称。

    方式二:对象,对象可以设置传递时的类型,也可以设置默认值等。

    2、父传子代码实例

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Title</title>
    </head>
    <body>
     
    <div id="app">
      <!--<cpn v-bind:cgirls="girls"></cpn>-->
      <!--<cpn cgirls="girls" cmessage="message"></cpn>-->
     
      <cpn :cmessage="message" :cgirls="girls"></cpn>
    </div>
     
    <template id="cpn">
      <div>
        <ul>
          <li v-for="item in cgirls">{{item}}</li>
        </ul>
        <h2>{{cmessage}}</h2>
      </div>
    </template>
     
    <script src="../js/vue.js"></script>
    <script>
      // 父传子: props
      const cpn = {
        template: '#cpn',
        // props: ['cgirls', 'cmessage'],
        props: {
          // 1.类型限制
          // cgirls: Array,
          // cmessage: String,
     
          // 2.提供一些默认值, 以及必传值
          cmessage: {
            type: String,
            default: 'aaaaaaaa',
            required: true
          },
          // 类型是对象或者数组时, 默认值必须是一个函数
          cgirls: {
            type: Array,
            default() {
              return []
            }
          }
        },
        data() {
          return {}
        },
        methods: {
     
        }
      }
     
      const app = new Vue({
        el: '#app',
        data: {
          message: 'CSDN哪吒',
          girls: ['云韵', '比比东', '雅妃']
        },
        components: {
          cpn
        }
      })
    </script>
    </body>
    </html>

    3、父传子效果展示 

    4、props中的驼峰标识

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Title</title>
    </head>
    <body>
     
    <div id="app">
      <cpn :c-info="info" :child-my-message="message" v-bind:class></cpn>
    </div>
     
    <template id="cpn">
      <div>
        <h2>{{cInfo}}</h2>
        <h2>{{childMyMessage}}</h2>
      </div>
    </template>
     
    <script src="../js/vue.js"></script>
    <script>
      const cpn = {
        template: '#cpn',
        props: {
          cInfo: {
            type: Object,
            default() {
              return {}
            }
          },
          childMyMessage: {
            type: String,
            default: ''
          }
        }
      }
     
      const app = new Vue({
        el: '#app',
        data: {
          info: {
            name: '哪吒',
            age: 18,
            height: 1.88
          },
          message: 'csdn博客专家'
        },
        components: {
          cpn
        }
      })
    </script>
     
    </body>
    </html>

    效果展示 

    5、子传父(自定义事件方式)

    自定义事件方式完成子传父。

    什么时候需要自定义事件呢?

    当子组件需要向父组件传递数据时,就要用到自定义事件了。

    我们之前学习的v-on不仅仅可以用于监听DOM事件,也可以用于组件间的自定义事件。

    自定义事件的流程:

    1. 在子组件中,通过$emit()来触发事件。
    2. 在父组件中,通过v-on来监听子组件事件。

    6、子传父代码实例

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Title</title>
    </head>
    <body>
     
    <!--父组件模板-->
    <div id="app">
      <cpn @item-click="cpnClick"></cpn>
    </div>
     
    <!--子组件模板-->
    <template id="cpn">
      <div>
        <button v-for="item in categories"
                @click="btnClick(item)">
          {{item.name}}
        </button>
      </div>
    </template>
     
    <script src="../js/vue.js"></script>
    <script>
     
      // 1.子组件
      const cpn = {
        template: '#cpn',
        data() {
          return {
            categories: [
              {id: '1', name: '云韵'},
              {id: '2', name: '比比东'},
              {id: '3', name: '雅妃'},
              {id: '4', name: '纳兰嫣然'},
            ]
          }
        },
        methods: {
          btnClick(item) {
            // 发射事件: 自定义事件
            this.$emit('item-click', item)
          }
        }
      }
     
      // 2.父组件
      const app = new Vue({
        el: '#app',
        data: {
          message: 'csdn哪吒'
        },
        components: {
          cpn
        },
        methods: {
          cpnClick(item) {
            console.log('cpnClick', item);
          }
        }
      })
    </script>
     
    </body>
    </html>

    7、子传父效果展示

    上一篇:Vue知识体系总结 3:Vue常用标签

    下一篇:Vue基础知识总结 5:Vue实现树形结构

    🍅 作者简介:哪吒,CSDN2021博客之星亚军🏆、新星计划导师✌、博客专家💪

    🍅 哪吒多年工作总结:Java学习路线总结,搬砖工逆袭Java架构师

    🍅 关注公众号【哪吒编程】,回复1024,获取Java学习路线思维导图、大厂面试真题、加入万粉计划交流群、一起学习进步

     关注公众号,备注1024,获取Java学习路线思维导图、加入万粉计划交流群  

    展开全文
  • 二、vue组件化开发(轻松入门vue)

    千次阅读 2020-04-15 17:28:59
    二、vue组件化开发(轻松入门vue) Vue组件化开发五、组件化开发1. 组件注册组件命名规范组件注册注意事项全局组件注册局部组件注册2. Vue调试工具下载3. 组件间数据交互父组件向子组件传值props传递数据原则:单向...

    轻松入门vue系列

    • 组件化思想:标准、分治、重用、组合
    • 组件 (Component) 是 Vue.js 最强大的功能之一
    • 组件可以扩展 HTML 元素,封装可重用的代码

    五、组件化开发

    1. 组件注册

    官方强烈推荐遵循 W3C 规范中的自定义组件名 (字母全小写且必须包含一个连字符)。这会帮助你避免和当前以及未来的 HTML 元素相冲突。

    组件命名规范
    1. 当使用 短横线分隔命名定义一个组件时,你也必须在引用这个自定义元素时使用短横线分隔命名例如:
    Vue.component('my-component-name', { /* ... */ })
    <my-component-name>
    
    1. 当使用 首字母大写命名定义一个组件时,你在引用这个自定义元素时两种命名法都可以使用(在组件模板内容中)直接在dom中依旧只能使用短横线分割的形式。
    Vue.component('MyComponentName', { /* ... */ })
    <my-component-name>或者<MyComponentName>
    
    组件注册注意事项
    1. data必须是一个函数

    data使用函数会形成一个闭包的环境,保证每个组件的数据是独立的。

    Vue.component('button-counter',{
            //组件中需要的数据
           data: function () {
               return{
                   count:0
               }
           },
            //组件模板内容
            template:`
                <div>
                    <button @click='handel'>点击了{{count}}次</button>
                    <button>确定</button>
                </div>
            `,
            methods:{
               handel:function () {
                   this.count+=2;
               }
            }
        });
        ```
    2. 组件模板内容必须是单个根节点的元素
    
    ```vue
    <!--错误-->
    <button @click='handel'>点击了{{count}}次</button>
    <button>确定</button>
    <!--正确-->
    <div>
    	<button @click='handel'>点击了{{count}}次</button>
    	<button>确定</button>
    </div>
    
    1. 组件模板内容可以是模板字符串(ES6语法需要浏览器支持)

    当模板很长的时候使用字符串形式代码将会十分繁杂

    //组件模板内容
    template:"<div>\n" +
        "\t<button @click='handel'>点击了{{count}}次</button>\n" +
        "\t<button>确定</button>\n" +
        "</div>",
    

    vue提供模板字符串形式,在模板外部加上反引号

    //组件模板内容
    template:`
        <div>
            <button @click='handel'>点击了{{count}}次</button>
            <button>确定</button>
        </div>
    `,
    
    全局组件注册

    注册之后可以用在任何新创建的 Vue 根实例 (new Vue) 的模板中

    Vue.component('组件名称', {
    	data:组件数据(必须是一个函数),
    	template:组件模板内容
    });
    

    demo

    <body>
        <div id="app">
            <button-counter></button-counter>
            <button-counter></button-counter>
        </div>
        <script>
            //组件注册
            Vue.component('button-counter',{
                //组件中需要的数据
               data: function () {
                   return{
                       count:0
                   }
               },
                //组件模板内容
                template:"<button @click='handel'>点击了{{count}}次</button>",
                methods:{
                   handel:function () {
                       this.count+=2;
                   }
                }
            });
            var vue = new Vue({
                el:"#app",
                data:{
    
                },
            })
        </script>
    </body>
    
    局部组件注册

    只能在注册他的父组件中使用

    //可以通过一个普通的 JavaScript 对象来定义组件:
    var ComponentA = { /* ... */ }
    var ComponentB = { /* ... */ }
    var ComponentC = { /* ... */ }
    //在 components 选项中定义你想要使用的组件:
    new Vue({
      el: '#app',
      components: {
        'component-a': ComponentA,
        'component-b': ComponentB
      }
    })
    

    demo

    <div id="app1">
        <component-a></component-a>
    </div>
    <script>
        var ComponentA = {
            //组件中需要的数据
            data: function () {
                return{
                    count:0
                }
            },
            //组件模板内容
            template:`
                <div>
                    <button @click='handel'>点击了{{count}}次</button>
                    <button>确定</button>
                </div>
            `,
            methods:{
                handel:function () {
                    this.count+=2;
                }
            }
        };
        new Vue({
            el: '#app1',
            components: {
                'component-a': ComponentA,
            }
        })
    </script>
    

    2. Vue调试工具下载

    vue-devtools是一款基于chrome游览器的插件,用于调试vue应用,这可以极大地提高我们的调试效率。

    1. 根据官网提示信息去github下载安装

    在这里插入图片描述
    2. chrome商店直接下载
    在这里插入图片描述

    方便的查看各组件之间的关系,能够直接清楚的看到组件中的数据

    在这里插入图片描述

    3. 组件间数据交互

    父组件向子组件传值
    1. 组件内部通过props接收传递过来的值

    props用于接收父组件传递过来的数据,是一个数组

    Vue.component('blog-post', {
      // 在 JavaScript 中是 camelCase 的
      props: ['postTitle'],
      template: '<h3>{{ postTitle }}</h3>'
    })
    
    1. 父组件通过属性将值传递给子组件
    <blog-post post-title="来自父组件的数据!"></blog-post>
    <!--也可以是绑定的数据-->
    <blog-post :post-title="post"></blog-post>
    

    demo

    <div id="app">
        <!--直接传值、注意不能用postTitle(Html大小写不敏感)-->
        <blog-post post-title="来自父组件的数据"></blog-post>
        <!--通过 v-bind 动态赋值-->
        <blog-post :post-title="postTitle"></blog-post>
    </div>
    <script>
        Vue.component('blog-post', {
            // 在 JavaScript 中是 camelCase 的
            props: ['postTitle'],
            data:function(){
              return{
                  msg:"子组件本身的数据"
              }
            },
            template: '<h3>{{ postTitle +"----" + msg}}</h3>'
        });
        var vue =new Vue({
            el:"#app",
            data:{
                postTitle:"postTitle",
            },
        })
    </script>
    
    1. props属性名规则

    在props中使用驼峰形式,模板中需要使用短横线的形式

    字符串式的模板中没有这个限制(在template模板中给子组件传值可以使用驼峰形式)

    1. props属性值类型

    字符串String(略)

    数值Number

    <!-- 即便 `42` 是静态的,我们仍然需要 `v-bind` 来告诉 Vue -->
    <!-- 这是一个 JavaScript 表达式而不是一个字符串。-->
    <blog-post v-bind:likes="42"></blog-post>
    
    <!-- 用一个变量进行动态赋值。-->
    <blog-post v-bind:likes="post.likes"></blog-post>
    

    布尔值Boolean

    <!-- 包含该 prop 没有值的情况在内,都意味着 `true`。-->
    <blog-post is-published></blog-post>
    
    <!-- 即便 `false` 是静态的,我们仍然需要 `v-bind` 来告诉 Vue -->
    <!-- 这是一个 JavaScript 表达式而不是一个字符串。-->
    <blog-post v-bind:is-published="false"></blog-post>
    
    <!-- 用一个变量进行动态赋值。-->
    <blog-post v-bind:is-published="post.isPublished"></blog-post>
    

    数组Array

    <!-- 即便数组是静态的,我们仍然需要 `v-bind` 来告诉 Vue -->
    <!-- 这是一个 JavaScript 表达式而不是一个字符串。-->
    <blog-post v-bind:comment-ids="[234, 266, 273]"></blog-post>
    
    <!-- 用一个变量进行动态赋值。-->
    <blog-post v-bind:comment-ids="post.commentIds"></blog-post>
    

    对象Object

    <!-- 即便对象是静态的,我们仍然需要 `v-bind` 来告诉 Vue -->
    <!-- 这是一个 JavaScript 表达式而不是一个字符串。-->
    <blog-post
      v-bind:author="{
        name: 'Veronica',
        company: 'Veridian Dynamics'
      }"
    ></blog-post>
    
    <!-- 用一个变量进行动态赋值。-->
    <blog-post v-bind:author="post.author"></blog-post>
    
    props传递数据原则:单向数据流。

    只允许父组件向子组件传递数据,不允许子组件直接操作props中的数据

    子组件向父组件传值
    1. 子组件通过自定义事件向父组件传递信息
    Vue.component('menu-text',{
            template:`
                <button @click="$emit('enlarge-text')">字体变大</button>
            `
        });
    
    1. 父组件监听子组件的事件
    <menu-text @enlarge-text="handel"></menu-text>
    

    demo

    <div id="app">
        <div :style="{fontSize:fontSize+'px'}">字体</div>
        <menu-text @enlarge-text="handel"></menu-text>
    </div>
    <script>
        Vue.component('menu-text',{
            template:`
                <button @click="$emit('enlarge-text')">字体变大</button>
            `
        });
    
        var vue = new Vue({
            el:"#app",
            data:{
                fontSize:5,
            },
            methods:{
                handel:function () {
                    this.fontSize+=10;
                }
            }
        })
    </script>
    
    1. 子组件通过自定义事件向父组件传递信息
    <button @click="$emit('enlarge-text',10)">字体变大</button>
    
    1. 父组件监听子组件的事件
    <menu-text @enlarge-text="handel($event)"></menu-text>
    

    demo

    <div id="app">
        <div :style="{fontSize:fontSize+'px'}">字体</div>
        <menu-text @enlarge-text="handel($event)"></menu-text>
    </div>
    <script>
        Vue.component('menu-text',{
            template:`
                <button @click="$emit('enlarge-text',10)">字体变大</button>
            `
        });
    
        var vue = new Vue({
            el:"#app",
            data:{
                fontSize:5,
            },
            methods:{
                handel:function (val) {
                    this.fontSize+=val;
                }
            }
        })
    </script>
    
    非父子组件之间传值
    1. 单独的时间中心管理组件间的通信
    var hub = new Vue();// 提供事件中心
    
    1. 监听事件与销毁事件
    // 监听事件(创建一个监听事件)
    hub.$on('tom-event', (val) => {
    	this.num += val;
    });
    //销毁事件
    hub.$off('tom-event');
    
    1. 触发事件
    // 触发兄弟组件的事件
    hub.$emit('tom-event', 1);
    

    demo

    <div id="app">
        <div>父组件</div>
        <div>
            <button @click='handle'>销毁事件</button>
        </div>
        <test-tom></test-tom>
        <test-jerry></test-jerry>
    </div>
    <script type="text/javascript">
        /*
          兄弟组件之间数据传递
        */
        // 提供事件中心
        var hub = new Vue();
    
        Vue.component('test-tom', {
            data: function(){
                return {
                    num: 0
                }
            },
            template: `
            <div>
              <div>TOM:{{num}}</div>
              <div>
                <button @click='handle'>点击</button>
              </div>
            </div>
          `,
            methods: {
                handle: function(){
                    hub.$emit('jerry-event', 2);
                }
            },
            mounted: function() {
                // 监听事件
                hub.$on('tom-event', (val) => {
                    this.num += val;
                });
            }
        });
        Vue.component('test-jerry', {
            data: function(){
                return {
                    num: 0
                }
            },
            template: `
            <div>
              <div>JERRY:{{num}}</div>
              <div>
                <button @click='handle'>点击</button>
              </div>
            </div>
          `,
            methods: {
                handle: function(){
                    // 触发兄弟组件的事件
                    hub.$emit('tom-event', 1);
                }
            },
            mounted: function() {
                // 监听事件
                hub.$on('jerry-event', (val) => {
                    this.num += val;
                });
            }
        });
        var vm = new Vue({
            el: '#app',
            data: {
    
            },
            methods: {
                handle: function(){
                    hub.$off('tom-event');
                    hub.$off('jerry-event');
                }
            }
        });
    </script>
    

    4. 组件插槽

    父组件向子组件传递内容(模板的内容,区别去上面的数据交互)

    父组件标签之间的内容会放置到子组件插槽中

    基本用法

    当组件渲染的时候,<slot></slot>将会被替换为“hello Vue”。插槽内可以包含任何模板代码,包括 HTML:

    1. 插槽位置
    Vue.component('text-show',{
            template:`
                <div>
                    <strong>莫逸风</strong>
                    <slot></slot>
                </div>
            `
        });
    
    1. 插槽内容
    <text-show>hello Vue</text-show>
    

    demo

    <div id="app">
        <text-show>
            <strong>HelloVue</strong>
        </text-show>
    </div>
    <script>
    
        Vue.component('text-show',{
            template:`
                <div>
                    <strong>莫逸风</strong>
                    <slot></slot>
                </div>
            `
        });
    
        var vue = new Vue({
            el:"#app",
            data:{
    
            },
        })
    </script>
    
    1. 编译作用域

    hello访问的是app实例中的数据,而不是text-show中的数据

    父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。

    <div id="app">
        <text-show>
            <strong>{{hello}}</strong>
        </text-show>
    </div>
    
    1. 后备内容

    在子组件中solt标签中添加默认内容

    <slot>默认</slot>
    

    插槽无内筒显示默认内容

    <text-show></text-show>    <!--显示“默认”-->
    

    插槽有内容覆盖默认内容

    <text-show>莫逸风</text-show>    <!--显示“莫逸风”-->
    
    具名插槽用法

    自 2.6.0 起有所更新。已废弃的使用 slot attribute 的语法在这里

    1. 插槽定义

    一个不带 nameslot 出口会带有隐含的名字“default”。

    <div class="container">
      <header>
        <slot name="header"></slot>
      </header>
      <main>
        <slot></slot>
      </main>
      <footer>
        <slot name="footer"></slot>
      </footer>
    </div>
    
    1. 插槽内容

    我们可以在一个 <template> 元素上使用 v-slot 指令,其参数对应插槽name

    <base-layout>
      <template v-slot:header>
        <h1>Here might be a page title</h1>
      </template>
    
      <p>A paragraph for the main content.</p>
      <p>And another one.</p>
    
      <template v-slot:footer>
        <p>Here's some contact info</p>
      </template>
    </base-layout>
    

    demo

    <div id="app">
        <base-layout>
            <template v-slot:header>
                <h1>Here might be a page title</h1>
            </template>
    
            <p>A paragraph for the main content.</p>
            <p>And another one.</p>
    
            <template v-slot:footer>
                <p>Here's some contact info</p>
            </template>
        </base-layout>
    </div>
    <script>
    
        Vue.component('base-layout',{
            template:`
                <div class="container">
                  <header>
                    <slot name="header"></slot>
                  </header>
                  <main>
                    <slot></slot>
                  </main>
                  <footer>
                    <slot name="footer"></slot>
                  </footer>
                </div>
            `
        })
    
        var vue =new Vue({
            el:"#app",
            data:{
    
            },
        })
    </script>
    
    作用域插槽

    自 2.6.0 起有所更新。已废弃的使用 slot-scope attribute 的语法在这里

    有时让插槽内容能够访问子组件中才有的数据是很有用的。

    1. 插槽定义

    为了让 user 在父级的插槽内容中可用,我们可以将 user 作为 slot 元素的一个 attribute 绑定上去

    <span>
      <slot v-bind:user="user">
        {{ user.lastName }}
      </slot>
    </span>
    
    1. 插槽内容

    绑定在 <solt> 元素上的 attribute 被称为插槽 prop。现在在父级作用域中,我们可以使用带值的 v-slot 来定义我们提供的插槽 prop 的名字:

    <current-user>
      <template v-slot:default="slotProps">
        {{ slotProps.user.firstName }}
      </template>
    </current-user>
    

    demo

    <div id="app">
        <current-user :user="user">
            <template v-slot:default="slotProps">
                {{ slotProps.bindUser.firstName }}
            </template>
        </current-user>
        <current-user :user="user"></current-user>
    </div>
    <script>
        Vue.component('current-user',{
            props: ['user'],
            template:`
                <span>
                  <slot v-bind:bindUser="user">
                    {{ user.lastName }}
                  </slot>
                </span>
            `
        })
    
        var vue = new Vue({
            el:"#app",
            data:{
                user:{
                    firstName:"莫",
                    lastName:"逸风",
                }
            }
        })
    </script>
    
    展开全文
  • 主要介绍了Vue组件化开发之通用型弹出框的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • 使用过vue的程序员一般这样... 最新的Vue.js全家桶课程,集中的讲解了VUE全家桶原理和实现,手写VUE,VUE2源码剖析,VUE面试集训,VUE组件化开发实践,VUE项目最佳实践,掌握这些内容可以让同学们在工作中大显身手。
  • 目录 1.组件化开发思想 2.组件注册 3.Vue调试工具用法 4.组件间数据交互 5.组件插槽 6.基于组件的案例
  • 3:Vue组件化开发

    千次阅读 2020-04-28 12:24:17
    组件化开发 组件 组件 (Component) 是 Vue.js 最强大的功能之一 组件可以扩展 HTML 元素,封装可重用的代码 思想体现:标准,分治,重用,组合 一:组件注册 全局注册 Vue.component(‘组件名称’, { }) 第1个...
  • Vue3.x全家桶之Vue组件化开发(二)

    千次阅读 多人点赞 2021-09-05 16:47:36
    1、组件化开发 我们将一个完整的页面分成很多个组件,每个组件都用于实现页面的一个功能块,而每一个组件又可以进行细分 1.1、组件的使用 步骤: 创建组件构造器: 调用 Vue.extend() 方法创建组件构造器 注册组件...
  • 带有浏览器自动刷新,可以配置多页面应用开发,.vue组件化开发
  • Vue2.X vue组件化开发 组件vue官方文档:组件注册 — Vue.js 组件就是对局部视图的封装,每个组件包含了:HTML结构 CSS样式 JavaScript行为 (methods行为 data数据) 提高开发效率,增强可维护性,更好的解决软件上...
  • Thymeleaf + Vue组件化开发

    千次阅读 2022-04-30 15:05:27
    Thymeleaf 搭配 Vue 完成组件化开发前言一、vue21.引入静态文件2.声明组件二、语法搭配使用vue方法调用th数据 前言 提示:thymeleaf 固然好,但是 vue 也少不了: 可能 vue 用习惯了之后大部分玩家之后使用脚手架,...
  • 面试官:谈一下你对Vue组件化的理解

    千次阅读 多人点赞 2022-03-20 21:27:52
    假设说采取传统开发网页的方式去开发一个系统,在一定程度上,会...为了避免这些弊端可以采取组件化设计去开发一个多人协作、功能又较多的项目,组件化开发带来的可维护性和可复用性可以提升开发效率、降低代码耦合度。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 85,374
精华内容 34,149
关键字:

vue组件化开发

友情链接: CreateACCESS.rar