推广

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

iseeyu3年前 (2024-02-21)推广154

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之间完成事件传递,那就要用到以下办法

  • 下载mitt库 npm 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

相关文章

西安企业做百度推广,一个月花三千和花三万到底差在哪?

4|最近跟几个西安的老板聊天,发现一个挺有意思的现象:同样做百度推广,有人一个月花三千块,询盘不断;有人一个月砸三万,水花都没见着。问他们区别在哪,大多数人说不清楚,只知道'钱花了,没效果'。 5| 6|百度推广这东西,说复杂也复杂,说简单也简单。核心就一件事:让你的潜在客户搜某个词的时候,你的信息...

我想当策划,大学应该选什么专业?

我想当策划,大学应该选什么专业?

学,广告,传播,公关,这些专业其实都可以。另外也可以学像汉语言文学,以及一些跟文学相关的一些专业,会对你找工作有帮助。但是,你想从事这个这份职业,除了专业的学习之外,更多的是,你要在上学的时候积极参与一些更营销策划相关的社会实践。比如说你可以做一些兼职,比如说帮别人去写稿,...

服装市场营销策略分析,“定位不慎满盘皆输”

服装市场营销策略分析,“定位不慎满盘皆输”

不同的区域需要不同的策略,而不同的营销策略需要不同的销售思路来配合。因此,在研究女装产品销售思路之前,最好先对于市场与营销策略做一次深入地了解。1.市场区域化(market segmentation):目标营销的第一步,是将整个市场拆分成若干个同性质的小市场。2.目标市场的...

晚间悦读丨你的思维方式,决定你的人生高度!

晚间悦读丨你的思维方式,决定你的人生高度!

越长大,越发现,能够决定你人生高度的,往往是你的认知层次。 你的认知在哪个层级,你的人生就处在什么状态。你认知的高度,决定了你人生的高度。 那如何才能升级方式、提升认知能力呢?可以从这三个方面做出改变。 NO. 1 改变态度 有人...

编写项目营销策划方案六大要点

编写项目营销策划方案六大要点

现在商业发展非常迅速,的需求非常的大,但是要做好营销策划是有一定难度的,我把自己做营销策划的一些体会在这里分享给朋友们。营销策划方案六大要点我们先说项目营销策划方案这个话题。大部分的营销策划人都是在企业里工作,大部分项目之初都是来源于一个想法,创始人、老板或者创始团队的一个...

【商场营销策划】如何进行商场营销策划?

【商场营销策划】如何进行商场营销策划?

商场是策划者们关注的永恒话题,那么究竟该如何作好商场营销策划呢?掌握以下这几点营销策略设计原则,至关重要!1.义利兼顾的原则。商场在获取利润的同时要充分考虑到消费者的合法利益和商场的长远利益。在作商场活动营销策略方案的时候应该将这一点作为首要的原则。对商场有利而对顾客不利的...

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

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