• vue组件传值


    1.父组件向子组件传值

    //- 父组件发送的形式是以属性的形式绑定值到子组件身上。
    //- 然后子组件用属性props接收
    
        <div id="app">
            <menu-item title='来自父组件的值'></menu-item>  //给子组件传入一个静态的值
            //2.需要动态的数据的时候 需要属性绑定的形式设置 此时 ptitle  来自父组件data 中的数据 .  传的值可以是数字、对象、数组等
            <menu-item :title='ptitle' content='hello'></menu-item>
        </div>
        <script type="text/javascript">
          Vue.component('menu-item', {   //menu-item   为  子组件
            props: ['title', 'content'],  // 3、 子组件用属性props接收父组件传递过来的数据  
            data: function() {
              return { msg: '子组件本身的数据'}
            },
            template: '<div>{{msg + "----" + title + "-----" + content}}</div>'
          });
          var vm = new Vue({
            el: '#app',
            data: {
              pmsg: '父组件中内容',
              ptitle: '动态绑定属性'
            }  });
        </script>
    

    2.子组件向父组件传值

    // 子组件用`$emit()`触发事件   // 父组件用v-on 监听子组件的事件
    // `$emit()`  第一个参数为 自定义的事件名称     第二个参数为需要传递的数据
    
        <div id="app">
          <div :style='{fontSize: fontSize + "px"}'>{{pmsg}}</div>
            <!--父组件用v-on 监听子组件的事件  这里 enlarge-text  是从 $emit 中的第一个参数对应   handle 为对应的事件处理函数-->		
          <menu-item :parr='parr' @enlarge-text='handle($event)'></menu-item>
        </div>
        <script type="text/javascript" src="js/vue.js"></script>
        <script type="text/javascript">
          Vue.component('menu-item', {  //子组件向父组件传值-携带参数
            props: ['parr'],
            template: `
              <div>
                <ul><li :key='index' v-for='(item,index) in parr'>{{item}}</li></ul>
                  ###  1、子组件用$emit()触发事件
                  ### 第一个参数为 自定义的事件名称   第二个参数为需要传递的数据  
                <button @click='$emit("enlarge-text", 5)'>扩大父组件中字体大小</button>
              </div>` });
          var vm = new Vue({
            el: '#app',
            data: {
              pmsg: '父组件中内容',
              parr: ['apple','orange','banana'],
              fontSize: 10 },
            methods: {
              handle: function(val){
                this.fontSize += val;   // 扩大字体大小
              } } });
        </script>
    

    3.兄弟之间的传递

    //借助于事件中心   var hub = new Vue()
    - 传递数据方,通过一个事件触发hub.$emit(方法名,传递的数据)
    - 接收数据方,通过mounted(){} 钩子中  触发hub.$on()方法名
    - 销毁事件 通过hub.$off()方法名销毁之后无法进行传递数据
    
        <div id="app">
            <div>父组件</div>
            <div> <button @click='handle'>销毁事件</button></div>
            <test-tom></test-tom>
            <test-jerry></test-jerry>
        </div>
            <script type="text/javascript" src="js/vue.js"></script>
            <script type="text/javascript">
              var hub = new Vue();  //1、 提供事件中心  //兄弟组件之间数据传递
              Vue.component('test-tom', {  
                data: function(){
                  return {num: 0}},
                template: `<div> 
                  <div>TOM:{{num}}</div>
                    <div>
                      <button @click='handle'>点击</button>
                    </div> </div>`,
                methods: {
                  handle: function(){  
                  //2、传递数据方,通过一个事件触发hub.$emit(方法名,传递的数据)   触发兄弟组件的事件
                    hub.$emit('jerry-event', 2);
                  }},
                mounted: function() {
                 // 3、接收数据方,通过mounted(){} 钩子中  触发hub.$on(方法名
                  hub.$on('tom-event', (val) => {
                    this.num += val;
                  })}
              });
              Vue.component('test-jerry', {
                data: function(){
                  return {num: 0}  },
                template: `
                  <div> <div>JERRY:{{num}}</div>
                    <div>
                      <button @click='handle'>点击</button>
                    </div>  </div> `,
                methods: {
                  handle: function(){
                    //2、传递数据方,通过一个事件触发hub.$emit(方法名,传递的数据)   触发兄弟组件的事件
                    hub.$emit('tom-event', 1);
                  }  },
                mounted: function() {
                  // 3、接收数据方,通过mounted(){} 钩子中  触发hub.$on()方法名
                  hub.$on('jerry-event', (val) => {
                    this.num += val;
                  })}
              });
              var vm = new Vue({
                el: '#app',
                data: { },
                methods: {
                  handle: function(){
                    //4、销毁事件 通过hub.$off()方法名销毁之后无法进行传递数据  
                    hub.$off('tom-event');
                    hub.$off('jerry-event');
                  }}  });
            </script>
    

    4,provide 和 inject https://vue3js.cn/docs/zh/guide/component-provide-inject.html

    父组件可以作为其所有子组件的依赖项提供程序,而不管组件层次结构有多深。这个特性有两个部分:父组件有一个 provide 选项来提供数据,子组件有一个 inject 选项来开始使用这个数据。
    如果要将 todo-items 的长度直接传递给 TodoListStatistics,我们将把这个属性向下传递到层次结构:TodoList -> TodoListFooter -> TodoListStatistics。
    通过 provide/inject 方法,我们可以直接执行以下操作:

    const app = Vue.createApp({})
    app.component('todo-list', {
      data() {
        return {
          todos: ['Feed a cat', 'Buy tickets']
        }
      },
      provide: {
        user: 'John Doe'
      },
      template: `
        <div>
          {{ todos.length }}
          <!-- 模板的其余部分 -->
        </div>
      `
    })
    app.component('todo-list-statistics', {
      inject: ['user'],
      created() {
        console.log(`Injected property: ${this.user}`) // > 注入 property: John Doe
      }
    })
    

    要访问组件实例 property,我们需要将 provide 转换为返回对象的函数
    这使我们能够更安全地继续开发该组件,而不必担心可能会更改/删除子组件所依赖的某些内容。

    app.component('todo-list', {
      data() {
        return {
          todos: ['Feed a cat', 'Buy tickets']
        }
      },
      provide() {
        return {
          todoLength: this.todos.length
        }
      },
      template: `
        ...
      `
    })
    

    处理响应性
    在上面的例子中,如果我们更改了 todos 的列表,这个更改将不会反映在注入的 todoLength property 中
    如果我们想对祖先组件中的更改做出反应,我们需要为我们提供的 todoLength 分配一个组合式 API computed property:

    app.component('todo-list', {
      // ...
      provide() {
        return {
          todoLength: Vue.computed(() => this.todos.length)
        }
      }
    })
    

    5,props https://vue3js.cn/docs/zh/guide/component-props.html

    A,Prop 类型

    // 到这里,我们只看到了以字符串数组形式列出的 prop:
    props: ['title', 'likes', 'isPublished', 'commentIds', 'author']
    // 通常你希望每个 prop 都有指定的值类型。这时,你可以以对象形式列出 prop,这些 property 的名称和值分别是 prop 各自的名称和类型:
    props: {
      title: String,
      likes: Number,
      isPublished: Boolean,
      commentIds: Array,
      author: Object,
      callback: Function,
      contactsPromise: Promise // 或任何其他构造函数
    }
    

    B,传递静态或动态的 Prop

    //1. 你已经知道了可以像这样给 prop 传入一个静态的值:
    <blog-post title="My journey with Vue"></blog-post>
    
    //2. 你也知道 prop 可以通过 v-bind 或简写 : 动态赋值,例如:
    <!-- 动态赋予一个变量的值 -->
    <blog-post :title="post.title"></blog-post>
    <!-- 动态赋予一个复杂表达式的值 -->
    <blog-post :title="post.title + ' by ' + post.author.name"></blog-post>
    
    // 我们传入的值都是字符串类型的,但实际上任何类型的值都可以传给一个 prop。
    //3. 传入一个数字
    <!-- 即便 `42` 是静态的,我们仍然需要 `v-bind` 来告诉 Vue     -->
    <!-- 这是一个 JavaScript 表达式而不是一个字符串。             -->
    <blog-post :likes="42"></blog-post>
    <!-- 用一个变量进行动态赋值。-->
    <blog-post :likes="post.likes"></blog-post>
    
    //4. 传入一个布尔值
    <!-- 包含该 prop 没有值的情况在内,都意味着 `true`。          -->
    <blog-post is-published></blog-post>
    <!-- 即便 `false` 是静态的,我们仍然需要 `v-bind` 来告诉 Vue  -->
    <!-- 这是一个 JavaScript 表达式而不是一个字符串。             -->
    <blog-post :is-published="false"></blog-post>
    <!-- 用一个变量进行动态赋值。                                -->
    <blog-post :is-published="post.isPublished"></blog-post>
    
    // 5.传入一个数组
    <!-- 即便数组是静态的,我们仍然需要 `v-bind` 来告诉 Vue        -->
    <!-- 这是一个 JavaScript 表达式而不是一个字符串。             -->
    <blog-post :comment-ids="[234, 266, 273]"></blog-post>
    <!-- 用一个变量进行动态赋值。                                -->
    <blog-post :comment-ids="post.commentIds"></blog-post>
    
    // 6.传入一个对象
    <!-- 即便对象是静态的,我们仍然需要 `v-bind` 来告诉 Vue        -->
    <!-- 这是一个 JavaScript 表达式而不是一个字符串。             -->
    <blog-post
      :author="{
        name: 'Veronica',
        company: 'Veridian Dynamics'
      }"
    ></blog-post>
    <!-- 用一个变量进行动态赋值。                                 -->
    <blog-post :author="post.author"></blog-post>
    
    // 7.传入一个对象的所有 property
    <!-- 如果你想要将一个对象的所有 property 都作为 prop 传入,你可以使用不带参数的 v-bind (取代 v-bind:prop-name)。例如,对于一个给定的对象 post:-->
    <blog-post v-bind="post"></blog-post>
    post: {
      id: 1,
      title: 'My Journey with Vue'
    }
    

    C,单向数据流
    1,所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。
    这样会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。
    2,每次父级组件发生变更时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。
    如果你这样做了,Vue 会在浏览器的控制台中发出警告。
    3,这个 prop 用来传递一个初始值;这个子组件接下来希望将其作为一个本地的 prop 数据来使用。在这种情况下,最好定义一个本地的 data property 并将这个 prop 作为其初始值:
    4,这个 prop 以一种原始的值传入且需要进行转换。在这种情况下,最好使用这个 prop 的值来定义一个计算属性:
    5,注意在 JavaScript 中对象和数组是通过引用传入的,所以对于一个数组或对象类型的 prop 来说,在子组件中改变变更这个对象或数组本身将会影响到父组件的状态。

    D,Prop 验证
    为了定制 prop 的验证方式,你可以为 props 中的值提供一个带有验证需求的对象,而不是一个字符串数组

    app.component('my-component', {
      props: {
        // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
        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
          }
        },
        // 具有默认值的函数
        propG: {
          type: Function,
          // 与对象或数组默认值不同,这不是一个工厂函数 —— 这是一个用作默认值的函数
          default: function() {
            return 'Default function'
          }
        }
      }
    })
    

    type 可以是下列原生构造函数中的一个:
    String Number Boolean Array Object Date Function Symbol
    此外,type 还可以是一个自定义的构造函数,并且通过 instanceof 来进行检查确认。例如,给定下列现成的构造函数:

    function Person(firstName, lastName) {
      this.firstName = firstName
      this.lastName = lastName
    }
    // 用于验证 author prop 的值是否是通过 new Person 创建的
    app.component('blog-post', {
      props: {
        author: Person
      }
    })
    

    E,Prop 的大小写命名
    HTML 中的 attribute 名是大小写不敏感的,所以浏览器会把所有大写字符解释为小写字符。这意味着当你使用 DOM 中的模板时,
    camelCase (驼峰命名法) 的 prop 名需要使用其等价的 kebab-case (短横线分隔命名) 命名:

    const app = Vue.createApp({})
    app.component('blog-post', {
      // camelCase in JavaScript
      props: ['postTitle'],
      template: '<h3>{{ postTitle }}</h3>'
    })
    <!-- kebab-case in HTML -->
    <blog-post post-title="hello!"></blog-post>
    
  • 相关阅读:
    20159320《网络攻防实践》第4周教材学习总结
    20159320《网络攻防实践》第3周学习总结
    20159320 《网络攻防实践》第3周教材学习总结
    20159320 《网络攻防实践》第3周视频学习总结
    网络攻防学习心得一(20159320)学习小结
    Android 开发环境搭建以及编译
    iTOP-4412 开发板镜像的烧写
    Ubuntu 的基本操作
    iTOP-4412 平台基础软件的安装和学习
    几个关于嵌入式芯片的硬件系统
  • 原文地址:https://www.cnblogs.com/xm0328/p/14250042.html
Copyright © 2020-2023  润新知