当前位置:   article > 正文

2.4Java全栈开发前端+后端(全栈工程师进阶之路)-前端框架VUE3-基础-Vue组件_java+vue技术栈体系图

java+vue技术栈体系图

初识Vue组件

Vue中的组件是页面中的一部分,通过层层拼装,最终形成了一个完整的组件。这也是目前前端最流行的开发方

式。下面是Vue3官方给出的一张图,通过图片能清楚的了解到什么是Vue中的组件。

图的左边是一个网页,网页分为了头部、左侧主体和右侧边栏。这时候你用组件的概念,就可以先把这个网页分为

三个大的组件,分别是头部、左侧和右侧。然后再根据每个大组件里的内容和功能,作更加详细的组件划分。

这样就可以把一个复杂的大页面,分解成一个个可以复用的小页面。

Vue中的组件可以分为:根组件、全局组件、局部组件。

根组件

  1. <div id="app">
  2. </div>
  3. <script src="../js/vue3.js"></script>
  4. <script>
  5. let app = Vue.createApp({}); //创建Vue实例
  6. let vm = app.mount('#app'); //根组件
  7. //Vue.createApp({}).mount('#app');
  8. </script>

Vue.createApp({}) 实际是建立一个Vue实例。

Vue.createApp({}).mount('#app') 将Vue的实例挂载到一个DOM节点上,就成为一个根组件。


全局组件

直接挂载到Vue实例上的组件就是一个全局组件。 全局组件可以应用在任何一个根组件中。

  1. <div id="app1">
  2. <h3>app1</h3>
  3. <mycomponent></mycomponent>
  4. <mycomponent></mycomponent>
  5. <mycomponent></mycomponent>
  6. </div>
  7. <div id="app2">
  8. <h3>app2</h3>
  9. <mycomponent></mycomponent>
  10. <mycomponent></mycomponent>
  11. <mycomponent></mycomponent>
  12. </div>
  13. <script src="../js/vue3.js"></script>
  14. <script>
  15. let app = Vue.createApp({}); //创建Vue实例
  16. //在Vue实例上创建一个mycomponent全局组件
  17. app.component('mycomponent',{
  18. template:'<p>我是全局组件</p>'
  19. });
  20. //全局组件可以应用在任何一个根组件中
  21. //app.mount('#app1');
  22. //let vm = app.mount('#app1'); //根组件
  23. let vm = app.mount('#app2'); //根组件
  24. </script>

使用vue.component()注册组件,需要提供2个参数:组件的标签名和组件构造器。组件构造器中的

template中设置组件的html模板。

组件中的内容

因为组件是可复用的vue实例,所以它们也能有data、computed、watch、methods以及生命周期钩子等。

  1. <div id="app">
  2. <mycomponent></mycomponent>
  3. </div>
  4. <script src="../js/vue3.js"></script>
  5. <script>
  6. let app = Vue.createApp({}); //创建Vue实例
  7. app.component('mycomponent',{
  8. template:`<div>
  9. <p>我是全局组件。 {{num}}</p>
  10. <button @click="add">加</button>
  11. <button @click="sub">减</button>
  12. </div>`,
  13. data(){
  14. return {
  15. num: 10
  16. }
  17. },
  18. methods:{
  19. add(){
  20. this.num++;
  21. },
  22. sub(){
  23. this.num--;
  24. }
  25. }
  26. });
  27. let vm = app.mount('#app'); //根组件
  28. </script>

组件模板的内容,可以写在一对反引号中(``),这样就可以不使用字符串拼接的形式了。

 

局部组件

全局组件可以在根组件的任何地方使用。

