vue.js学习笔记六

一、全局组件和局部组件

  • 当我们通过调用Vue.component()注册组件时,组件的注册是全局的
  • 这意味着该组件可以在任意Vue示例下使用
  • 如果我们注册的组件是挂载在某个实例中,那么就是一个局部组件
    <div id="app">
        <cpn>cpn>
        <cpn>cpn>
        <cpn>cpn>
    div>

    <div id="app2">
        <cpn>cpn>
    div>

    <script src="../js/vue.js">script>

    <script>
        //1。创建组件构造器
        const cpnC = Vue.extend({
       
            template: `
            

我是标题

我是内容,哈哈哈

`
}) // 2.注册组件(全局组件, 意味着可以在多个Vue的实例下面使用) // Vue.component('cpn', cpnC) // 疑问: 怎么注册的组件才是局部组件了? const app = new Vue({ el: '#app', data: { message: '你好啊' }, components: { // cpn使用组件时的标签名 cpn: cpnC } }) const app2 = new Vue({ el: '#app2' })
script>

二、父组件和子组件

  • 在前面我们看到了组件树
  • 组件和组件之间存在层级关系
  • 而其中一种非常重要的关系就是父子组件的关系
  • 父子组件错误用法:以子标签的形式在Vue实例中使用
  • 因为当子组件注册到父组件的components时,Vue会编译好父组件的模块
  • 该模板的内容已经决定了父组件将要渲染的HTML(相当于父组件中已经有了子组件中的内容了)
  • 是只能在父组件中被识别的
  • 类似这种用法, 是会被浏览器忽略的

vue.js学习笔记六_第1张图片

 <div id="app">
        <cpn2>cpn2>
        
        
    div>
    <script src="../js/vue.js">script>
    <script>
        // 1.创建第一个组件构造器(子组件)
        const cpnC1 = Vue.extend({
       
                template: `
      

我是标题1

我是内容, 哈哈哈哈

`
}) // 2.创建第二个组件构造器(父组件) const cpnC2 = Vue.extend({ template: `

我是标题2

我是内容, 呵呵呵呵

`
, components: { cpn1: cpnC1 } }) // root组件 const app = new Vue({ el: '#app', data: { message: '你好啊' }, components: { cpn2: cpnC2 } })
script>



三、注册组件语法糖

  • 在上面注册组件的方式,可能会有些繁琐
  • Vue为了简化这个过程,提供了注册的语法糖
  • 主要是省去了调用Vue.extend()的步骤,而是可以直接使用一个对象来代替
    <div id="app">
        <cpn1>cpn1>
        <cpn2>cpn2>
    div>
    <script src="../js/vue.js">script>
    <script>
        //1.全局组件注册的语法糖
        //1.创建组件构造器
        //const cpn1=Vue.extend()

        //2.注册组件
        Vue.component("cpn1", {
       
            template: `
            

我是标题1

我是内容,哈哈哈哈

`
}) //2.注册局部组件的语法糖 const app = new Vue({ el: "#app", data: { message: "你好啊" }, components: { "cpn2": { template: `

我是标题2

我是内容,hhehe1

