先介绍一下什么是组件把:

创建组件的两种方式:

  • 全局组件

// 组件就是vue的一个拓展实例
let component=Vue.extend({
data(){
return{
//与vue实例中的data不同,子组件的data必须是一个方法,必须有返回值,且返回值是对象。
//这样做可以使组件中的数据独立。
//需要共享数据时可把return的对象声明全局变量
}
}
template:'<div></div>'// 模板 这个组件的html元素
// })
//注册组件
Vue.component('hehe',component)

(简写)


Vue.component('组件名',{
template:''// 模板
})
  • 局部组件

new Vue({
el:'#app',
data:{
test:11
},
components:{
one:{
template:'<h1>这里是局部组件 </h1>'
}
} })

需要注意的是子组件的命名无法识别驼峰命名法,当组件做为标签使用的时候需要用“-”和小写字母替换该大写字母。


<div>
<one-data></one-data>
</div>
new Vue({
el:'#app',
data:{
test:11
},
components:{
oneData:{
template:'<h1>这里是局部组件 </h1>'
}
} })

1、父子属性传值

子组件不能直接使用父级data的内容,也不能直接修改父组件传递的值,但可以通过设置props属性来获得自身属性值。

原理:

  • 通过子组件的props抛出一个组件标签属性
  • 父组件通过该标签属性将参数传递给子组件
  • 子组件内部通过该标签属性获取值

代码实现:(实现过程中踩过的坑)

1.template标签内必须有且只有一个根元素

2.子组件标签内要通过v-bind的方式绑定父级的data的值

3.子组件通过props定义的自身属性值(test)获取父组件的data中的内容(父组件:{{name}} ;子组件:{{test}})


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="base/vue.js"></script>
</head>
<body>
<div>
{{name}}
<son :test='name'></son>
</div>
<!--实现功能较复杂时,会单独写个template标签,通过id与子组件中的template相关联,否则字符串拼接会很麻烦-->
<template>
<div>{{test}}</div>
</template>
</body>
<script>
new Vue({
el:'#myApp',
data:{
name:'加油鸭!'
},
components:{
son:{
template:'#tp',//类似于 el
props:['test']
}
}
})
</script>
</html>
  • 再用全局组件写一个父子属性传值,实现点击父组件按钮,子组件div显示和隐藏

(全局组件无固定父子关系,该组件标签放在哪个标签内就是哪个标签的子组件)


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>父向子传值</title>
<script src="base/vue.js"></script>
</head>
<body>
<div>
<!--c1就是myApp的子组件-->
<c1></c1>
</div>
<template>
<div>
<h4>我是c1,是父级</h4>
<button @click="change">点我c2变</button>
{{state}}
<hr>
<!--写在c1的template内,就是c1的子组件-->
<c2 :changed='state'></c2>
</div>
</template>
<template>
<div>
我是c2,是子级
<div v-show='changed'><h1>我是div</h1></div>
</div>
</template>
</body>
<script>
Vue.component("c1",{
template:'#tp1',
data(){
return {
state:true
}
},
methods:{
change(){
this.state=!this.state
}
}
})
Vue.component("c2",{
template:'#tp2',
props:['changed']
})
let vm=new Vue({
el:'#myApp'
})
</script>
</html>

2、子父事件传值

子组件不能直接修改父组件传递的值,可间接通过事件修改

原理

  • 子组件创建自定义事件
  • 自定义事件的处理函数是父组件的函数
  • 子组件通过$emit触发属于自己的自定义事件

代码实现:(点击子组件按钮,父组件div显示和隐藏)

代码中有一些思路注释:


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>子向父传值</title>
<script src="base/vue.js"></script>
</head>
<body>
<div>
<c1></c1>
</div>
<template>
<div>
<h4>我是c1,是父级</h4>
<div v-show='state'><h1>我是div</h1></div>
<hr>
<!--c2自定义了一个changed事件处理父组件的函数change-->
<c2 @changed='change'></c2>
</div>
</template>
<template>
<div>
我是c2,是子级
<!--子组件点击按钮,父组件显示隐藏,当然有点击事件啦,
所以给button加点击事件触发一个函数,发现c2没有设置methods,
所以去c2的实例中加一个methods并设置函数sclick,
再通过sclick函数把其自定义事件changed抛出,
changed里面就是c1的处理函数-->
<button @click="sclick">点我c1变</button>
</div>
</template>
</body>
<script>
Vue.component("c1",{
template:'#tp1',
data(){
return {
state:true
}
},
methods:{
change(){
this.state=!this.state
}
} })
Vue.component("c2",{
template:'#tp2',
methods:{
sclick(){
this.$emit('changed')
}
}
})
let vm=new Vue({
el:'#myApp'
})
</script>
</html>

3、非父子传值

原理

  • 创建公共汽车实例
  • 实例上注册事件,事件的处理函数就是要改变数据的处理函数
  • 触发事件

(1)公有的父元素作为桥接-----结合父子属性传值和子父事件传值来实现(适用于亲兄弟)


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>兄弟传值</title>
<script src="base/vue.js"></script>
</head>
<body>
<div>
我是父级
{{state}}
<hr>
<!--c1和c2都是div的子组件-->
<!--子父事件传值-->
<c1 @emit='change'></c1>
<hr>
<!--父子属性传值-->
<c2 :test='state'></c2>
</div>
<template>
<div>
我是c1,是c2的兄弟
<!--间接通过父级改变了兄弟级的值-->
<button @click='emit'>点我我的兄弟和父级都会发生改变</button>
</div>
</template>
<template>
<div>我是c2,是c1的兄弟
<p>{{test}}</p>
</div>
</template>
</body>
<script>
Vue.component('c1',{
template:'#tp1',
methods:{
emit(){
this.$emit('emit')
}
}
})
Vue.component('c2',{
template:'#tp2',
props:["test"]
})
new Vue({
el:'#myApp',
data:{
state:false
},
methods:{
change(){
this.state=!this.state
}
}
})
</script>
</html>

(2)公共汽车传值(声明一个公共实例作为过滤)

修改谁的值就去触发谁的方法


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>兄弟之间通过公共汽车传值</title>
<script src="base/vue.js"></script>
</head>
<body>
<div>
<father></father>
</div>
<template>
<div>我是父组件
<hr>
<son1></son1>
<hr>
<son2></son2>
</div> </template>
<template>
<div>{{name}}
<!--点击事件触发一下sclick函数,相当于把抛出的change函数触发了-->
<button @click='sclick'>点我</button>
</div>
</template>
<template>
<div>{{name}}</div>
</template>
</body>
<script>
let Bus=new Vue();
new Vue({
el:'#myApp',
components:{
father:{
template:'#father',
components:{
son1:{
template:'#son1',
data(){
return{
name:'我是子组件1'
}
},
methods:{
sclick(){
//触发test事件,再传一个参数給change函数中的val
//name值就从“我是子组件2”通过点击事件变成了"加油鸭!!!!"
Bus.$emit('test',"加油鸭!!!!")
}
}
},
son2:{
template:'#son2',
data(){
return{
name:'我是子组件2'
}
},
methods:{
change(val){
this.name=val
}
},
mounted(){
//只要mounted执行了,说明组件已经准备就绪
//注册一个函数,函数名叫test,处理函数就是methods中的change函数
//简单来说,只要想办法触发test事件就相当于执行了change函数
Bus.$on('test',this.change)
}
}
}
}
}
})
</script>
</html>

(3)vuex(集中式的数据状态管理器)

简单来说,就是用来管理全局变量的,不管哪里进行修改,页面都会随之变化。比如我们手机端的选择所在区域,假设你选了北京,跳到其他页面还是显示的北京就可以用vuex来实现。

解决的问题:

帮助我们管理共享状态。

vuex的相关配置步骤:

  1. npm install vuex --save-dev
  2. 引入:`import Vuex from ‘vuex’
  3. 使用:Vue.use(Vuex)
  4. 设置vuex

var store=new Vuex.Store({
state:{
},
mutations:{
},
actions:{
},
getters:{
}
})
  1. 将数据放入到实例中

new Vue({
el: '#app',
router,
store,
components: { App},
template: '<App/>',
})

vuex中的模块:

  1. state:存储状态,可通过this.$store.state获取我们在vuex中声明的全局变量的值

import Vuex from 'vuex'
Vue.use(Vuex)
let store=new Vuex.Store({
state:{
name:1,
}
})
export default store;
//一般我们会新建一个store文件夹,
//在该文件夹的js文件中通过暴露出store,
//再通过在main.js中引入该文件的方式来使用vuex

在组件中我们只需要通过{{this.$store.state.name}}就可以渲染name的值

写一个组件:


<template>
<div>
{{msg}}
{{this.$store.state.name}}
<hr>
</div>
</template> <script>
export default {
name:'List',
data(){
return {
msg:'list',
}
}
}
</script>
<style>
#list div{
width: 50px;
height: 50px;
background: red;
}
</style>



有木有觉得{{this.$store.state.name}}太长了,可不可以直接写{{name}}:


<template>
<div>
{{msg}}
{{name}}
<hr>
</div>
</template> <script>
export default {
name:'List',
data(){
return {
msg:'list',
}
},
computed:{
name(){
return this.$store.state.name
}
}
}
</script>
<style>
#list div{
width: 50px;
height: 50px;
background: red;
}
</style>

有小伙伴会说了,这样也不简单呀,那这样呢?


<template>
<div>
{{msg}}
{{name}}
<hr>
</div>
</template> <script>
import {mapState} from 'vuex'
export default {
name:'List',
data(){
return {
msg:'list',
}
},
//可不可以不用拓展操作符?可以呀
//computed:mapState(['name'])
//可是这样你如果还有其他的方法要在computed中操作就没法操作了
computed:{
...mapState(['name'])
}
}
</script>
<style>
#list div{
width: 50px;
height: 50px;
background: red;
}
</style>

如果遇到需要改名的情况,可通过对象的形式:


{{_name}} //改后的名字进行页面渲染
...mapState({_name:"name"})

后面的方法基本思路一样,接下来就都用简写形式啦!

2. mutations:修改状态


import Vuex from 'vuex'
Vue.use(Vuex)
let store=new Vuex.Store({
state:{
name:1,
},
mutations:{
CHANGE_NUM(state,name){
state.name=name
}
},
})
export default store;

我们来做一个小效果,点击按钮改变状态值从1变为888


<template>
<div>
<div @click='CHANGE_NUM(888)'>change</div>
{{msg}}
{{_name}}
<hr>
</div>
</template> <script>
import {mapState,mapMutations} from 'vuex'
export default {
name:'List',
data(){
return {
msg:'list',
}
},
methods:{
//非简写形式,点击事件的调用方法换为getName
//getName(){
// this.$store.commit('CHANGE_NUM',888)
// }
...mapMutations(['CHANGE_NUM']),
},
computed:{
...mapState({_name:'name'})
}
}
</script>
<style>
#list div{
width: 50px;
height: 50px;
background: red;
}
</style>





3. actions:专门用来做异步操作

通过计时器模拟一个异步操作,并通过commit触发mutations


import Vuex from 'vuex'
Vue.use(Vuex)
let store=new Vuex.Store({
state:{
name:1,
},
mutations:{
CHANGE_NUM(state,name){
state.name=name
}
},
actions:{
//逻辑处理及异步请求
getNumApi({commit},params){
setTimeout(()=>{
commit('CHANGE_NUM',params)
},2000)
}
}
})
export default store;

再来实现一个点击按钮改变值的效果:


<template>
<div>
<div @click='getNumApi("xixi")'>change</div>
{{msg}}
{{_name}}
<hr>
</div>
</template> <script>
import {mapState,mapActions} from 'vuex'
export default {
name:'List',
data(){
return {
msg:'list',
}
},
methods:{
//非简写的写法:(通过dispatch触发相应的action)
//emitActions(params){
// this.$store.dispatch('getNumApi',params)
// }
...mapActions(['getNumApi'])
},
computed:{
...mapState({_name:'name'})
}
}
</script>
<style>
#list div{
width: 50px;
height: 50px;
background: red;
}
</style>

2秒后name值改变了



4. getters:类似于计算属性computed,里面进行一些计算操作


import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
let store=new Vuex.Store({
state:{
name:1
},
mutations:{
CHANGE_NUM(state,name){
state.name=name
}
},
getters:{
double(state){
return state.name*2
}
},
actions:{
//逻辑处理及异步请求
getNumApi({commit},params){
setTimeout(()=>{
commit('CHANGE_NUM',params)
},2000)
}
}
})
export default store;

再来做点击事件:


<template>
<div>
<div @click='getNumApi("xixi")'>change</div>
{{msg}}
{{_name}}
{{double}}
<hr>
</div>
</template> <script>
import {mapState,mapMutations,mapActions,mapGetters} from 'vuex'
export default {
name:'List',
data(){
return {
msg:'list',
}
},
methods:{
...mapActions(['getNumApi'])
},
computed:{
...mapState({_name:'name'}),
...mapGetters(['double'])
}
}
</script>
<style>
#list div{
width: 50px;
height: 50px;
background: red;
}
</style>

由于字符串不能进行乘法操作,所以打印结果是NaN



5. modules:模块

在实际开发中,我们会把以上四个模块,分别写在四个js文件中,在通过引入、暴露的形式写在一个index.js文件下。


import actions from './actions'
import state from './state'
import mutations from './mutations'
import getters from './getters' export default {
state,
mutations,
getters,
actions
}

再把这5个文件放在store文件夹下的shopcar文件夹下(名字随意),在再store文件夹下,新建一个index.js文件,并通过modules的形式展现:


import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
import shopcar from './shopcar'
let store=new Vuex.Store({
modules:{
shopcar:shopcar
}
})
export default store

来源:https://blog.csdn.net/weixin_43747906/article/details/84981199

Vue组件通信(传值)的更多相关文章

  1. vue 组件通信传值

    父子组件通信: 子组件 <template> <div> <h3 @click="alerrt"> 我是子组件一</h3> < ...

  2. vue组件通信传值——Vuex

    一.Vuex介绍 Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化. Vuex 也集成到 Vu ...

  3. Vue 组件间传值

    前言 Vue 作为现在比较火的框架之一,相信您在使用的过程中,也会遇到组件间传值的情况,本文将讲解几种 Vue 组件间传值的几种方法,跟着小编一起来学习一下吧! 实现 注意: 学习本文,需要您对 Vu ...

  4. vue组件之间传值方式解析

    vue组件之间传值方式解析一.父组件传到子组件 1.父组件parent代码如下: <template> <div class="parent"> <h ...

  5. 【Vue组件通信】props、$ref、$emit,组件传值

    1.什么是组件通信 组件间如何通信,也就成为了vue中重点知识,组件通信,涉及到组件之间数据的传递.类似NET POST/GET参数传递. Vue基本的三种传递方式** (props.\(ref.\) ...

  6. vue组件通信的几种方式

    最近用vue开发项目,记录一下vue组件间通信几种方式 第一种,父子组件通信 一.父组件向子组件传值 1.创建子组件,在src/components/文件夹下新建一个Child.vue 2.Child ...

  7. vue组件通信新姿势

    在vue项目实际开发中我们经常会使用props和emit来进行子父组件的传值通信,父组件向子组件传递数据是通过prop传递的, 子组件传递数据给父组件是通过$emit触发事件来做到的.例如: Vue. ...

  8. vue组件通信全面总结

    写在前面 组件间的通信是是实际开发中非常常用的一环,如何使用对项目整体设计.开发.规范都有很实际的的作用,我在项目开发中对此深有体会,总结下vue组件间通信的几种方式,讨论下各自的使用场景 文章对相关 ...

  9. vue 组件通信

    组件 组件之间的数据是单向绑定的. 父组件向子组件通信 是通过子组件定义的props属性来实现.通过props定义变量与变量类型和验证方式. props简化定义 在简化定义中,变量是以数组的方式定义. ...

  10. Vue组件间传值 v-model

    使用过Vue的同学应该都了解组件之间传值 父组件 --> 子组件 : props 子组件 --> 父组件 : 事件 其实有一种更为简单的方法,是基于上述两种方法,那就是 v-model 我 ...

随机推荐

  1. 关于Android项目中的分层,参考eoecn开源项目(8.29)

    以下为eoecn开源项目的分层情况: ├ cn.eoe.app --存放程序全局性类的包├ cn.eoe.app.adapter --存放适配器的实现类的包 ├ cn.eoe.app.adapter. ...

  2. 数据库表设计时一对一关系存在的必要性 数据库一对一、一对多、多对多设计 面试逻辑题3.31 sql server 查询某个表被哪些存储过程调用 DataTable根据字段去重 .Net Core Cors中间件解析 分析MySQL中哪些情况下数据库索引会失效

    数据库表设计时一对一关系存在的必要性 2017年07月24日 10:01:07 阅读数:694 在表设计过程中,我无意中觉得一对一关系觉得好没道理,直接放到一张表中不就可以了吗?真是说,网上信息什么都 ...

  3. 【android】listview改变选中行背景图片

    [android]listview改变选中行背景图片 目标:当item选中时,改变其背景图片.效果图如下: 直接在listview的xml文件中使用listselector: 1 2 3 4 5 6 ...

  4. Storm/Cassandra集成错误:NoSuchMethodError: concurrent.Futures.withFallback

    本文原文出处: http://blog.csdn.net/bluishglc/article/details/50443205 严禁不论什么形式的转载.否则将托付CSDN官方维护权益. 2015年的最 ...

  5. the reactor pattern and java nio

    在<java NIO>作者PPT<How to Build a Scalable Multiplexed Server With NIO> 和 Doug Lea <Sca ...

  6. Atitit.跨语言 java c#.net php js常用的codec encode算法api 兼容性  应该内置到语言里面

    Atitit.跨语言 java c#.net php js常用的codec encode算法api 兼容性  应该内置到语言里面 1. 常用算法1 1.1. 目录2 1.2. 定义和用法编辑2 1.3 ...

  7. gitlab配置smtp时,总是提示需要鉴权,记录一下爬坑过程。

    配置好smtp,然后发送邮件时总是提示 Net::SMTPFatalError: 550 5.7.1 authentication is required 最后发现是因为在gitlab web界面上配 ...

  8. C#实战Microsoft Messaging Queue(MSMQ)消息队列(干货)<转>

    前言 在使用MSMQ之前,我们需要自行安装消息队列组件!(具体安装方法大家自己搜一下吧) 采用MSMQ带来的好处是:由于是异步通信,无论是发送方还是接收方都不用等待对方返回成功消息,就可以执行余下的代 ...

  9. 配置Nginx与tomcat负责均衡集群,

    今天主要说说,nginx如何配置tomcat集群,首先我们先介绍一下各个软件: 一: 1.Nginx介绍: 下载地址:http://nginx.org/en/download.html nginx这个 ...

  10. JavaWeb学习总结第五篇--认识Cookie机制

    Cookie机制 前言 会话跟踪是Web程序中常用的技术,用来跟踪用户的整个会话.常用的会话跟踪技术是Cookie和Session.Cookie通过在客户端记录信息确定用户身份,Session通过在服 ...