但一旦定义了全局组件,就会占用系统资源。因为即使是你并不使用某个组件,它仍然会被包含在最终的构建结果中。这就造成了用户下载的JavaScript的无谓的增加。

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

  1. <div id="app">
  2. <mycomponent></mycomponent>
  3. </div>
  4. <script src="../js/vue3.js"></script>
  5. <script>
  6. Vue.createApp({
  7. data(){
  8. return {}
  9. },
  10. components:{
  11. mycomponent:{
  12. template:`
  13. <div>
  14. <h3>我是局部组件</h3>
  15. {{num}} <button @click="add">加</button>
  16. </div>`,
  17. data(){
  18. return {
  19. num: 100
  20. }
  21. },
  22. methods:{
  23. add(){
  24. this.num++;
  25. }
  26. }
  27. }
  28. }
  29. }).mount('#app');
  30. </script>

组件模板

如果组件中的template内容过多,那么可以使用组件模板来声明template中的内容。

  1. <div id="app">
  2. <mycomponent></mycomponent>
  3. <!--组件之间相互独立-->
  4. <mycomponent></mycomponent>
  5. </div>
  6. <!-- 组件模板 -->
  7. <template id="mytemplate">
  8. <div>
  9. <p>我是局部组件</p>
  10. <div>hello world!</div>
  11. {{num}}
  12. <button @click="add"></button>
  13. </div>
  14. </template>
  15. <script src="../js/vue3.js"></script>
  16. <script>
  17. Vue.createApp({
  18. data(){
  19. return {}
  20. },
  21. components:{
  22. mycomponent:{
  23. template:'#mytemplate',
  24. data(){
  25. return {
  26. num: 100
  27. }
  28. },
  29. methods:{
  30. add(){
  31. this.num++;
  32. }
  33. }
  34. }
  35. }
  36. }).mount('#app');
  37. </script>

父子组件

当我们继续在组件中写组件,形成组件嵌套的时候,就是我们所说的父子组件了。

  1. <div id="app">
  2. <mycomponent></mycomponent>
  3. </div>
  4. <template id="mytemplate">
  5. <div>
  6. <p>我是父组件</p>
  7. <!-- 在父组件中使用子组件 -->
  8. <subcomponent></subcomponent>
  9. </div>
  10. </template>
  11. <script src="../js/vue3.js"></script>
  12. <script>
  13. Vue.createApp({
  14. data(){
  15. return {}
  16. },
  17. components:{
  18. mycomponent:{
  19. template:'#mytemplate',
  20. components:{ //声明子组件
  21. subcomponent:{
  22. template:`<div>我是子组件</div>`
  23. }
  24. }
  25. }
  26. }
  27. }).mount('#app');
  28. </script>

组件之间的通信

组件与组件之间是可以互相通信的。包括父子组件之间、兄弟组件之间等等,都可以互相通信。 下面只讨论父子组 件之间通信问题。

子组件获取父组件数据

数据传递选项prop

在vue中,组件实例的作用域是孤立的,默认情况下,父子组件的数据是不能共享的,也就是说,子组件是不能直接访问父组件的数据的。为此,vue给我们提供了一个数据传递的选项prop,用来将父组件的数据传递给子组件。

具体使用如下:

  1. <div id="app">
  2. <mycomponent></mycomponent>
  3. </div>
  4. <template id="mytemplate">
  5. <div>
  6. <p>我是父组件</p>
  7. <!-- 在父组件中使用子组件 -->
  8. <subcomponent :msg="id" ></subcomponent>
  9. </div>
  10. </template>
  11. <script src="../js/vue3.js"></script>
  12. <script>
  13. Vue.createApp({
  14. components:{
  15. mycomponent:{
  16. template:'#mytemplate',
  17. data(){
  18. return {
  19. id:100
  20. }
  21. },
  22. components:{ //声明子组件
  23. subcomponent:{
  24. template:`<div>我是子组件,我能获取父组件传递的数据:{{msg}}</div>`,
  25. props: ['msg']
  26. }
  27. }
  28. }
  29. }
  30. }).mount('#app');
  31. </script>

上面实例中,子组件获取父组件传递的数据的步骤为:

  1. 在子组件标签中,声明 msg 属性,属性值即为父组件向子组件传递的值。

  2. 在子组件中,使用props选项,声明接收父组件向子组件传递值的载体,即 ‘msg’ 。

  3. 子组件中就可以使用 msg 获取父组件向子组件传递的值了。

