首页 > 其他分享 >Vue3的学习---4

Vue3的学习---4

时间:2024-08-09 21:40:31浏览次数:9  
标签:学习 Vue return template --- components Vue3 组件 data

4.Vue组件

4.1 初始Vue组件

4.1.1 根组件

根组件的主要作用是:

  1. 初始化应用程序。
  2. 提供全局的状态管理或配置。
  3. 作为其他组件的容器,构建整个应用程序的组件树。

通过根组件,开发者可以控制应用程序的整体结构和行为,确保各个部分能够协同工作。

<body>
    <div id="app"></div>

    <script src="../js/vue3.js"></script>
    <script>
        let app = Vue.createApp({})   // 创建一个Vue实例
        let vm = app.mount('#app')    // 根组件

        // Vue.createApp({}).mount('#app')
    </script>
</body>

4.1.2 全局组件

直接挂载到Vue实例上的组件就是一个全局组件。

全局组件的优点是:

  1. 方便使用:一旦注册,可以在任何地方直接使用,无需再次导入或声明。
  2. 减少重复代码:适用于需要在多个地方使用的通用组件。

全局组件的缺点是:

  1. 性能问题:全局组件在应用程序启动时就会被注册,可能会影响初始加载时间。
  2. 命名冲突:如果多个全局组件使用相同的名称,可能会导致冲突。
<body>
    <div id="app">
        <mycomponent></mycomponent>
    </div>

    <script src="../js/vue3.js"></script>
    <script>
        let app = Vue.createApp({})   // 创建一个Vue实例
        app.component('mycomponent', {      // 创建一个全局组件
            template: `<div>
                            <p>我是全局组件。{{ num }}</p>
                            <button @click="add">加</button>
                            <button @click="sub">减</button>
                        </div>`,
            data() {
                return {
                    num: 0
                }
            },
            methods: {
                add() {
                    this.num++
                },
                sub() {
                    this.num--
                }
            }

        })
        let vm = app.mount('#app')    
    </script>
</body>

4.1.3 局部组件

声明在根组件上的组件就是局部组件。局部组件只能应用在根组件中,而且局部组件只有在使用时才会消耗系统资源。

局部组件的主要特点包括:

  • 作用域有限:只在特定的范围内使用,不对外公开。
  • 提高可维护性:通过将功能拆分为更小的、独立的组件,使得代码更易于维护和理解。
  • 减少耦合:局部组件不依赖于全局状态或其他外部组件,从而减少了系统内部的耦合度
<body>
    <div id="app">
        <mycomponent></mycomponent>
    </div>

    <script src="../js/vue3.js"></script>
    <script>
        Vue.createApp({
            data() {
                return {}
            },
            components: {
                mycomponent: {
                    template: '<p>我是局部组件</p>'
                }
            }
        }).mount('#app')
    </script>
</body>

4.1.4 组件模板

<body>
    <div id="app">
        <mycomponent></mycomponent>
        <mycomponent></mycomponent>
    </div>

    <template id="mycomponent">
        <div>
            <h3>我是局部组件</h3>
            <p>hello world</p>
            {{ num }}
            <button @click="add">加</button>
        </div>
    </template>

    <script src="../js/vue3.js"></script>
    <script>
        Vue.createApp({
            data() {
                return {}
            },
            components: {
                mycomponent: {
                    template: '#mycomponent',
                    data() {
                        return {
                            num: 0
                        }
                    },
                    methods: {
                        add() {
                            this.num += 1
                        }
                    }
                }
            }
        }).mount('#app')
    </script>
</body>

4.2 父子组件

父子组件的特点:

  1. 嵌套关系:父组件在其模板或JSX中直接包含子组件。
  2. 数据传递:父组件可以通过属性(props)向子组件传递数据。
  3. 事件通信:子组件可以通过事件(events)向父组件传递信息或触发父组件的方法。
  4. 作用域隔离:子组件通常有自己独立的作用域和状态,不会直接影响父组件或其他兄弟组件的状态。
