焊管机组,王雅媛博客,盐湖钾肥价格
总结为三大类:
props
/ $emit
$children
/ $parent
provide
/ inject
ref
/ refs
localstorage
/ sessionstorage
$attrs
与 $listeners
props
; $parent
/ $children
; provide
/ inject
; ref
; $attrs
/ $listeners
eventbus
; vuexeventbus
;vuex;provide
/ inject
、$attrs
/ $listeners
props
/ $emit
article.vue
中如何获取父组件section.vue
中的数据articles:['红楼梦', '西游记','三国演义']
// section父组件 <template> <div class="section"> <com-article :articles="articlelist"></com-article> </div> </template> <script> import comarticle from './test/article.vue' export default { name: 'helloworld', components: { comarticle }, data() { return { articlelist: ['红楼梦', '西游记', '三国演义'] } } } </script>
// 子组件 article.vue <template> <div> <span v-for="(item, index) in articles" :key="index">{{item}}</span> </div> </template> <script> export default { props: ['articles'] } </script>
总结: prop 只可以从上一级组件传递到下一级组件(父子组件),即所谓的单向数据流。而且 prop 只读,不可被修改,所有修改都会失效并警告。
$emit
我自己的理解是这样的: $emit
绑定一个自定义事件, 当这个语句被执行时, 就会将参数arg传递给父组件,父组件通过v-on监听并接收参数。 通过一个例子,说明子组件如何向父组件传递数据。 在上个例子的基础上, 点击页面渲染出来的ariticle
的item
, 父组件中显示在数组中的下标// 父组件中 <template> <div class="section"> <com-article :articles="articlelist" @onemitindex="onemitindex"></com-article> <p>{{currentindex}}</p> </div> </template> <script> import comarticle from './test/article.vue' export default { name: 'helloworld', components: { comarticle }, data() { return { currentindex: -1, articlelist: ['红楼梦', '西游记', '三国演义'] } }, methods: { onemitindex(idx) { this.currentindex = idx } } } </script>
<template> <div> <div v-for="(item, index) in articles" :key="index" @click="emitindex(index)">{{item}}</div> </div> </template> <script> export default { props: ['articles'], methods: { emitindex(index) { this.$emit('onemitindex', index) } } } </script>
$children
/ $parent
$parent
和$children
就可以访问组件的实例,拿到实例代表什么?代表可以访问此组件的所有方法和data
。接下来就是怎么实现拿到指定组件的实例。
// 父组件中 <template> <div class="hello_world"> <div>{{msg}}</div> <com-a></com-a> <button @click="changea">点击改变子组件值</button> </div> </template> <script> import coma from './test/coma.vue' export default { name: 'helloworld', components: { coma }, data() { return { msg: 'welcome' } }, methods: { changea() { // 获取到子组件a this.$children[0].messagea = 'this is new value' } } } </script>
// 子组件中 <template> <div class="com_a"> <span>{{messagea}}</span> <p>获取父组件的值为: {{parentval}}</p> </div> </template> <script> export default { data() { return { messagea: 'this is old' } }, computed:{ parentval(){ return this.$parent.msg; } } } </script>
#app
上拿$parent
得到的是new vue()
的实例,在这实例上再拿$parent
得到的是undefined
,而在最底层的子组件拿$children
是个空数组。也要注意得到$parent
和$children
的值不一样,$children
的值是数组,而$parent
是个对象provide
/ inject
provide
/ inject
是vue2.2.0
新增的api, 简单来说就是父组件中通过provide
来提供变量, 然后再子组件中通过inject
来注入变量。inject
那么就可以注入provide
中的数据,而不局限于只能从当前父组件的props属性中回去数据// a.vue <template> <div> <comb></comb> </div> </template> <script> import comb from '../components/test/comb.vue' export default { name: "a", provide: { for: "demo" }, components:{ comb } } </script>
// b.vue <template> <div> {{demo}} <comc></comc> </div> </template> <script> import comc from '../components/test/comc.vue' export default { name: "b", inject: ['for'], data() { return { demo: this.for } }, components: { comc } } </script>
// c.vue <template> <div> {{demo}} </div> </template> <script> export default { name: "c", inject: ['for'], data() { return { demo: this.for } } } </script>
ref
/ refs
ref
:如果在普通的 dom 元素上使用,引用指向的就是 dom 元素;如果用在子组件上,引用就指向组件实例,可以通过实例直接调用组件的方法或访问数据, 我们看一个ref
来访问组件的例子:
// 子组件 a.vue export default { data () { return { name: 'vue.js' } }, methods: { sayhello () { console.log('hello') } } }
// 父组件 app.vue <template> <component-a ref="coma"></component-a> </template> <script> export default { mounted () { const coma = this.$refs.coma; console.log(coma.name); // vue.js coma.sayhello(); // hello } } </script>
eventbus
又称为事件总线,在vue中可以使用它来作为沟通桥梁的概念, 就像是所有组件共用相同的事件中心,可以向该中心注册发送事件或接收事件, 所以组件都可以通知其他组件。eventbus
来实现组件之间的数据通信呢?具体通过下面几个步骤// event-bus.js import vue from 'vue' export const eventbus = new vue()
<template> <div> <show-num-com></show-num-com> <addition-num-com></addition-num-com> </div> </template> <script> import shownumcom from './shownum.vue' import additionnumcom from './additionnum.vue' export default { components: { shownumcom, additionnumcom } } </script>
// addtionnum.vue 中发送事件 <template> <div> <button @click="additionhandle">+加法器</button> </div> </template> <script> import {eventbus} from './event-bus.js' console.log(eventbus) export default { data(){ return{ num:1 } }, methods:{ additionhandle(){ eventbus.$emit('addition', { num:this.num++ }) } } } </script>
// shownum.vue 中接收事件 <template> <div>计算和: {{count}}</div> </template> <script> import { eventbus } from './event-bus.js' export default { data() { return { count: 0 } }, mounted() { eventbus.$on('addition', param => { this.count = this.count + param.num; }) } } </script>
这样就实现了在组件addtionnum.vue
中点击相加按钮, 在shownum.vue
中利用传递来的 num
展示求和的结果.
import { eventbus } from 'event-bus.js' eventbus.$off('addition', {})
vuex 是一个专为 vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化. vuex 解决了多个视图依赖于同一状态
和来自不同视图的行为需要变更同一状态
的问题,将开发者的精力聚焦于数据的更新而不是数据在组件之间的传递上
state
:用于数据的存储,是store中的唯一数据源getters
:如vue中的计算属性一样,基于state数据的二次包装,常用于数据的筛选和多个数据的相关性计算mutations
:类似函数,改变state数据的唯一途径,且不能用于处理异步事件actions
:类似于mutation
,用于提交mutation
来改变状态,而不直接变更状态,可以包含任意异步操作modules
:类似于命名空间,用于项目中将各个模块的状态分开定义和操作,便于维护// 父组件 <template> <div id="app"> <childa/> <childb/> </div> </template> <script> import childa from './components/childa' // 导入a组件 import childb from './components/childb' // 导入b组件 export default { name: 'app', components: {childa, childb} // 注册a、b组件 } </script>
// 子组件childa <template> <div id="childa"> <h1>我是a组件</h1> <button @click="transform">点我让b组件接收到数据</button> <p>因为你点了b,所以我的信息发生了变化:{{bmessage}}</p> </div> </template> <script> export default { data() { return { amessage: 'hello,b组件,我是a组件' } }, computed: { bmessage() { // 这里存储从store里获取的b组件的数据 return this.$store.state.bmsg } }, methods: { transform() { // 触发receiveamsg,将a组件的数据存放到store里去 this.$store.commit('receiveamsg', { amsg: this.amessage }) } } } </script>
// 子组件 childb <template> <div id="childb"> <h1>我是b组件</h1> <button @click="transform">点我让a组件接收到数据</button> <p>因为你点了a,所以我的信息发生了变化:{{amessage}}</p> </div> </template> <script> export default { data() { return { bmessage: 'hello,a组件,我是b组件' } }, computed: { amessage() { // 这里存储从store里获取的a组件的数据 return this.$store.state.amsg } }, methods: { transform() { // 触发receivebmsg,将b组件的数据存放到store里去 this.$store.commit('receivebmsg', { bmsg: this.bmessage }) } } } </script>
vuex的store.js
import vue from 'vue' import vuex from 'vuex' vue.use(vuex) const state = { // 初始化a和b组件的数据,等待获取 amsg: '', bmsg: '' } const mutations = { receiveamsg(state, payload) { // 将a组件的数据存放于state state.amsg = payload.amsg }, receivebmsg(state, payload) { // 将b组件的数据存放于state state.bmsg = payload.bmsg } } export default new vuex.store({ state, mutations })
let defaultcity = "上海" try { // 用户关闭了本地存储功能,此时在外层加个try...catch if (!defaultcity){ defaultcity = json.parse(window.localstorage.getitem('defaultcity')) } }catch(e){} export default new vuex.store({ state: { city: defaultcity }, mutations: { changecity(state, city) { state.city = city try { window.localstorage.setitem('defaultcity', json.stringify(state.city)); // 数据改变的时候把数据拷贝一份保存到localstorage里面 } catch (e) {} } } })
这里需要注意的是:由于vuex里,我们保存的状态,都是数组,而localstorage只支持字符串,所以需要用json转换:
json.stringify(state.subscribelist); // array -> string json.parse(window.localstorage.getitem("subscribelist")); // string -> array
localstorage
/ sessionstorage
window.localstorage.getitem(key)
获取数据 通过window.localstorage.setitem(key,value)
存储数据json.parse()
/ json.stringify()
做数据格式转换 localstorage
/ sessionstorage
可以结合vuex
, 实现数据的持久保存,同时使用vuex解决数据和状态混乱问题.$attrs
与 $listeners
现在我们来讨论一种情况, 我们一开始给出的组件关系图中a组件与d组件是隔代关系, 那它们之前进行通信有哪些方式呢?
props
绑定来进行一级一级的信息传递, 如果d组件中状态改变需要传递数据给a, 使用事件系统一级级往上传递eventbus
,这种情况下还是比较适合使用, 但是碰到多人合作开发时, 代码维护性较低, 可读性也低在vue2.4
中,为了解决该需求,引入了$attrs
和$listeners
, 新增了inheritattrs
选项。 在版本2.4以前,默认情况下,父作用域中不作为 prop 被识别 (且获取) 的特性绑定 (class 和 style 除外),将会“回退”且作为普通的html特性应用在子组件的根元素上。
$attrs
:包含了父作用域中不被 prop 所识别 (且获取) 的特性绑定 (class 和 style 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind="$attrs" 传入内部组件。通常配合 inheritattrs 选项一起使用。$listeners
:包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件接下来看一个跨级通信的例子:
// app.vue // index.vue <template> <div> <child-com1 :name="name" :age="age" :gender="gender" :height="height" title="程序员成长指北" ></child-com1> </div> </template> <script> const childcom1 = () => import("./childcom1.vue"); export default { components: { childcom1 }, data() { return { name: "zhang", age: "18", gender: "女", height: "158" }; } }; </script>
// childcom1.vue <template class="border"> <div> <p>name: {{ name}}</p> <p>childcom1的$attrs: {{ $attrs }}</p> <child-com2 v-bind="$attrs"></child-com2> </div> </template> <script> const childcom2 = () => import("./childcom2.vue"); export default { components: { childcom2 }, inheritattrs: false, // 可以关闭自动挂载到组件根元素上的没有在props声明的属性 props: { name: string // name作为props属性绑定 }, created() { console.log(this.$attrs); // { "age": "18", "gender": "女", "height": "158", "title": "程序员成长" } } }; </script>
// childcom2.vue <template> <div class="border"> <p>age: {{ age}}</p> <p>childcom2: {{ $attrs }}</p> </div> </template> <script> export default { inheritattrs: false, props: { age: string }, created() { console.log(this.$attrs); // { "gender": "女", "height": "158", "title": "程序员成长" } } }; </script>
父组件通过v-model传递值给子组件时,会自动传递一个value的prop属性,
子组件中通过this.$emit(‘input',val)自动修改v-model绑定的值,下面看个例子。
父组件:
<template> <div> <child v-model="total"></child> <button @click="increse">增加5</button> </div> </template> <script> import child from "./child.vue" export default { components: { child }, data: function () { return { total: 0 }; }, methods: { increse: function () { this.total += 5; } } } </script>
子组件:
<template> <div> <span>{{value}}</span> <button @click="reduce">减少5</button> </div> </template> <script> export default { props: { value: number // 注意这里是value }, methods: { reduce: function(){ this.$emit("input", this.value - 5) // 事件为input } } } </script>
如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复
Object.keys() 和 Object.getOwnPropertyNames() 的区别详解
JavaScript使用prototype属性实现继承操作示例
JavaScript直接调用函数与call调用的区别实例分析
JavaScript设计模式--简单工厂模式实例分析【XHR工厂案例】
网友评论