也可以使用 v-bind 绑定子组件标签属性,这样就可以将父组件data数据传递个子组件了。

  1. <div id="app">
  2. <mycomponent></mycomponent>
  3. </div>
  4. <template id="mytemplate">
  5. <div>
  6. <p>我是父组件</p>
  7. <!-- 在父组件中使用子组件 -->
  8. <subcomponent :msg="id" ></subcomponent>
  9. </div>
  10. </template>
  11. <script src="../js/vue3.js"></script>
  12. <script>
  13. Vue.createApp({
  14. components:{
  15. mycomponent:{
  16. template:'#mytemplate',
  17. data(){
  18. return {
  19. id:100
  20. }
  21. },
  22. components:{ //声明子组件
  23. subcomponent:{
  24. template:`<div>我是子组件,我能获取父组件传递的数据:{{msg}}</div>`,
  25. props: ['msg']
  26. }
  27. }
  28. }
  29. }
  30. }).mount('#app');
  31. </script>

传值校验

我们希望组件之间传递数据时,可以对数据的类型、是否必填等进行校验,这就是参数校验功能。

只要将 props 采用对象形式就可以实现参数校验:

  1. components:{ //声明子组件
  2. subcomponents:{
  3. template:`<div>我是子组件,我能获取父组件传递的数据:{{msg}}</div>`,
  4. props:{
  5. msg:{
  6. type:String,
  7. required: true
  8. }
  9. //或者简写
  10. //msg:String
  11. }
  12. }
  13. }

完整:

  1. <div id="app">
  2. <mycomponent></mycomponent>
  3. </div>
  4. <template id="mytemplate">
  5. <div>
  6. <p>我是父组件</p>
  7. <subcomponent :msg="id" ></subcomponent>
  8. </div>
  9. </template>
  10. <script src="../js/vue3.js"></script>
  11. <script>
  12. Vue.createApp({
  13. data(){
  14. return {}
  15. },
  16. components:{
  17. mycomponent:{
  18. template:'#mytemplate',
  19. data(){
  20. return {
  21. id:100
  22. }
  23. },
  24. components:{
  25. subcomponent:{
  26. template:`<div>我是子组件,我接受父组件传值:{{msg+1}} {{title}}</div>`,
  27. props: {
  28. msg:{
  29. type: Number
  30. },
  31. title:{
  32. type: String,
  33. required: true
  34. }
  35. }
  36. }
  37. }
  38. }
  39. }
  40. }).mount('#app');
  41. </script>

type:表示参数类型。值:String、Boolean、Array、Object、Function、Symbol

required:表示是否必填。值:true、false

 

单向数据流

父组件向子组件传递数据是单向的。也就是说:子组件可以接收并使用父组件传递过来的数据,但子组件不能修改此数据。

  1. <div id="app">
  2. <mycomponent></mycomponent>
  3. </div>
  4. <template id="mytemplate">
  5. <div>
  6. <p>我是父组件</p>
  7. <subcomponent :msg="id" ></subcomponent>
  8. </div>
  9. </template>
  10. <script src="../js/vue3.js"></script>
  11. <script>
  12. Vue.createApp({
  13. data(){
  14. return {}
  15. },
  16. components:{
  17. mycomponent:{
  18. template:'#mytemplate',
  19. data(){
  20. return {
  21. id:100
  22. }
  23. },
  24. components:{
  25. subcomponent:{
  26. template:`<div>
  27. 我是子组件,我接受父组件传值:{{num+1}} {{title}}
  28. <button @click="change">更改</button>
  29. </div>`,
  30. props: {
  31. msg:{
  32. type: Number
  33. },
  34. title:{
  35. type: String,
  36. required: true
  37. }
  38. },
  39. data(){
  40. return {
  41. num: this.msg
  42. }
  43. },
  44. methods:{
  45. change(){
  46. this.num = 50;
  47. }
  48. }
  49. }
  50. }
  51. }
  52. }
  53. }).mount('#app');
  54. </script>