<body>
    <div id="app">
        <mycomponent></mycomponent>
    </div>

    <template id="mycomponent">
        <div>
            <p>我是父组件</p>
            <subcomponent></subcomponent>
        </div>
    </template>

    <script src="../js/vue3.js"></script>
    <script>
        Vue.createApp({
            data() {
                return {}
            },
            components: {
                mycomponent: {
                    template: '#mycomponent',
                    components: {
                        subcomponent: {
                            template: '<div>我是子组件</div>'
                        }
                    }
                }
            }
        }).mount('#app')
    </script>
</body>

4.3 组件之间的通信

4.3.1 子组件获取父组件数据

4.3.1.1 数据传递选项prop

prop是一种用于父组件向子组件传递数据的机制。通过prop,父组件可以将数据传递给子组件,子组件则可以通过定义props属性来接收这些数据。

<body>
    <div id="app">
        <mycomponent></mycomponent>
    </div>

    <template id="mycomponent">
        <div>
            <p>我是父组件</p>
            <subcomponent msg="hello world"></subcomponent>
        </div>
    </template>

    <script src="../js/vue3.js"></script>
    <script>
        Vue.createApp({
            data() {
                return {}
            },
            components: {
                mycomponent: {
                    template: '#mycomponent',
                    components: {
                        subcomponent: {
                            template: '<div>我是子组件,我接受父组件传值:{{ msg }}</div>',
                            props: ['msg']
                        }
                    }
                }
            }
        }).mount('#app')
    </script>
</body>
4.3.1.2 传值校验
<body>
    <div id="app">
        <mycomponent></mycomponent>
    </div>

    <template id="mycomponent">
        <div>
            <p>我是父组件</p>
            <subcomponent :msg="num" title="第二个参数"></subcomponent>
        </div>
    </template>

    <script src="../js/vue3.js"></script>
    <script>
        Vue.createApp({
            data() {
                return {
                    
                }
            },
            components: {
                mycomponent: {
                    template: '#mycomponent',
                    data() {
                        return {
                            num: 100
                        }
                    },
                    components: {
                        subcomponent: {
                            template: '<div>我是子组件,我接受父组件传值:{{ msg + 1 }},{{ title                               }}</div>',
                            props: {
                                msg: {
                                    // type: Number 表示msg必须是一个数字类型。
                                    type: Number
                                },
                                title: {
                                    // type: String 表示title必须是一个字符串类型。
                                    type: String,
                                    // required: true 表示title是必填项,父组件必须传递这个属性。
                                    required: true
                                }
                            }
                        }
                    }
                }
            }
        }).mount('#app')
    </script>
</body>

除了类型和必填项的校验,Vue.js还支持更多的校验规则,例如:

  • default:设置属性的默认值。
  • validator:自定义校验函数。
4.3.1.3单向数据流

数据只能从上到下单向流动,即从父组件流向子组件,而子组件不能直接修改父组件的状态。这种设计模式有助于提高代码的可维护性和可预测性,因为它减少了状态管理的复杂性。

<body>
    <div id="app">
        <mycomponent></mycomponent>
    </div>

    <template id="mycomponent">
        <div>
            <h3>我是父组件</h3>
            <subcomponent :msg="num"></subcomponent>
        </div>
    </template>

    <script src="../js/vue3.js"></script>
    <script>
        Vue.createApp({
            data() {
                return {
                    
                }
            },
            components: {
                mycomponent: {
                    template: '#mycomponent',
                    data() {
                        return {
                            num: 10
                        }
                    },
                    components: {
                        subcomponent: {
                            template: `<div>
                                我是子组件,我接受父组件传值:{{msg}}
                                <button @click="changeNum">改变父组件传值</button>
                            </div>`,
                            props: {
                                msg: {
                                    type: Number
                                }
                            },
                            methods: {
                                changeNum() {
                                    this.msg = 100
                                }
                            }
                        }
                    }
                }
            }
        }).mount('#app')
    </script>
</body>

当点击按钮想要改变数据时,控制台就会弹出警告,显示msg是只读,不可以修改。若是想修改传递过来的值,只需要将传过来的参数改为自己的参数:

 components: {
         subcomponent: {
             template: `<div>
                    我是子组件,我接受父组件传值:{{num}}
                    <button @click="changeNum">改变父组件传值</button>
             </div>`,
             props: {
				msg: {
					type: Number
				}
			},
			data() {
				return {
					num: this.msg
				}
			},
			methods: {
				changeNum() {
					this.num = 100
				}
			}
		}
	}

