vue-组件传值

作者: 云高风轻 | 来源:发表于2021-07-03 10:36 被阅读0次

    1.前言

    组件传值 不管 vue 还是react 亦或某个框架都是重点
    记得有篇文章写了 ,其实有些情况 完全可以用 js自带 dataset来传值哦


    2. 引子

    每个组件只能访问组件内部的 data数据源,要想访问其他组件就需要传值

    <template>
    
      <div id="component_1">
        <h1>子组件内容</h1>
        <p>{{ hour | hourToSecond }}</p>
        <p>{{ componentHour }}小时</p>
        <p>{{ componentMsg }}</p>
        <button @click="changeHour">子组件修改</button>
      </div>
    </template>
    
    <script>
    export default {
      props: ["hour", "msg"],
      data: function () {
        return {
          componentHour: 10,
        //组件的data函数中,可以使用props中的数据赋初始值
          componentMsg: this.msg,
        };
      },
      methods: {
          changeHour(){
                  // 从父组件接收的传值是只读的,只能使用,不能修改。
                    // 也就是说vue中数据的传递是单向的,只能自上而下传递,子组件不能修改父组件的数据,这样保证了组件数据的安全性。这叫做vue组件的单向数据流。
              console.log(">>>>",this.hour)
              this.componentHour++
          }
      }
    };
    </script>
    
    <style lang="less" scoped>
    
    </style>
    

    子组件需要修改父组件数据可能是以下几个目的:

    1.父组件传递的值不能直接使用,需要进一步加工:例如父组件传递的是一种单位(米),子组件需要显示另一种单位(千米),这种情况可以使用过滤器解决。

    2.父组件传递的数据不能直接使用,需要进行一些计算,然后使用计算之后的结果,这种情况可以使用computed解决。

    3.从父组件接受的值只是一个初始值,子组件需要把这个值赋值一份为自己所用。这种情况,需要在子组件的data定义一个变量取接受这个初始值,需要修改时就修改子组件data中的这个变量,而不是修改父组件传递的props。


    3. 子组件 修改 父组件 数据

    思考子组件 为什么不能修改 例如避免数据流混乱 难以管理
    那父组件的数据 可以由父组件自己改变 ,咋改变呢写个函数 ,
    好 那就在父组件写个 改变函数

    这是父组件的 函数哦

     changeCount(count) {
          this.totalPrice = this.price * count;
        },
    

    接着分析 ,父组件可以通过 自己定义的修改函数 修改自己内部的数据
    嘿嘿 如果 子组件可以调用 父组件的这个修改函数不就哦了
    那问题来了怎么传 函数呢 js里面 函数本身也是一种数据类型,那就按照正常的传法传嘛
    使用子组件的时候 绑定 属性 传值为函数的名字就可以
    :cb="changeCount"

    <p>单价:{{ price }}</p>
          <p>总价:{{ totalPrice }}</p>
          <Component-Emit :cb="changeCount"></Component-Emit>
          <hr />
    

    子组件当然需要 接受下父组件的 传参嘛
    props:["cb"] 少不了
    子组件 内部 来个按钮 绑定自己的事件函数
    在函数里面调用这个 cb就行了嘛 ,就当个正常的变量来使用

    <template>
      <div id="component_2">
        <span>商品数量</span>
        <button @click="add">{{ count }} +</button>
      </div>
    </template>
    
    <script>
    export default {
      props: ["cb"],
      data: function () {
        return {
            count:1,
        };
      },
      methods: {
          add(){
              this.count++
                // 方式一:使用父组件属性传值,得到函数  
               // 回调函
              this.cb(this.count)
          }
      },
    };
    </script>
    
    <style scoped>
    </style>
    

    这里其实 属性应该加个验证更好

    props:{
    cb:{
    type:Function
    }
    }
    

    以上就是用原有的 思想解决问题

    重点是把 函数当做变量传给子组件 这种方法 非常常用哦
    vue 难道自己没有解决方案嘛 ,当然有 ,一起玩下


    4. 事件触发

    这里默认你已经了解 emit,
    其实不了解也无妨 ,能看懂 哈哈
    我们采用倒推的方法来玩吧
    先看我们下边的代码
    写法类比回调函数 就是上面的写法
    @get-count 其实也能猜出来 就是 自定义一个事件 事件名是 get-count 类似 @click

    <p>单价:{{ price }}</p>
          <p>总价:{{ totalPrice }}</p>
          <Component-Emit :cb="changeCount" @get-count="change"></Component-Emit>
          <hr />
    

    change就是父组件的方法

    methods:{
     change(a, b) {
          this.totalPrice = this.price * a + b;
        },
    

    那子组件怎么写呢

    核心是

    this.$emit("get-count",this.count,"¥")
    

    参数1是事件名 和 父组件传参 绑定的保持一致
    后续 可以根据需要 写很多参数

    <template>
      <div id="component_2">
        <span>商品数量</span>
        <button @click="add">{{ count }} +</button>
        <button @click="duce">{{ count }} +</button>
    
      </div>
    </template>
    
    <script>
    export default {
      props: ["cb"],
      data: function () {
        return {
            count:1,
        };
      },
      methods: {
          add(){
              this.count++
                // 方式一:使用父组件属性传值,得到函数  
               // 回调函
              this.cb(this.count)
          },
          duce(){
            // 方式二: 发射事件:参数1:事件名 参数2及以上是要传递的参数  
              this.count --
              this.$emit("get-count",this.count,"¥")
          }
      },
    };
    </script>
    
    <style scoped>
    </style>
    

    5.简单写个 分页案例

    简单的分页组件

    <template>
      <div id="pageContainer">
          <button @click="prevPage">上一页</button>
          <span>{{page}}</span>
          <button @click="nextPage">下一页</button>
      </div>
    </template>
    
    <script>
    export default {
        props: ["page","cb"],
        methods:{
            prevPage(){
                console.log("----")
                this.cb("prev")
            },
            nextPage(){
        // $emit方法只能给父组件发射事件,父组件的父组件不能接收到这个事件。
                this.$emit("get-page","next")
            }
        }
    }
    </script>
    
    <style scoped>
    
    </style>
    

    分页组件的使用

      <p>父标签 获取到 page信息:{{ page }}</p>
          <Component-Page
            :page="page"
            :cb="changePage"
            @get-page="changePage"
          ></Component-Page>
    

    6. 分页案例 v-model 实现

    page.vue

    <template>
      <div>
            <button @click="prevClick()">上一页</button>
            <span>当前页:{{value}}</span>
            <button @click="nextClick()">下一页</button>
      </div>
    </template>
    
    <script>
    //  v-model =  v-bind:value  + v-on:input
    export default {
        // 这里必须用 value
        // 因为 v-model 指令 绑定的是 value属性
        props:["value"],
        methods:{
            prevClick(){
                // 因为  v-model 绑定是   input事件
                // 所以 emit 发射/方法调用 的必须是  input事件
                this.$emit("input",this.value-1)
            },
            nextClick(){
                this.$emit("input",this.value+1)
            }
        }
    
    }
    </script>
    
    

    App.vue使用

          <Component-Model v-model="page1"></Component-Model>
    
    

    本质 v-model

       <!-- 本质 
        arguments[0] 子组件 $emit()方法的 事件参数
        -->
          <Component-Model :value="page1" @input="page1 = arguments[0]"
            >本质</Component-Model>
    

    参考资料

    vue-自定义事件


    初心

    我所有的文章都只是基于入门,初步的了解;是自己的知识体系梳理;
    如果能帮助到有缘人,非常的荣幸,一切为了部落的崛起;
    共勉

    相关文章

      网友评论

        本文标题:vue-组件传值

        本文链接:https://www.haomeiwen.com/subject/dasuultx.html