这样做是为了防止子组件意外改变父组件的状态,从而导致父组件的行为异常。

  1. <script src="https://unpkg.com/vue@next"></script>
  2. <script>
  3. //...
  4. subcomponents:{
  5. template:`<div>
  6. 我是子组件,我能获取父组件传递的数据:{{msg}}
  7. <button @click="update">更改</button>
  8. </div>`,
  9. props:['msg'],
  10. methods: {
  11. update(){
  12. this.msg = 'haha';
  13. }
  14. }
  15. }
  16. //...
  17. </script>

当子组件试图修改父组件传递值时,就会出现警告,表示 msg 是只读的:

vue@next:1568 [Vue warn]: Attempting to mutate prop "msg". Props are readonly

父组件获取子组件数据

和上面不一样的是,父组件想要获取子组件的数据时,需要子组件通过emit主动将自己的数据发送给父组件。

  1. <div id="app">
  2. <mycomponent></mycomponent>
  3. </div>
  4. <template id="mytemplate">
  5. <div>
  6. <p>我是父组件,接受子组件传递的数据 {{childValue}}</p>
  7. <subcomponent msg="hello world!" @childmsg="get"></subcomponent>
  8. </div>
  9. </template>
  10. <script src="../js/vue3.js"></script>
  11. <script>
  12. Vue.createApp({
  13. data(){
  14. return {}
  15. },
  16. components:{
  17. mycomponent:{
  18. template:'#mytemplate',
  19. data(){
  20. return {
  21. childValue: ''
  22. }
  23. },
  24. methods:{
  25. get(value){
  26. this.childValue = value;
  27. }
  28. },
  29. components:{
  30. subcomponent:{
  31. template:`<div>
  32. 我是子组件,我接受父组件传值:{{msg}}<br>
  33. <button @click="send">给父组件传值</button>
  34. </div>`,
  35. props: ['msg'],
  36. methods:{
  37. send(){
  38. this.$emit('childmsg','这是子组件的数据');
  39. }
  40. }
  41. }
  42. }
  43. }
  44. }
  45. }).mount('#app');
  46. </script>

首先,我们需要在子组件中触发一个主动发送数据的事件。上面的例子中是一个点击事件send

其次,在点击事件中使用emit方法,这个emit接收两个参数:传递数据的事件和需要传递的数据。 这个传递数据的事件也是自定义的;

然后在父组件中引用子组件,并在引用的子组件中使用on监听上一步传递数据的事件。上面的例子中是childmsg;

最后在父组件中使用这个事件,这个事件带有一个参数,就是从子组件发送过来的数据。

多级组件通信

下面是一个多级组件之间的传值:

 

  1. <div id="app">
  2. <mycomponent></mycomponent>
  3. </div>
  4. <template id="mytemplate">
  5. <div>
  6. <p>我是父组件</p>
  7. <subcomponent msg="hello"></subcomponent>
  8. </div>
  9. </template>
  10. <script src="../js/vue3.js"></script>
  11. <script>
  12. Vue.createApp({
  13. data(){
  14. return {}
  15. },
  16. components:{
  17. mycomponent:{
  18. template:'#mytemplate',
  19. components:{
  20. subcomponent:{
  21. template:`<div>
  22. 我是子组件<br>
  23. <subsubcomponent :msg="msg"></subsubcomponent>
  24. </div>`,
  25. props:['msg'],
  26. components: {
  27. subsubcomponent:{
  28. template:`<div>我是孙子组件,接收爷爷组件传的值 {{msg}}</div>`,
  29. props:['msg'],
  30. }
  31. }
  32. }
  33. }
  34. }
  35. }
  36. }).mount('#app');
  37. </script>

上面实例中,父组件经过三级传递,将数据传递给孙子组件。

 

那么,如果此时有更多级组件嵌套,那么传递数据将非常麻烦。而且,父组件其实只想将数据传递给孙子组件,但

却不得不通过子组件接力传递。