4.3.2 父组件获取子组件数据

父组件想要获取子组件的数据时,需要子组件通过$emit主动将自己的数据发送给父组件。

<body>
    <div id="app">
        <mycomponent></mycomponent>
    </div>
    <template id="mycomponent">
        <div>
            <p>我是父组件,我接收子组件传值:{{ChildValue}}</p>
            <subcomponent msg="hello world" @childmsg="get"></subcomponent>
        </div>
    </template>

    <script src="../js/vue3.js"></script>
    <script>
        Vue.createApp({
            data(){
                return {}
            },
            components: {
                mycomponent: {
                    template: '#mycomponent',
                    data() {
                        return {
                            ChildValue: ''
                        }
                    },
                    methods: {
                        get(value) {
                            this.ChildValue = value
                        }
                    },
                    components: {
                        subcomponent: {
                            template: `<div>
                                我是子组件,我接收父组件传值:{{msg}}
                                <button @click="send">给父组件传值</button>
                            </div>`,
                            props: ['msg'],
                            methods: {
                                send() {
                                    // this.$emit('自定义事件名称', 自定义事件参数)
                                    this.$emit('childmsg', '子组件给父组件传的值')
                                }
                            }
                        }
                    }
                }
            }
        }).mount('#app')
    </script>
</body>

4.3.3 多级组件通信

以下是多级组件通信的一个例子:

<body>
    <div id="app">
        <father></father>
    </div>
    <template id="father">
        <div>
            <p>我是父组件</p>
            <son msg="hello world"></son>
        </div>
    </template>

    <script src="../js/vue3.js"></script>
    <script>
        Vue.createApp({
            data() {
                return {}
            },
            components: {
                father: {
                    template: '#father',
                    components: {
                        son: {
                            template: `<div>
                                    我是子组件
                                    <grandson :msg="msg"></grandson>
                                </div>`,
                            props: ['msg'],
                            components: {
                                grandson: {
                                    template: `<div>
                                            我是孙子组件,接收父组件传值:{{ msg }}
                                        </div>`,
                                    props: ['msg']
                                }
                            }
                        }
                    }
                }
            }
        }).mount('#app')
    </script>
</body>
  • 上述实例中,父组件经过三级传递,将数据传递给孙子组件,太过繁琐。通过provideinject,可以简化跨层级组件之间的数据传递,提高代码的可维护性和可读性。
<body>
    <div id="app">
        <father></father>
    </div>
    <template id="father">
        <div>
            <p>我是父组件</p>
            <son></son>
        </div>
    </template>

    <script src="../js/vue3.js"></script>
    <script>
        Vue.createApp({
            data() {
                return {}
            },
            components: {
                father: {
                    template: '#father',
                    provide() {
                        return {
                            msg: 'hello world'
                        }
                    },
                    components: {
                        son: {
                            template: `<div>
                                    我是子组件
                                    <grandson></grandson>
                                </div>`,
                            components: {
                                grandson: {
                                    template: '<div>我是孙子组件,我接收父组件传值:{{ msg }}</div>',
                                    inject: ['msg']
                                }
                            }
                        }
                    }
                }
            }
        }).mount('#app')
    </script>
</body>

注意事项:

  1. 响应性:通过provide传递的数据默认不是响应式的。如果需要传递响应式数据,可以使用computed属性。
  2. 依赖注入provideinject主要用于非响应式场景,对于需要响应式数据传递的场景,建议使用Vuex或Pinia等状态管理库。

4.4 slot插槽

slot插槽用于在组件中定义可替换的内容。通过使用slot,父组件可以向子组件传递自定义的内容。

4.4.1 基本用法

