推广

组件通信、插槽、动态组件、异步组件

iseeyu2年前 (2024-02-21)推广136

image.png

模板的两种写法

创建构造器&&注册组件

Vue.component('mycpn', {
      template: '#cpn'
    })
  • <script>标签
 <script type="text/x-template" id="cpn">
    <div>
      <h2>欢迎使用组件化开发</h2>
      <p>这里是内容</p>
      <p>哈哈哈</p>
    </div>
  </script>
  • <template>标签
 <template id="cpn">
        <div>
          <h2>欢迎使用组件化开发</h2>
      <p>这里是内容</p>
      <p>哈哈哈</p>
    </div>
    </template>

在模板里面添加数据

  • 模板里面的数据要存放在data函数当中
     <template id="cpn">
             <div>
          <h2>{{title}}</h2>
              <p>这里是内容</p>
              <p>哈哈哈</p>
            </div>
    </template>
    Vue.component('mycpn', {
      template: '#cpn',
      data() {
        return {
          title: '我是标题'
        }
      }
    })
  • 为什么data是一个函数,而不是一个对象? 因为Vue让每个组件对象都返回一个新的对象,因为如果是同一个对象的,组件在多次使用后会相互影响。

组件通信

父到子通信

image.png

  • props的三种写法
 const cpn = {
      template: '#npm',
      // 1.数组类型写法
      // props: ['cmessage']
      props: {
        /* 2.类型限制
        cmessage: String */
        // 3.提供一些默认值
        cmessage: {
          type: String,
          default: 'aaaa',
          //如果没有传值,默认为aaaa,且报错
          required: true
        },
        cmovies: {
          type: Array,
          //type:object默认值必须是函数返回,目的是防止不要智指向 一个对象
          default () {
            return [111]
          }
        }
      }
    }
  • 更多写法

    image.png

  • 关于props里面驼峰命名时传参的方式

    image.png


在父组件中的自定义标签中,添加标签属性,那么在子标签中添加 v-bind="$attrs",这样子组件中就会添加父组件自定义标签里的属性


子到父的通信
  • 子到父数据的传递需要使用自定义事件
 <div id="app">
    <mycpn @item-click='cClick'></mycpn>
  </div>
  <template id="npm">
        <div>
            <button v-for='item of students' v-on:click='btnClick(item)'>{{item.name}}</button>
        </div>
    </template>
  <script src="../../node_modules/vue/dist/vue.js"></script>
  <script>
    //定义子组件
    const cpn = {
      template: '#npm',
      data() {
        return {
          students: [{
            id: 1,
            name: 'guo'
          }, {
            id: 2,
            name: 'zhang'
          }, {
            id: 3,
            name: 'liu'
          }, {
            id: 4,
            name: 'li'
          }]
        }
      },
      methods: {
        btnClick(item) {
          this.$emit('item-click', item)
        }
      }
    }
    const app = new Vue({
      el: '#app',
      data: {

      },
      components: {
        mycpn: cpn
      },
      methods: {
        cclick(item) {
          console.log('cClick', item);
        }
      }
    })
  </script>

image.png

父子间双向通信

image.png

<body>
  <div id="app">
    <cpn :pnum1='num1' :pnum2='num2' @cchange1='fchange1' @cchange2='fchange2' @changenum1='changenum1'></cpn>
  </div>
  <template id="tem">
<div>
    <h1>props:{{pnum1}}</h1>
    <h1>data:{{cnum1}}</h1>
    <input type="text" v-bind:value='cnum1' @input='cinputchange1'>
    <h1>props:{{pnum2}}</h1>
    <h1>data:{{cnum2}}</h1>
    <input type="text" v-bind:value='cnum2' @input='cinputchange2'>