所以,Vue提供了 provide/inject 来解决这个问题。

provide和inject

  1. <div id="app">
  2. <mycomponent></mycomponent>
  3. </div>
  4. <template id="mytemplate">
  5. <div>
  6. <p>我是父组件</p>
  7. <subcomponent></subcomponent>
  8. </div>
  9. </template>
  10. <script src="../js/vue3.js"></script>
  11. <script>
  12. Vue.createApp({
  13. data(){
  14. return {}
  15. },
  16. components:{
  17. mycomponent:{
  18. template:'#mytemplate',
  19. data(){
  20. return {
  21. score: 99
  22. }
  23. },
  24. provide(){
  25. return {
  26. num: this.score
  27. }
  28. },
  29. components:{ //声明子组件
  30. subcomponent:{
  31. template:`<div>
  32. 我是子组件<br>
  33. <subsubcomponent></subsubcomponent>
  34. </div>`,
  35. components: {
  36. subsubcomponent:{
  37. template:`<div>我是孙子组件,接收爷爷组件传的值 {{num}}</div>`,
  38. inject: ['num']
  39. }
  40. }
  41. }
  42. }
  43. }
  44. }
  45. }).mount('#app');
  46. </script>

上面实例中,使用 provide 来声明要传递的数据

在孙子组件中使用inject 来接收数据。这样,就可以越过子组件进行数据传递了。

slot插槽

父组件不但可以向子组件传递数据,还能向子组件分发内容(就是向子组件传递html内容)。

官方解释:Vue 实现了一套内容分发的 API,将 slot 元素作为承载分发内容的出口。

基本用法

 

  1. <div id="app">
  2. <mycomponent></mycomponent>
  3. </div>
  4. <template id="mytemplate">
  5. <div>
  6. <p>我是父组件</p>
  7. <subcomponent>
  8. <p>父组件向子组件分发的内容</p>
  9. </subcomponent>
  10. </div>
  11. </template>
  12. <script src="../js/vue3.js"></script>
  13. <script>
  14. Vue.createApp({
  15. data(){
  16. return {}
  17. },
  18. components:{
  19. mycomponent:{
  20. template:'#mytemplate',
  21. data(){
  22. return {
  23. num: 100
  24. }
  25. },
  26. components:{ //声明子组件
  27. subcomponent:{
  28. template:`<div>
  29. <p>我是子组件</p>
  30. <slot></slot>
  31. </div>`,
  32. }
  33. }
  34. }
  35. }
  36. }).mount('#app');
  37. </script>

在父组件中,使用子组件标签时,标签中将会添加需要分发给子组件的内容,也就是一段html代码。

在子组件中,就可以使用slot标签来显示父组件分发的内容。

值得注意的是,官网中有这样一句话:父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。

插槽作用域 

  1. <div id="app">
  2. <mycomponent></mycomponent>
  3. </div>
  4. <template id="mytemplate">
  5. <div>
  6. <p>我是父组件</p>
  7. <subcomponent>
  8. <p>这是插槽内容{{msg}}</p>
  9. </subcomponent>
  10. </div>
  11. </template>
  12. <script src="../js/vue3.js"></script>
  13. <script>
  14. Vue.createApp({
  15. data(){
  16. return {}
  17. },
  18. components:{
  19. mycomponent:{
  20. template:'#mytemplate',
  21. data(){
  22. return {
  23. msg: '父组件向子组件分发的内容'
  24. }
  25. },
  26. components:{ //声明子组件
  27. subcomponent:{
  28. template:`<div>
  29. <p>我是子组件</p>
  30. <slot></slot>
  31. </div>`,
  32. }
  33. }
  34. }
  35. }
  36. }).mount('#app');
  37. </script>

上面实例中,父组件会访问自己的 msg 数据去解析插槽内容。之后才分发给子组件。

并不是在子组件中去访问父组件的 msg 数据。

slot默认内容