<body>
    <div id="app">
        <father></father>
    </div>
    <template id="father">
        <div>
            <p>我是父组件</p>
            <son>
                <p>插槽的内容</p>
                <div>这还是插槽的内容</div>
            </son>
        </div>
    </template>

    <script src="../js/vue3.js"></script>
    <script>
        Vue.createApp({
            data() {
                return {}
            },
            components: {
                father: {
                    template: '#father',
                    components: {
                        son: {
                            template: `<div>
                                    <p>我是子组件</p>
                                    <slot></slot>
                                </div>`
                        }
                    }
                }
            }
        }).mount('#app')
    </script>
</body>

4.4.2 slot默认内容

  1. 作用域插槽

​ 作用域插槽允许父组件在子组件的插槽内容中访问子组件的数据。通过作用域插槽,子组件可以向父组件传递数据,父组件可以在插槽内容中使用这些数据。

官网中有这样一句话:父级模版里的所有内容否是在父级作用域中编译的,子级模板中的所有内容都是在子级作用域中编译的。即父组件当中的动态数据会先被解析为静态数据,再将数据传递给父组件,反之亦然。

<body>
    <div id="app">
        <father></father>
    </div>
    <template id="father">
        <div>
            <p>我是父组件</p>
            <son>
                <p>插槽的内容 {{num}}</p>
            </son>
        </div>
    </template>

    <script src="../js/vue3.js"></script>
    <script>
        Vue.createApp({
            data() {
                return {}
            },
            components: {
                father: {
                    template: '#father',
                    data() {
                        return {
                            num: 100
                        }
                    },
                    components: {
                        son: {
                            template: `<div>
                                    <p>我是子组件</p>
                                    <slot></slot>
                                </div>`
                        }
                    }
                }
            }
        }).mount('#app')
    </script>
</body>
  1. 默认内容

    插槽可以定义默认内容,当父组件没有提供插槽内容时,将显示默认内容。

<body>
    <div id="app">
        <father></father>
    </div>
    <template id="father">
        <div>
            <p>我是父组件</p>
            <son></son>
        </div>
    </template>

    <script src="../js/vue3.js"></script>
    <script>
        Vue.createApp({
            data() {
                return {}
            },
            components: {
                father: {
                    template: '#father',
                    components: {
                        son: {
                            template: `<div>
                                    <p>我是子组件</p>
                                    <slot>默认内容</slot>
                                </div>`
                        }
                    }
                }
            }
        }).mount('#app')
    </script>
</body>

4.4.3 具名插槽

通过具名插槽,你可以在组件中定义多个插槽,每个插槽可以有不同的名称,父组件可以根据名称向这些插槽提供内容。

<body>
    <div id="app">
        <father></father>
    </div>
    <template id="father">
        <div>
            <p>我是父组件</p>
            <son>
                <template v-slot:header>头部内容</template>
                <template v-slot:footer>尾部内容</template>
            </son>
        </div>
    </template>

    <script src="../js/vue3.js"></script>
    <script>
        Vue.createApp({
            data() {
                return {}
            },
            components: {
                father: {
                    template: '#father',
                    components: {
                        son: {
                            template: `<div>
                                    <slot name="header"></slot>
                                    <p>我是子组件</p>
                                    <slot name="footer"></slot>
                                </div>`
                        }
                    }
                }
            }
        }).mount('#app')
    </script>
</body>

总结:插槽是父子组件关系,插槽在子组件中展示位置以及展示内容的操作手段。父组件决定展示内容,子组件决定展示位置。

4.5 动态组件

动态组件允许你根据数据或条件动态地切换组件。你可以使用 <component> 元素并结合 is 属性来实现动态组件。

4.5.1 基本用法

<body>
    <div id="app">
        <father></father>
    </div>
    <template id="father">
        <div>
            <h3>父组件</h3>
            <!-- <son1 v-if="num === 0"></son1>
            <son2 v-if="num === 1"></son2> -->
            <component :is="name"></component>
            <button @click="change">点击切换子组件</button>
        </div>
    </template>

    <script src="../js/vue3.js"></script>
    <script>
        Vue.createApp({
            data() {
                return {}
            },
            components: {
                father: {
                    template: '#father',
                    data() {
                        return {
                            name: 'son1'
                        }
                    },
                    components: {
                        son1: {
                            template: '<div>子组件1</div>'
                        },
                        son2: {
                            template: '<div>子组件2</div>'
                        }
                    },
                    methods: {
                        change() {
                            if (this.name ==='son1') {
                                this.name ='son2'
                            } else {
                                this.name ='son1'
                            }
                        }
                    }
                }
            }
        }).mount('#app')
    </script>