</div>
    </template>
  <script src="../../node_modules/vue/dist/vue.js"></script>
  <script>
    //子组件
    const cpn = {
        template: '#tem',
        props: {
          //只接受父级传递过来的参数,不能手动对其进行修改
          pnum1: Number,
          pnum2: Number
        },
        data() {
          //因为父级也会改变props里面的值,所以我们初始化出来一个变量,来接受父级的改变的变量
          return {
            cnum1: this.pnum1,
            cnum2: this.pnum2
          }
        },
        methods: {
          cinputchange1(event) {
            this.cnum1 = event.target.value
            this.$emit('cchange1', this.cnum1)
            this.cnum2 = this.cnum1 * 100
            this.$emit('changenum1', this.cnum1 * 100)
          },
          cinputchange2(event) {
            this.cnum2 = event.target.value
            this.$emit('cchange2', this.cnum2)
            this.cnum1 = this.cnum2 * 0.01
            this.$emit('changenum2', this.cnum1)
          }
        }
      }
      //父组件
    const app = new Vue({
      el: '#app',
      data: {
        num1: 1,
        num2: 2
      },
      components: {
        cpn
      },
      methods: {
        fchange1(pnum1) {
          this.num1 = pnum1 * 1
        },
        fchange2(pnum2) {
          this.num2 = pnum2 * 1
        },
        changenum1(num) {
          this.num2 = num
        },
        changenum1(num) {
          this.num1 = num
        }
      }
    })
  </script>
</body>

image.png

父子组件通信之$children(Vue3已经弃用了)

      methods: {
        btnClick() {
          //以数组的形式输出所有的组件
          console.log(this.$children);
          //调用子组件的函数
          this.$children[0].cfn()
            //由于组件之间可能会插入其他的组件,所以但用数组的形式选择相应的子模块可能会出问题
            //refs的用法
          console.log(this.$refs); //输出一个对象,对象里包含组件中所有包含ref的组件,
          console.log(this.$refs.aaa.message) //输出子数据

        }
      }

子访父之 $parent $root $el(可以拿到子组件整个模板)

  • 子组件应该尽量避免直接访问父组件的数据,因为这样耦合度太高了
  • 如果我们将子组件放在另外一个组件之内,很可能该父组件没有对应的属性,往往会引起问题
 const app = new Vue({
      el: '#app',
      data: {
        message: '我是父组件'
      },
      components: {
        cpn: {
          template: '#cpn',
          methods: {
            btnClick() {
              //访问父组件
              console.log(this.$parent);
              console.log(this.$parent.message);
              console.log(this.$root);
            }
          },
          components: {
            ccpn: {
              template: '#ccpn',
              methods: {
                cbtnClick() {
                  //访问根组件
                  console.log(this.$root.message);
                }
              }
            }
          }
        }
      }
    })
  • $refs能够拿到所有绑定ref的DOM元素

    image.png

非父子组件之间的访问(信息由高到低)

父组件添加新属性:

provide:{
name:"why"
age:18
}
  • provide里面的内容想要响应式处理需要用到computed,computed返回的是一个ref对象,需要取出其中的value来使用
  • 当前的this指向的是根组件本身,即this能够访问到data里面的值

    image.png

子组件也添加新属性

inject:["name","age"]

事件总线

image.png

在Vue2中

image.png

在Vue3中

如果想AB之间完成事件传递,那就要用到以下办法

  • 下载mittnpm install mitt
  • 封装一个工具

    image.png

  • 导入工具并在B里面定义事件
 btnClick() {
        console.log("about按钮的点击");
        emitter.emit("why", {name: "why", age: 18});
        // emitter.emit("kobe", {name: "kobe", age: 30});
      }
  • 在A里面监听函数
created() {
      emitter.on("why", (info) => {
        console.log("why:", info);
      });

      emitter.on("kobe", (info) => {
        console.log("kobe:", info);
      });
//所有的事件  type:事件名,info:传过来的信息
      emitter.on("*", (type, info) => {
        console.log("* listener:", type, info);
      })
    }
  • 取消事件

    image.png

插槽<slot></slot>

  • 模板中slot标签里没有内容的时候,可以通过自定义组件标签里添加内容插入
  • 模板中slot标签中有内容的时候,那就是默认插入的内容,若自定义组件标签里有内容,则会对其就行替换

    image.png

具名slot

  • 如果自定义模板标签里的内容没有写name属性,则会替换所有无名slot标签内容

    image.png

    第二种写法

  • v-slot:center 可以缩写成 #center

插槽作用域改变

image.png

 <div id="app">
    <cpn>
      <template slot-scope='info'>{{info.data.join(' - ')}}</template>
    </cpn>
  </div>
  <template id="cpn">
        <div>
            <slot :data='movies'></slot>
        </div>
    </template>

vue3中

image.png

动态组件

  • component 是内置组件,通过里面的is属性指定是哪个组件显示

    image.png