`
} } })
script>



四、模板的分离写法

  • 刚才,我们通过语法糖简化了Vue组件的注册过程,另外还有一个的写法比较麻烦,就是template模板写法
  • 如果我们能将其中的HTML分离出来写,然后挂载到对应的组件上,必然结构会变得非常清晰
  • Vue提供了两种方案来定义HTML模板内容:
  • 使用 --> <template id="cpn"> <div> <h2>我是标题h2> <p>我是内容,呵呵呵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>



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

    • 组件是一个单独功能模块的封装:
    • 这个模块有属于自己的HTML模板,也应该有属性自己的数据data
    • 组件中的数据是保存在哪里呢?顶层的Vue实例中吗?
    • 我们先来测试一下,组件中能不能直接访问Vue实例中的data

    解析:组件去访问message,message定义在Vue,我们发现最终并没有显示结果
    结论:组件是不能直接访问Vue实例中的data数据

    vue.js学习笔记六_第4张图片



    六、组件数据的存放

    • 组件自己的数据存放在哪里呢?
    • 组件对象也有一个data属性(也可以有methods等属性,下面我们会用到)
    • 只是这个data属性必须是一个函数
    • 而且这个函数返回一个对象,对象内部保存着数据
        <div id="app">
            <cpn>cpn>
            <cpn>cpn>
            <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: "#app",
                data() {
           
                    return {
           
                        title: "abc"
                    }
                }
            })
            const app = new Vue({
           
                el: "#app",
                data: {
           
                    message: "你好啊",
                }
            })
        script>
    

    vue.js学习笔记六_第5张图片

    vue.js学习笔记六_第6张图片

    七、为什么data是一个函数呢?

    • 为什么data在组件中必须是一个函数呢?
    • 首先,如果不是一个函数,Vue直接就会报错
    • 其次,原因是在于Vue让每个组件对象都返回一个新的对象,因为如果是同一个对象的,组件在多次使用后会相互影响
        
        <div id="app">
            <cpn>cpn>
            <cpn>cpn>
            <cpn>cpn>
        div>
        <template id="cpn">
          <div>
            <h2>当前计数:{
        {counter}}h2>
            <button @click="increment">+button>
            <button @click="decrement">-button>
          div>
        template>
    
        <script src="../js/vue.js">script>
        <script>
            //1.注册组件
            const obj = {
           
                counter: 0
            }
            Vue.component("cpn", {
           
                template: "#cpn",
                // data() {
           
                //     return {
           
                //         counter: 0
                //     }
                // },
                data() {
           
                    return obj
                },
                methods: {
           
                    increment() {
           
                        this.counter++
                    },
                    decrement() {
           
                        this.counter--
                    }
                }
            })
            const app = new Vue({
           
                el: '#app',
                data: {
           
                    message: '你好啊'
                }
            })
        script>
    
        <script>
            // const obj = {
           
            //   name: 'why',
            //   age: 18
            // }
            //
            // function abc() {
           
            //   return obj
            // }
            //
            // let obj1 = abc()
            // let obj2 = abc()
            // let obj3 = abc()
            //
            // obj1.name = 'kobe'
            // console.log(obj2);
            // console.log(obj3);
        script>
    

    vue.js学习笔记六_第7张图片



    八、父子组件的通信

    • 在上一个小节中,我们提到了子组件是不能引用父组件或者Vue实例的数据的
    • 但是,在开发中,往往一些数据确实需要从上层传递到下层:
    • 比如在一个页面中,我们从服务器请求到了很多的数据
    • 其中一部分数据,并非是我们整个页面的大组件来展示的,而是需要下面的子组件进行展示
    • 这个时候,并不会让子组件再次发送一个网络请求,而是直接让大组件(父组件)将数据传递给小组件(子组件)

    vue.js学习笔记六_第8张图片

    • 如何进行父子组件间的通信呢?
    • 通过props向子组件传递数据
    • 通过事件向父组件发送信息

    在下面的代码中,会将Vue实例当做父组件,并且其中包含子组件来简化代码
    真实的开发中,Vue实例和子组件的通信父组件和子组件的通信过程是一样的



    九、props基本用法

    • 在组件中,使用选项props来声明需要从父级接收到的数据
    • props的值有两种方式:
    • 方式一:字符串数组,数组中的字符串就是传递时的名称
    • 方式二:对象,对象可以设置传递时的类型,也可以设置默认值等
    • 我们先来看一个最简单的props传递

    vue.js学习笔记六_第9张图片



    十、props数据验证

    • 在前面,我们的props选项是使用一个数组
    • 除了数组之外,我们也可以使用对象,当需要对props进行类型等验证时,就需要对象写法了
    • 验证都支持哪些数据类型呢?
      String
      Number
      Boolean
      Array
      Object
      Date
      Function
      Symbol
       <script>
            Vue.component("my-component", {
           
                props: {
           
                    //基础的类型检查(`null`匹配任何类型)
                    propA: Number,
                    //多个可能的类型
                    propB: [String, Number],
                    //必填的字符串
                    propC: {
           
                        type: String,
                        required: true
                    },
                    //带有默认值的数字
                    propD: {
           
                        type: Number,
                        default: 100
                    },
                    //带有默认值的对象
                    propE: {
           
                        type: Object,
                        //对象或数组默认值必须从一个工厂函数获取
                        default: function() {
           
                            return {
           
                                message: "hello"
                            }
                        }
                    },
                    //自定义验证函数
                    propF: {
           
                        validator: function(value) {
           
                            //这个值必须匹配下列字符串中的一个
                            return ["success", "warning", "danger"].indexOf(value) !== -1
                        }
                    }
                }
            })
        script>
    
    • 当我们有自定义构造函数时,验证也支持自定义的类型
    <script>
            function Person(firstName, lastName) {
           
                this.firstName = firstName;
                this.lastName = lastName
            }
            Vue.component("blog-post", {
           
                props: {
           
                    author: Person
                }
            })
        script>
    



    十一、子级向父级传递

    • props用于父组件向子组件传递数据,还有一种比较常见的是子组件传递数据或事件到父组件中
    • 这个时候,我们需要使用自定义事件来完成
    • 什么时候需要自定义事件呢?
    • 当子组件需要向父组件传递数据时,就要用到自定义事件了
    • 自定义事件的流程:
    • 在子组件中,通过$emit()来触发事件
    • 在父组件中,通过v-on来监听子组件事件



    • 我们来看一个简单的例子
    • 之前做过的那个两个按钮+1和-1,点击后修改counter
    • 整个操作的过程还是在子组件中完成,但是之后的展示交给父组件
    • 这样,我们就需要将子组件中的counter,传给父组件的某个属性,比如total

    vue.js学习笔记六_第10张图片

      
        <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: 'aaa',
                            name: '热门推荐'
                        }, {
           
                            id: 'bbb',
                            name: '手机数码'
                        }, {
           
                            id: 'ccc',
                            name: '家用家电'
                        }, {
           
                            id: 'ddd',
                            name: '电脑办公'
                        }, ]
                    }
                },
                methods: {
           
                    btnClick(item) {
           
                        // 发射事件: 自定义事件
                        this.$emit('item-click', item)
                    }
                }
            }
    
            // 2.父组件
            const app = new Vue({
           
                el: '#app',
                data: {
           
                    message: '你好啊'
                },
                components: {
           
                    cpn
                },
                methods: {
           
                    cpnClick(item) {
           
                        console.log('cpnClick', item);
                    }
                }
            })
        script>
    
    

你可能感兴趣的:(JavaScript,vue,学习笔记,vue,js)