</body>

4.5.2 保持组件状态

keep-alive ,用于在HTTP客户端和服务器之间保持持久连接。这意味着在单个TCP连接中可以发送多个HTTP请求和响应,而不需要为每个请求/响应对都建立和关闭一个新的连接。这可以显著提高性能,特别是在需要频繁通信的场景中。

以下是一些关于keep-alive的关键点:

  1. 减少延迟:通过减少连接的建立和关闭次数,可以减少延迟。
  2. 减少资源消耗:减少了服务器和客户端的资源消耗,因为不需要频繁地创建和销毁连接。
  3. 提高性能:在需要多次请求的场景中,性能可以得到显著提升。
<body>
    <div id="app">
        <father></father>
    </div>
    <template id="father">
        <div>
            <h3>父组件</h3>
            <!-- 这里使用了keep-alive包裹了子组件,可以缓存组件,提高渲染性能 -->
            <keep-alive>
                <component :is="name"></component>
            </keep-alive>
            <button @click="change">点击切换子组件</button>
        </div>
    </template>

    <script src="../js/vue3.js"></script>
    <script>
        Vue.createApp({
            data() {
                return {}
            },
            components: {
                father: {
                    template: '#father',
                    data() {
                        return {
                            name: 'son1'
                        }
                    },
                    components: {
                        son1: {
                            template: '<div>子组件1</div>'
                        },
                        son2: {
                            template: '<div>子组件2</div>'
                        }
                    },
                    methods: {
                        change() {
                            if (this.name === 'son1') {
                                this.name = 'son2'
                            } else {
                                this.name = 'son1'
                            }
                        }
                    }
                }
            }
        }).mount('#app')
    </script>
</body>

4.6 异步组件

异步组件是指在需要时才加载其代码和资源的组件。这种方式可以显著提高应用的性能,因为只有在组件实际需要被渲染时,才会去加载相关的代码和资源,而不是在应用初始加载时就全部加载。

异步组件的优势

  1. 性能优化:
    • 减少初始加载时间:只加载当前页面所需的组件,其他组件在需要时再加载。
    • 减轻服务器负担:按需加载组件,减少服务器一次性传输的数据量。
  2. 更好的用户体验:
    • 用户可以更快地看到页面内容,因为不需要等待所有组件都加载完成。
<body>
    <div id="app">
        <father></father>
    </div>
    <template id="father">
        <div>
            <h3>父组件</h3>
            <son1></son1>
            <son2></son2>
        </div>
    </template>

    <script src="../js/vue3.js"></script>
    <script>
        Vue.createApp({
            data() {
                return {}
            },
            components: {
                father: {
                    template: '#father',
                    components: {
                        son1: {
                            template: '<div>子组件1</div>'
                        },
                        // Vue.defineAsyncComponent 用于定义一个异步组件。这个方法接受一个工厂函数,该函数返回一个 Promise。
                        // (resolve, reject) => { ... }: 这是一个返回 Promise 的工厂函数。resolve 和 reject 是 Promise 的两个回调函数,分别用于成功和失败的情况。
                        // setTimeout(() => { ... }, 3000): 这是一个定时器函数,设置在 3000 毫秒(即 3 秒)后执行回调函数。这里模拟了一个异步操作,比如从服务器获取组件的代码。
                        // resolve({ template: '<div>子组件2</div>' }): 在定时器结束后,调用 resolve 函数并传递一个对象,该对象包含组件的模板。这意味着在 3 秒后,组件的模板会被加载并渲染。
                        son2: Vue.defineAsyncComponent((resolve, reject)=>{
                            setTimeout(()=>{
                                resolve({
                                    template: '<div>子组件2</div>'
                                })
                            },3000)
                        })
                    }
                }
            }
        }).mount('#app')
    </script>
</body>

标签:学习,Vue,return,template,---,components,Vue3,组件,data
From: https://www.cnblogs.com/yishengwanwuzhao/p/18351537