keep-alive

  • include:只有匹配到name属性的组件才会被缓存

  • exclude:匹配到任何之间的名称都不会被缓存

  • max:最多可以缓存的数目,超过这个数目之后,会把最久未使用的组件删除缓存

    image.png

在webpack打包的时候,将不同的函数分包

image.png

异步组件

  • 通过定义异步组件的方式引入组件,并注册组件之后再使用组件,那webpack在进行打包的时候会进行分包处理
  • 写法一:
  import Home from './Home.vue';
  const AsyncCategory = defineAsyncComponent(() => import("./AsyncCategory.vue"))
  • 写法二:
  const AsyncCategory = defineAsyncComponent({
    loader: () => import("./AsyncCategory.vue"),
    loadingComponent: Loading,
    // errorComponent,
    // 在显示loadingComponent组件之前, 等待多长时间
    delay: 2000,
    /**
     * err: 错误信息,
     * retry: 函数, 调用retry尝试重新加载
     * attempts: 记录尝试的次数
     */
    onError: function(err, retry, attempts) {

    }
  })

异步组件和Suspense

  • Suspense:内置的全局组件,它里面有两个插槽,一个名叫:default(默认显示),另一个是:fallback(default能显示就不会显示该组件)
  • 注册Suspense组件之后,使用组件,

    image.png

扫描二维码推送至手机访问。

版权声明:本文由西安泽虎代运营发布,如需转载请注明出处。

转载请注明出处https://www.0291.com.cn/post/57222.html

相关文章

抖音怎么申请MCN机构?需要什么资料和要求

抖音怎么申请MCN机构?需要什么资料和要求

  抖音MCN主要是负责达人资源储备与达人运营,依托于平台方的政策扶持与资本加持,为其提供专业的孵化管理服务。 这主要是因为现在很多抖音玩家被限流,没法接广告,或粉丝增长遇到瓶颈,遇到这种情况说明需要加MCN了。小编就和大家聊聊抖音怎么申请MCN机构。 如何申请抖音MCN机...

农副产品推广平台有哪些(突破200亿元)

农副产品推广平台有哪些(突破200亿元)

我们都知道,农产品的销售一直是我们日常生活中最大的问题。而在目前的市场环境下,电子商务已经成为了现在最热门的推广方式之一。但是电商平台种类繁多,让消费者难以抉择。那么对于农副产品推广平台有哪些? 1、叮咚买菜 叮咚买菜是一家集“生活服务、生鲜果蔬、家居百货、社区团购”等业务于一体的O2...

绝对地址和相对地址的概念

绝对地址和相对地址的概念

在电脑操作学习和互联网使用中,我们经常会接触绝对和相对地址的概念。这里,重点谈互联网上的,具体谈在做时,绝对地址和相对地址有什么区别? 绝对地址:互联网上的独立地址,在任何网站通过这个地址可以直接到达目标网页。包含主域名和目录地址。相对地址:相对于网站的地址,当域名改变时,相对地址的“绝对地址”也...

搜索引擎一般多长时间更新一次,SEO 多长时间有效果。

搜索引擎一般多长时间更新一次,SEO 多长时间有效果。

搜索引擎基本每天都更新网页数据库,隔两三天都会对每个关键词进行一次排名。一般情况下,对于具体的某个关键词,其搜索结果不会突然发现巨大的变动。我们很少看到某关键词的搜索结果前10位突然都换成其他的了,除非搜索引擎进行算法修改。但对于具体某一个网站,如果受惩罚或降权,可能一夜之间排名发生巨大变化。 的效...

直通车出价目标设置选哪个(直通车怎么调整出价)

直通车出价目标设置选哪个(直通车怎么调整出价)

进入直通车的后台,然后类目出价就可以对出价默认金额进行修改,需要做到的是设置好出价平台和分时段折扣比例。...

网站被降权后如何快速恢复。

网站被降权后如何快速恢复。

以前已经谈了很多关于网站被降权或者是被封杀的问题了,这种问题虽然说是很严重,但是也不是说无法恢复,一般造成降权或者是封杀的原因就那么几个,找清楚原因后对症下药就好了,所以今天就和大家具体的谈一下关于网站被降权后如何快速恢复的方法。 首先要做的就是找一个稳定的空间商,如果刚开始建站没有...

现在,非常期待与您的又一次邂逅

我们努力让每一部企业宣传片和抖音短视频成为商业大片