如果父组件没有提供插槽内容,那么子组件可以在 slot标签中书写插槽的默认内容。

  1. <template id="mytemplate">
  2. <div>
  3. <subcomponent></subcomponent>
  4. </div>
  5. </template>
  6. subcomponent:{
  7. template:`<div>
  8. <p>我是子组件</p>
  9. <slot>插槽默认内容</slot>
  10. </div>`,
  11. }

当父组件没有提供插槽内容时,子组件将使用自己的默认内容显示。

 

具名插槽

有时,父组件需要分发多个内容,并且这些内容需要在子组件的不同位置进行显示。

比如:在实际应用中,一个组件的头部和尾部是共通的,那么头部和尾部就应该由父组件,统一分发给所有子组

件。此时可以使用具名插槽。

  1. <div id="app">
  2. <mycomponent></mycomponent>
  3. </div>
  4. <template id="mytemplate">
  5. <div>
  6. <p>我是父组件</p>
  7. <subcomponent>
  8. <template v-slot:header>
  9. <div>头部内容</div>
  10. </template>
  11. <template v-slot:footer>
  12. <div>尾部内容</div>
  13. </template>
  14. </subcomponent>
  15. </div>
  16. </template>
  17. <script src="../js/vue3.js"></script>
  18. <script>
  19. Vue.createApp({
  20. data(){
  21. return {}
  22. },
  23. components:{
  24. mycomponent:{
  25. template:'#mytemplate',
  26. data(){
  27. return {
  28. msg: '父组件向子组件分发的内容'
  29. }
  30. },
  31. components:{ //声明子组件
  32. subcomponent:{
  33. template:`<div>
  34. <slot name="header">
  35. <div>默认头部内容</div>
  36. </slot>
  37. <p>我是子组件</p>
  38. <slot name="footer">
  39. <div>默认尾部部内容</div>
  40. </slot>
  41. </div>`,
  42. }
  43. }
  44. }
  45. }
  46. }).mount('#app');
  47. </script>

在父组件中,使用 template 标签声明具名插槽,并取名。

在子组件中,通过插槽名决定内容的显示位置。

v-slot:header 可以简写为 #header。

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

决定展示位置。

动态组件

基本用法

有时,我们可能需要根据状态来决定使用那个组件,比如下面的例子:

 

  1. <div id="app">
  2. <mycomponent></mycomponent>
  3. </div>
  4. <template id="mytemplate">
  5. <div>
  6. <p>我是父组件</p>
  7. <!-- <subcomponent1 v-if="num==0"></subcomponent1>
  8. <subcomponent2 v-if="num==1"></subcomponent2> -->
  9. <component :is="comName"></component>
  10. <button @click="change">切换子组件</button>
  11. </div>
  12. </template>
  13. <script src="../js/vue3.js"></script>
  14. <script>
  15. Vue.createApp({
  16. data(){
  17. return {}
  18. },
  19. components:{
  20. mycomponent:{
  21. template:'#mytemplate',
  22. data(){
  23. return {
  24. comName:'subcomponent1'
  25. }
  26. },
  27. methods:{
  28. change(){
  29. if(this.comName=='subcomponent1'){
  30. this.comName='subcomponent2';
  31. }else{
  32. this.comName='subcomponent1';
  33. }
  34. }
  35. },
  36. components:{ //声明子组件
  37. subcomponent1:{
  38. template:`<div>我是子组件1</div>`
  39. },
  40. subcomponent2:{
  41. template:`<div>我是子组件2</div>`
  42. }
  43. }
  44. }
  45. }
  46. }).mount('#app');
  47. </script>

上面实例中,通过在子组件上使用 v-if 来判断 componentname 的状态,从而实现对子组件的切换使用。

但是上面的写法有些麻烦,所以Vue提供了动态组件用于实现上面的功能。

  1. <template id="mytemplate">
  2. <div>
  3. <component :is="comName"></component>
  4. <button @click="change">切换子组件</button>
  5. </div>
  6. </template>

使用 component 标签中的 is 属性,它会根据子组件名来动态的切换子组件的显示。

