前言
在vue项目中,不可避免的会在不同组件之间进行传值 ,不同需求下有各式各样的传值方式。就比如说,兄弟组件传值,父子子父之间传值,路由传值,ref方式传值或者是共享状态(数据)等,一些花里胡哨的方式,都有各自使用场景且有可能不经常使用导致容易忘记,故总结记之,方便自己以后更好运用自如。
目录
[TOC]
使用props传值
- 简单的示例
父组件:
<template lang="html">
<div class="">
<h1>首页</h1>
<home1 :msg='str'></home1>
</div>
</template>
<script>
import home1 from './home1'
export default {
data(){
return {
str:'我是在父组件的数据通过props传递给子组件'
}
},
components: {
home1
}
}
</script>
<style>
</style>
子组件:
<template>
<div id="">
<h2>{{msg}}</h2>
</div>
</template>
<script>
export default {
props: ['msg'],
name: "",
data: () => ({
})
}
</script>
<style scoped>
</style>
小结:通过以上代码,就可以明显看出,在子组件vue实例声明props属性以及在父元素中子组件进行赋值操作,即可实现父子组件传值。值得注意的是,也可通过在子组件中定义一个函数,在父组件触发这个函数,也可达到父传子的效果。详情下料聊
- props实现子组件向父组件传值,其原理实现如上小结,实现时值得注意的是:
- 在父组件中,传值的是函数名,而不是函数的执行结果
- 在子组件中触发函数时机时:通过this.函数名取得父传子的函数,并传参(即是子向父传递的数据)执行。这样父可以拿到子的数据。
父组件代码如下:
<template lang="html">
<div class="">
<h1>首页</h1>
<home1 :fn='parent'></home1>
<!-- 来展示从子组件传来的值 -->
<h2>{{ num }}</h2>
</div>
</template>
<script>
import home1 from './home1'
export default {
data(){
return {
// 来保存从子组件传来的值
num:''
}
},
components: {
home1
},
methods: {
parent(data) {
// 如果子组件触发函数会调转到父组件来执行该函数,即把传递进来的参数赋值给vue实例中的data数据中的num变量中
this.num = data;
}
}
}
</script>
<style media="screen">
</style>
子组件代码如下:
<template>
<div id="">
<h2>hello</h2>
</div>
</template>
<script>
export default {
props: ['fn'],
name: "",
data: () => ({
str:'我是子组件里面的数据要通过props传递给父组件'
}),
mounted() {
//do something after mounting vue instance
// 在子组件渲染完毕时,触发从父组件传递过来的函数
this.fn(this.str)
}
}
</script>
<style scoped>
</style>
使用路由传值
路由传值:主要分为在同一路由下传值(同一组件)和不同路由跳转传值(不同组件),其中重要知识点有:
- 路由传参有两种情况:编程式传参和声明式传参,格式用法见下代码实例
- 通过this.$route.params.? 来接收路由参数(这一般存放小数据),而this.$route.query.?来接收存放在路由的数据,一般是存放大数据
- 当然如果是同一路由下传参,要配置路由如格式:
{name:'home',path:'/home/:id',component:Home},...
- 同一路由下传值实现代码如下:
<template lang="html">
<div class="">
<h1>首页</h1>
<!-- 点击路由链接向当前路由传递参数 -->
<!-- 1.声明式传参 -->
<router-link :to="{ name: 'home', params: { id: 'hello'}}">1</router-link>
<!-- 2.编程式参参 -->
<p @click='fn1'>2</p>
<!-- 点击按钮获取当前url路径的参数 -->
<button @click="fn" type="button" name="button">获取动态路由参数</button>
<h4>我是动态数据:{{num}}</h4>
<!-- 通过query中值获得数据 -->
<h5>{{num1.name}}</h5>
<h5>{{num1.age}}</h5>
</div>
</template>
<script>
// import home1 from './home1'
export default {
data(){
return {
num:'',
// 在路由的query对象存放大量数据方便存取
num1:''
}
},
methods: {
// 点击按钮获取当前url路径的参数的函数
fn() {
this.num = this.$route.params.id;
this.num1 = this.$route.query;
},
// 点击’2‘后,进行编程式路由跳转并传递参数
fn1() {
this.$router.push(
{name:'home',params:{id:'world'},query:{
name:'zhangsna',
age:23
}}
)
}
},
components: {
// home1
}
}
</script>
<style media="screen">
</style>
- 不同路由下实现传值:
跳转前路由组件代码如下:
<template lang="html">
<div class="">
<h1 @click='fn'>首页</h1>
</div>
</template>
<script>
export default {
data(){
return {
num:''
}
},
methods: {
fn(){
this.$router.push({
name:'car',
query:{
name:'xioahang',
age:23
}
})
}
}
}
</script>
<style media="screen">
</style>
调转后路由组件代码如下
<template lang="html">
<div class="car">
<h1>我的购物车</h1>
<h2>{{ msg.name }}</h2>
<h2>{{ msg.age }}</h2>
</div>
</template>
<script>
export default {
data() {
return {
msg:{}
}
},
created() {
//do something after creating vue instance
this.msg = this.$route.query
}
}
</script>
<style media="screen">
</style>
使用ref方式传值
尽管有props和events,但是仍然需要在JavaScript中直接访问子组件。为此可以使用ref为子组件指定一个索引ID。
值得注意的是:ref的属性所对应的属性值是一个固定值,不是一个变量。因为ref不是动态更新的
用法非常简单,示例如下:
父组件:
<template lang="html">
<div class="">
<h1>首页</h1>
<!-- 在子组件书写ref属性以及值 -->
<home1 ref='mark'></home1>
<!-- 在父组件中,测试从子组件拿到的值 -->
<h2>通过ref来拿到子组件的数据传递给 {{num}}</h2>
</div>
</template>
<script>
// 导入子组件
import home1 from './home1'
export default {
data(){
return {
num:''
}
},
methods: {
},
components: {
home1
},
mounted() {
// 向子组件拿到的数据赋值给父vue实例中的变量
this.num = this.$refs.mark.str;
// 在父组件中,测试从子组件拿到的函数
this.$refs.mark.fn();
}
}
</script>
<style media="screen">
</style>
子组件:
<template>
<div id="">
<h2>hello</h2>
</div>
</template>
<script>
export default {
name: "",
data: () => ({
str:'我是子组件里面的数据,父组件通过ref来向子组件拿值'
}),
methods: {
fn() {
console.log('我是子组件的方法,父组件可通过ref来拿到我这里的值!');
}
}
}
</script>
<style scoped>
</style>
使用BUS传值
BUS传值主要运用了events事件的原理。实现步骤如下:首先,在定义一个第三方的vue实例并导出,然后通过BUS.$on()来注册事件,其中里面的函数中this的指向格外注意,普通函数this指向BUS,而不是当前的vue实例,可使用es6的箭头函数,它的this指向当前的vue实例。最后在传值的那个组件,使用BUS.$emit()触发事件并传值,即可实现两个组件之间的传值。一般用于兄弟组件之间传值及父子子父之间传值等
以下实例通过BUS实现父子传值:
import Vue from 'vue'
export default new Vue()
<template lang="html">
<div class="">
<h1>首页</h1>
<home1></home1>
<h1>我是通过bus事件传递过来的值为:{{num}}</h1>
</div>
</template>
<script>
// 导入Busvue实例
import Bus from '../bus'
import home1 from './home1'
export default {
data(){
return {
num:''
}
},
methods: {
},
components: {
home1
},
created() {
Bus.$on('sendVal',(data) => {
this.num = data
});
}
}
</script>
<style media="screen">
</style>
<template>
<div id="">
<h2>hello</h2>
</div>
</template>
<script>
import Bus from '../bus'
export default {
name: "",
data: () => ({
str:'我是这个子组件中的数据'
}),
methods: {
fn() {
}
},
created() {
//do something after creating vue instance
Bus.$emit('sendVal',this.str)
}
}
</script>
<style scoped>
</style>
通过$parent,$children方法来拿值
通过$parent,$children方法调取层级关系的组件内的数据和方法,该方法的弊端,就是增强组件之间的耦合,不利于组件的复用
使用$parent,$children来进行父子子父之间传值
父组件代码:
<template lang="html">
<div class="">
<h1>首页</h1>
<home1></home1>
<p>{{num1}}</p>
</div>
</template>
<script>
import home1 from './home1'
export default {
data(){
return {
num:'我是父组件的数据',
num1:''
}
},
methods: {
parentFn(){
console.log('我是父组件的方法');
}
},
components: {
home1
},
mounted() {
// console.log(this.$children);
// 值得注意的是 this.$children 获取到是一个数组,并非是一个对象
this.num1 = this.$children[0].$data.str // 获取子组件的数据
this.$children[0].sonFn() // 获取子组件的方法
}
}
</script>
<style media="screen">
</style>
子组件代码:
<template>
<div id="">
<h2>hello</h2>
<h4>{{str1}}</h4>
</div>
</template>
<script>
export default {
name: "",
data: () => ({
str:'我是这个子组件中的数据',
str1:''
}),
methods: {
sonFn() {
console.log('我是子组件的方法');
}
},
created() {
//do something after creating vue instance
// 获取父组件的数据
this.str1 = this.$parent.num;
// 获取父组件的方法
this.$parent.parentFn()
}
}
</script>
<style scoped>
</style>
vue原型传值
vue原型同js对象有着的原型链,故向vue组件中存放值与方法,子组件即可通过原型链获取值与方法
import Vue from 'vue'
Vue.prototype.num = 'test prototype'
Vue .prototype.sayFn = function () { console.log('hello world!'); }
使用localStorage或sessionStorage存储
localStorage、sessionStorage以及cookie存储,都是js实现本地存储的方式 。实现方法如下:
保存数据:
- sessionStorage.setItem(key,value)
- localStorage.setItem(key,value)
读取数据:- var v = sessionStorage.getItem(key)
- var v = localStorage.getItem(key)
移除数据:- sessionStorage.removeItem(key)
- localStorage.removeItem(key)
清除数据:- sessionStorage.clear()
- localStorage.clear()
利用vue-x方式进行传值
vue-x是vue的共享状态(即数据)的模块,官网介绍为:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。
- 一个表示“单向数据流”理念的极简示意:
当我们的应用遇到多个组件共享状态时,单向数据流的简洁性很容易被破坏,故使用vuex如下图所示:
2.其中核心概念有:
* state:存放状态,即数据
* mutations:存放改变state数据的同步方法
* actions:存放改变state数据的异步方法
* getters:相当于计算属性,避免了直接向state数据取值
- 代码具体实现如下:
首先创建store实例
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state:{
// 共享状态
num:0
},
mutations:{
addNum(state,step){
state.num += step;
},
reduceNum(state,step){
state.num -= step;
}
},
actions:{
},
getters:{
getNum(state){
return state.num
}
}
})
在任意组件中,取共享状态中数据
<template lang="html">
<div class="">
<h1>首页</h1>
<p>{{getNum}}</p>
<button @click='fn' type="button" name="button">点我增加共享数据</button>
<button @click='fn1' type="button" name="button">点我减少共享数据</button>
</div>
</template>
<script>
export default {
data(){
return {
num:''
}
},
methods: {
fn(){
this.$store.commit('addNum',1)
},
fn1(){
this.$store.commit('reduceNum',1)
}
},
components: {
},
computed:{
getNum(){
return this.$store.state.num;
}
},
created() {
//do something after creating vue instance
}
}
</script>
<style media="screen">
</style>
生活寄语
爱代码,爱生活!