vue组件传值

一、父子传值

1. props传递单个参数

· 父组件

<template>
  <div class="app-container">
    <Pagination :page="currentPage" @changePage="listenPageChange"/>
  </div>
</template>

<script>
import Pagination from './components/pagination';
export default &#123;
  components:&#123;
    Pagination
  &#125;,
  methods:&#123;
    listenPageChange(data)&#123;
      console.log(data);
    &#125;
  &#125;,
  data() &#123;
    return &#123;
      currentPage:1
  &#125;
&#125;;
</script>

·子组件

<template>
  <el-pagination
    @size-change="handleSizeChange"
    @current-change="handleCurrentChange"
    :current-page="page"
    :page-sizes="[100, 200, 300, 400]"
    :page-size="100"
    layout="total, sizes, prev, pager, next, jumper"
    :total="400"
  ></el-pagination>
</template>
<script>
export default &#123;
  props: ["page"],
  methods: &#123;
    handleSizeChange(val) &#123;
      this.pageOption.pageSize = val;
      this.listenOptionChange(this.pageOption);
    &#125;,
    handleCurrentChange(val) &#123;
      this.pageOption.page = val;
      this.listenOptionChange(this.pageOption);
    &#125;,
    listenOptionChange(datas) &#123;
       this.$emit("changePage", datas);
    &#125;
  &#125;
&#125;;
</script>

2. props传递对象

·父组件

<template>
  <div class="p-5">
    <Pagination :pageOption="pageOptions" />
  </div>
</template>

<script>
import Pagination from './components/pagination';

export default &#123;
  data () &#123;
    return &#123;
      pageOptions:&#123;
        page:1,
        pageSize:10,
        pageSizes:[10,20,30,40],
        total:40
      &#125;
    &#125;;
  &#125;,
  components: &#123;
    Pagination
  &#125;
&#125;

</script>

· 子组件

<template>
  <div>
    <el-pagination
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      :current-page="propOptions.page"
      :page-sizes="propOptions.pageSizes"
      :page-size="propOptions.pageSize"
      layout="total, sizes, prev, pager, next, jumper"
      :total="propOptions.total"
    ></el-pagination>
  </div>
</template>

<script>
export default &#123;
  props: ["page-option"],
  data() &#123;
    return &#123;
        propOptions:this.pageOption
    &#125;;
  &#125;,
  methods: &#123;
      handleSizeChange(val) &#123;
        this.propOptions.pageSize=val;
      &#125;,
      handleCurrentChange(val) &#123;
        this.propOptions.page=val;
      &#125;
  &#125;
&#125;;
</script>

二、兄弟组件传值

1. 借助事件车

· 自定义公用组件bus.js

自定义创建bus.js,兄弟组件共同引用此js,bus.js内容:

import Vue from 'vue';
var VueEvent=new Vue();
export default VueEvent;

· 兄弟组件a

<template>
  <div>
    <el-pagination
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      :current-page="propOptions.page"
      :page-sizes="propOptions.pageSizes"
      :page-size="propOptions.pageSize"
      layout="total, sizes, prev, pager, next, jumper"
      :total="propOptions.total"
    ></el-pagination>
  </div>
</template>

<script>
import Bus from './bus.js';
export default &#123;
  props: ["page-option"],
  data() &#123;
    return &#123;
        propOptions:this.pageOption
    &#125;;
  &#125;,
  methods: &#123;
      handleSizeChange(val) &#123;
        console.log(`每页 $&#123;val&#125; 条`);
      &#125;,
      handleCurrentChange(val) &#123;
        Bus.$emit('pageChangeTo',val);
      &#125;
  &#125;
&#125;;
</script>

· 兄弟组件b

<template>
  <div>
    <el-steps :active="pageOption.page" align-center>
      <el-step title="步骤1" description="这是一段很长很长很长的描述性文字"></el-step>
      <el-step title="步骤2" description="这是一段很长很长很长的描述性文字"></el-step>
      <el-step title="步骤3" description="这是一段很长很长很长的描述性文字"></el-step>
      <el-step title="步骤4" description="这是一段很长很长很长的描述性文字"></el-step>
    </el-steps>
  </div>
</template>