保持组件状态 keep-alive保持组件状态

上面实例中,当子组件切换时,子组件状态将会被重置(比如:文本框中输入的数据不能保持)。

vue提供了 keep-alive 标签让我们保持子组件状态。它能够将子组件状态缓存起来,在子组件显示时在恢复其状

态。

  1. <div id="app">
  2. <mycomponent></mycomponent>
  3. </div>
  4. <template id="mytemplate">
  5. <div>
  6. <p>我是父组件</p>
  7. <keep-alive>
  8. <component :is="comName"></component>
  9. </keep-alive>
  10. <button @click="change">切换子组件</button>
  11. </div>
  12. </template>
  13. <script src="../js/vue3.js"></script>
  14. <script>
  15. Vue.createApp({
  16. data(){
  17. return {}
  18. },
  19. components:{
  20. mycomponent:{
  21. template:'#mytemplate',
  22. data(){
  23. return {
  24. comName:'subcomponent1'
  25. }
  26. },
  27. methods:{
  28. change(){
  29. if(this.comName=='subcomponent1'){
  30. this.comName='subcomponent2';
  31. }else{
  32. this.comName='subcomponent1';
  33. }
  34. }
  35. },
  36. components:{
  37. subcomponent1:{
  38. template:`<div>我是子组件1 <input type="text"/></div>`
  39. },
  40. subcomponent2:{
  41. template:`<div>我是子组件2 <textarea></textarea></div>`
  42. }
  43. }
  44. }
  45. }
  46. }).mount('#app');
  47. </script>
  1. <template id="mytemplate">
  2. <div>
  3. <p>我是父组件</p>
  4. <keep-alive>
  5. <component :is="comName"></component>
  6. </keep-alive>
  7. <button @click="change">切换子组件</button>
  8. </div>
  9. </template>

当子组件切换时,子组件状态将会被保持。

异步组件

在实际开发中,一个应用可能会非常复杂。它可能会由很多组件组成。如果在应用启动时就加载所有组件,势必会造成效率低下。因此,正确的方式应该是按需加载。也就是先加载必要组件,然后根据需求在加载其它组件。

为了实现这个需求,Vue为我们提供了异步组件。

官网解释:在大型应用中,我们可能需要将应用分割成小一些的代码块,并且只在需要的时候才从服务器加载一个模块。为了简化,Vue 允许你以一个工厂函数的方式定义你的组件,这个工厂函数会异步解析你的组件定义。Vue只有在这个组件需要被渲染的时候才会触发该工厂函数,且会把结果缓存起来供未来重渲染

  1. <div id="app">
  2. <mycomponent></mycomponent>
  3. </div>
  4. <template id="mytemplate">
  5. <div>
  6. <p>我是父组件</p>
  7. <subcomponent1></subcomponent1>
  8. <subcomponent2></subcomponent2>
  9. </div>
  10. </template>
  11. <script src="../js/vue3.js"></script>
  12. <script>
  13. Vue.createApp({
  14. data(){
  15. return {}
  16. },
  17. components:{
  18. mycomponent:{
  19. template:'#mytemplate',
  20. data(){
  21. return {
  22. }
  23. },
  24. components:{
  25. subcomponent1:{
  26. template:`<div>我是子组件1</div>`
  27. },
  28. subcomponent2:Vue.defineAsyncComponent(()=>{
  29. return new Promise((resolve,reject)=>{
  30. setTimeout(()=>{
  31. resolve({
  32. template:'<div>我是子组件2</div>'
  33. })
  34. },3000);
  35. });
  36. })
  37. }
  38. }
  39. }
  40. }).mount('#app');
  41. </script>

上面代码中声明了两个子组件,一个是同步组件,一个是异步组件。

使用 Vue.defineAsyncComponent 来声明异步组件,并且它要求返回一个Promise对象。

代码运行后,先加载第一个子组件,3秒钟后加载第二个组件。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/喵喵爱编程/article/detail/892825
推荐阅读
相关标签
  

闽ICP备14008679号