相关文章

  • C语言(五)-结构体
    C语言(五)-结构体1.结构体定义在编程的时候需要将不同的类型的数据组合成为一个整体,以便于引用。例如,一名学生有学号、姓名、性别、年龄、地址等属性,如果针对学生的学号、姓名、年龄等都单独定义一个变量,那么在有多名学生时,变量就难以分清。为此,C语言提供结构体来管理不同类......
  • Java学习回归
    先从第一个代码开始!点击查看代码//创建一个类,类的名字叫做HelloWorldpublicclassHelloWorld{//这是java公认的程序入口方法publicstaticvoidmain(String[]args){//调用系统的输出功能,将内容输出在控制台中System.out.println("你好......
  • Datawhale AI夏令营第四期 魔搭-AIGC方向 task01笔记
    DatawhaleAI夏令营第四期魔搭-AIGC方向task01笔记提示词提示词很重要,一般写法:主体描述,细节描述,修饰词,艺术风格,艺术家举个例子【promts】Beautifulandcutegirl,smiling,16yearsold,denimjacket,gradientbackground,softcolors,softlighting,cinematicedge......
  • Vue3项目创建及相关配置
    Vue是一种用于构建用户界面的JavaScript框架。它采用了一种称为MVVM(Model-View-ViewModel)的架构模式。MVVM是一种将用户界面与业务逻辑和数据分离的设计模式。它包括三个部分:Model(模型):表示应用程序的数据和业务逻辑。在Vue中,模型通常是一个JavaScript对象。View(视图):表示......
  • 深度学习张量数值计算
    张量的介绍PyTorch是一个Python深度学习框架,它将数据封装成张量(Tensor)来进行运算。PyTorch中的张量就是元素为同一种数据类型的多维矩阵。在PyTorch中,张量以"类"的形式封装起来,对张量的一些运算、处理的方法被封装在类中。张量基本运算基本运算中,包括add、sub、mul......
  • Java【案例2-5】 剪刀石头布小游戏
    案例介绍:“剪刀石头布”的游戏相信大家都不陌生,本案例要求编写一个剪刀石头布游戏的程序。程序启动后会随机生成1~3的随机数,分别代表剪刀、石头和布,玩家通过键盘输入剪刀、石头和布与电脑进行5轮的游戏,赢的次数多的一方为赢家。若五局皆为平局,则最终结果判为平局。案例思路: ......
  • Java【案例3-1】基于控制台的购书系统
    案例介绍:伴随互联网的蓬勃发展,网络购书系统作为电子商务的一种形式,正以其高效、低成本的优势逐步成为新兴的经营模式,人们已经不再满足互联网的用途仅仅局限于信息的浏览和发布,更渴望着能够充分享受互联网所带来的更多便利。网络购书系统正适应了当今社会快节奏地生活,使顾客足不......
  • Kubernetes-POD的QoS
    目录背景问题分析进一步排查问题原因Pod的QoS服务质量等级结论背景今天开发团队反馈,测试环境中部分业务功能无法正常使用。经过初步排查,发现某个业务Pod在一天内重启了10次,因此需要进一步调查原因。问题分析首先,我查看了Pod的日志,发现JVM并未抛出任何错误,服务却直接重启了。这......
  • 计算属性-监听属性,生命周期,组件,组件通信之父传子,组件通信之子传父,ref属性
    Ⅰ计算属性-监听属性【一】计算属性:computed#1本质是一个函数,但是当属性用 计算属性是基于它们的依赖进行缓存的计算属性只有在它的相关依赖发生改变时才会重新求值计算属性就像Python中的property,可以把方法/函数伪装成属性#2计算属性和普通函数的区别 ......
  • Ruoyi-Cloud 启动失败的坑,关于 selectConfigList
    刚才编辑了一堆,不知道为啥加了个英文单词,当前页面刷新自动搜索了单词,之前的内容总的就是现在都要会SpringCloud,高并发,几个真正懂高并发的,问题一般项目也没有啥高并发。自己之前的项目遇到过高并发,单体服务Tomcat最大连接数在那摆着设置再高没有用,打开后台一看OOM一直跳,重......