<script>
import Bus from "./bus.js";
export default &#123;
  data() &#123;
    return &#123;
      pageOption: &#123;
        page: 1
      &#125;
    &#125;;
  &#125;,
  mounted() &#123;
    this.listenPageChange();
  &#125;,
  methods: &#123;
    listenPageChange() &#123;
      Bus.$on("pageChangeTo", val => &#123;
        this.pageOption.page = val;
      &#125;);
    &#125;
  &#125;
&#125;;
</script>

三、Vuex传值

1. 开始使用vuex,新建一个 sotre文件夹,分开维护 actions mutations getters

网络不好

2. 在store/index.js文件中新建vuex 的store实例

import Vue from 'vue'
import Vuex from 'vuex'
import * as getters from './getters' // 导入响应的模块,*相当于引入了这个组件下所有导出的事例
import * as actions from './actions'
import * as mutations from './mutations'

Vue.use(Vuex)
// 首先声明一个需要全局维护的状态 state,比如 我这里举例的resturantName
const state = &#123;
    resturantName: '飞歌餐馆' // 默认值
    // id: xxx  如果还有全局状态也可以在这里添加
    // name:xxx
&#125;

// 注册上面引入的各大模块
const store = new Vuex.Store(&#123;
    state,    // 共同维护的一个状态,state里面可以是很多个全局状态
    getters,  // 获取数据并渲染
    actions,  // 数据的异步操作
    mutations  // 处理数据的唯一途径,state的改变或赋值只能在这里
&#125;)

export default store  // 导出store并在 main.js中引用注册。

3.actions

// 给action注册事件处理函数。当这个函数被触发时候,将状态提交到mutations中处理
export function modifyAName(&#123;commit&#125;, name) &#123; // commit 提交;name即为点击后传递过来的参数,此时是 'A餐馆'
    return commit ('modifyAName', name)
&#125;
export function modifyBName(&#123;commit&#125;, name) &#123;
    return commit ('modifyBName', name)
&#125;

// ES6精简写法
// export const modifyAName = (&#123;commit&#125;,name) => commit('modifyAName', name)

4.mutations

// 提交 mutations是更改Vuex状态的唯一合法方法
export const modifyAName = (state, name) => &#123; // A组件点击更改餐馆名称为 A餐馆
    state.resturantName = name // 把方法传递过来的参数,赋值给state中的resturantName
&#125;
export const modifyBName = (state, name) => &#123; // B组件点击更改餐馆名称为 B餐馆
    state.resturantName = name
&#125;

5.getters

// 获取最终的状态信息
export const resturantName = state => state.resturantName

6.在main.js中导入 store实例

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store'

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue(&#123;
  el: '#app',
  router,
  store,  // 这样就能全局使用vuex了
  components: &#123; App &#125;,
  template: '<App/>'
&#125;)

7.在组件A中,定义点击事件,点击 修改 餐馆的名称,并把餐馆的名称在事件中用参数进行传递。

…mapactions 和 …mapgetters都是vuex提供的语法糖,在底层已经封装好了,拿来就能用,简化了很多操作。

其中…mapActions([‘clickAFn’]) 相当于this.$store.dispatch(‘clickAFn’,{参数}),mapActions中只需要指定方法名即可,参数省略。

…mapGetters([‘resturantName’])相当于this.$store.getters.resturantName

<template>
  <div class="componentsA">
      <P class="title">组件A</P>
      <P class="titleName">餐馆名称:&#123;&#123;resturantName&#125;&#125;</P>
      <div>
            <!-- 点击修改 为 A 餐馆 -->
          <button class="btn" @click="modifyAName('A餐馆')">修改为A餐馆</button>
      </div>
      <div class="marTop">
          <button class="btn" @click="trunToB">跳转到B页面</button>
      </div>
  </div>
</template>

<script>
import &#123;mapActions, mapGetters&#125; from 'vuex'
export default &#123;
  name: 'A',
  data () &#123;
    return &#123;
    &#125;
  &#125;,
  methods:&#123;
      ...mapActions( // 语法糖
          ['modifyAName'] // 相当于this.$store.dispatch('modifyName'),提交这个方法
      ),
      trunToB () &#123;
          this.$router.push(&#123;path: '/componentsB'&#125;) // 路由跳转到B
      &#125;
  &#125;,
  computed: &#123;
      ...mapGetters(['resturantName']) // 动态计算属性,相当于this.$store.getters.resturantName
  &#125;
&#125;
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
    .title,.titleName&#123;
        color: blue;
        font-size: 20px;
    &#125;
    .btn&#123;
        width: 160px;
        height: 40px;
        background-color: blue;
        border: none;
        outline: none;
        color: #ffffff;
        border-radius: 4px;
    &#125;
    .marTop&#123;
        margin-top: 20px;
    &#125;
</style>

B组件同理

<template>
  <div class="componentsB">
      <P class="title">组件B</P>
      <P class="titleName">餐馆名称:&#123;&#123;resturantName&#125;&#125;</P>
      <div>
          <!-- 点击修改 为 B 餐馆 -->
          <button class="btn" @click="modifyBName('B餐馆')">修改为B餐馆</button>
      </div>
      <div class="marTop">
          <button class="btn" @click="trunToA">跳转到A页面</button>
      </div>
  </div>
</template>

<script>
import &#123;mapActions, mapGetters&#125; from 'vuex'
export default &#123;
  name: 'B',
  data () &#123;
    return &#123;
    &#125;
  &#125;,
  methods:&#123;
      ...mapActions( // 语法糖
          ['modifyBName'] // 相当于this.$store.dispatch('modifyName'),提交这个方法
      ),
      trunToA () &#123;
          this.$router.push(&#123;path: '/componentsA'&#125;) // 路由跳转到A
      &#125;
  &#125;,
  computed: &#123;
      ...mapGetters(['resturantName']) // 动态计算属性,相当于this.$store.getters.resturantName
  &#125;
&#125;
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
    .title,.titleName&#123;
        color: red;
        font-size: 20px;
    &#125;
    .btn&#123;
        width: 160px;
        height: 40px;
        background-color: red;
        border: none;
        outline: none;
        color: #ffffff;
        border-radius: 4px;
    &#125;
    .marTop&#123;
        margin-top: 20px;
    &#125;
</style>

参考文章:Vue通信、传值的多种方式,详解(都是干货)


  转载请注明: XMwarrior vue组件传值

 上一篇
优秀文章收录 优秀文章收录
安全 竞争激烈的互联网时代,是否需要注重一下WEB安全? -2019年05月15日 网络、浏览器基础 你不知道的浏览器页面渲染机制 -2019年04月02日 面试的信心来源于过硬的基础 -2018年02月23日 http 缓存小结 201
下一篇 
搭建hexo博客体会 搭建hexo博客体会
发现问题虽然此前也搭建过博客,并且尝试写过markdown博客文章,但也没有深入了解过hexo博客的搭建。一切只能从一个合并博客内容的想法开始…因为本人日前做过两个博客,XMwarrior跟xmsniper。 XMwarrior是纯手撸的
2019-04-18
  目录