Vue的observable用法

下面是vue官网的介绍
在这里插入图片描述
在多个子组件项目中使用这个非常好用。子组件数据传递,我们可能先想到先把子组件数据传到父组件,再由父组件传给另一个子组件,这样使很麻烦的。
现在我们建立一个js文件,让两个子组件或多个子组件共享这里的数据,这里提供读取和修改方法。我在真实的项目中用到这些,用到了elementUI组件,两个Dialog弹窗的嵌套。下面我这个demo的结构跟我真实项目一致,只是数据不同。

父组件

<template>
    <div id="observable-box">
        <el-table :data="tableData" style="width: 100%">
            <el-table-column prop="number" label="学生证编号" width="180" />
            <el-table-column prop="name" label="姓名" width="180" />
            <el-table-column prop="professional" label="专业" width="180" />
            <el-table-column prop="theClass" label="班级" />
            <el-table-column
                prop="clubMember"
                label="俱乐部"
                :formatter="formatter"
            />
            <el-table-column label="操作">
                <template slot-scope="scope">
                    <el-button
                        type="primary"
                        size="mini"
                        @click="modify(scope.row)"
                        >修改</el-button
                    >
                    <el-button
                        type="primary"
                        size="mini"
                        :disabled="scope.row.clubMember !== 1"
                        @click="applyQualification(scope.row)"
                        >申请会员</el-button
                    >
                </template>
            </el-table-column>
        </el-table>
        <el-dialog
            title="修改个人信息"
            :visible.sync="dialogVisible"
            width="800px"
        >
            <Modify
                :modify="needModifyObj"
                @modifyFinish="modifyFinish"
                @closeDialog="closeDialog"
            />
            <MoreInfo />
        </el-dialog>
    </div>
</template>

<script>
import { students } from '@/mook/observableData.js'
import Modify from '@/components/vueObservable/modify.vue'
import MoreInfo from "@/components/vueObservable/moreInfo.vue"

export default {
    name: 'Observable',
    components: {
        Modify,
        MoreInfo
    },
    data() {
        return {
            tableData: students,
            dialogVisible: false,
            needModifyObj: {}
        }
    },
    methods: {
        modify(row) {
            console.log("11:", row);
            this.dialogVisible = true;
            this.needModifyObj = { ...row }
        },
        // 申请会员资格
        applyQualification(row) {
            console.log(row);
        },
        formatter(row) {
            return row.clubMember === 1 ? "非会员" : "会员"
        },
        modifyFinish(data) {
            this.tableData.forEach(item => {
                if (item.number === data.number) {
                    const { professional, name, theClass } = data
                    item.professional = professional;
                    item.name = name;
                    item.theClass = theClass;
                }
            })
        },
        closeDialog() {
            this.dialogVisible = false;
        }
    },
}
</script>

核心代码就是子组件Modify和MoreInfo

子组件Modify

<template>
    <div class="observable-motify">
        <el-form ref="form" :model="form" label-width="100px">
            <el-form-item label="学生证编号:">
                <el-input v-model="form.number" disabled></el-input>
            </el-form-item>
            <el-form-item label="姓名:">
                <el-input v-model="form.name"></el-input>
            </el-form-item>
            <el-form-item label="专业:">
                <el-input v-model="form.professional"></el-input>
            </el-form-item>
            <el-form-item label="班级:">
                <el-input v-model="form.theClass"></el-input>
            </el-form-item>

            <el-form-item label="个人成就:">
                <el-button @click="moreInfo" type="primary">添加</el-button>

                <el-table :data="achievementData" style="width: 100%">
                    <el-table-column prop="time" label="时间" width="180" />
                    <el-table-column prop="type" label="成就" width="180" />
                    <el-table-column label="操作">
                        <template>
                            <el-button type="text" size="mini" @click="remove"
                                ><i class="el-icon-close"></i
                            ></el-button>
                        </template>
                    </el-table-column>
                </el-table>
            </el-form-item>
        </el-form>
        <el-row type="flex" justify="center">
            <el-button type="primary" @click="confirm">确 定</el-button>
            <el-button type="primary" @click="cancel">取 消</el-button>
        </el-row>
    </div>
</template>
<script>
import { isEmptyObject } from '@/utils/common.js'
import { store, mutations, resetStore } from './bus.js'
export default {
    props: {
        modify: {
            type: Object,
            default: () => { }
        },
    },
    data() {
        return {
            form: {
                number: '',
                name: '',
                professional: '',
                theClass: '',
            }
        }
    },
    computed: {
        // 该数据是moreInfo.vue选中之后保存在store.achievementList里,这里直接读取就ok
        achievementData() {
            return store.achievementList
        }
    },
    created() {
        this.init()
    },
    methods: {
        init() {
            // 如果不是{}就赋值
            if (!isEmptyObject(this.modify)) {
                this.form = { ...this.modify }
            }
        },
        // 确定 
        confirm() {
            if(this.achievementData && this.achievementData.length){
                // 把一条个人成就插入到form表单中
                this.$set(this.form,"oneAchievement",this.achievementData)
            }
            // 派发事件,修改完把数据回传
            this.$emit("modifyFinish", this.form);
            this.$emit('closeDialog');
            console.log(JSON.parse(JSON.stringify(this.form)));
        },
        cancel() {
            this.$emit('closeDialog');
        },
        moreInfo() {
            // 重置一下数据
            resetStore.resetFunc();
            // 打开弹窗
            mutations.setMoreInfoVisible(true)
        },
        // 移除数据
        remove() {
            mutations.setAchievementList([])
        }
    },
}
</script>

子组件MoreInfo

<template>
    <div class="observable-motify">
        <el-dialog
            append-to-body
            title="荣耀时刻"
            :visible.sync="dialogVisible"
            :before-close="beforeClose"
            @open="openDialog"
            width="800px"
        >
            <el-form ref="form" :model="form" label-width="100px" inline>
                <el-form-item label="时间段">
                    <el-input v-model.trim="form.time"></el-input>
                </el-form-item>
                <el-form-item label="获得成就">
                    <el-input v-model.trim="form.type"></el-input>
                </el-form-item>
                <el-form-item>
                    <el-button @click="search" type="primary">搜索</el-button>
                </el-form-item>
            </el-form>
            <el-table :data="searchResult" style="width: 100%">
                <el-table-column prop="time" label="时间" />
                <el-table-column prop="type" label="成就" />
                <el-table-column label="选择" center>
                    <template slot-scope="scope">
                        <el-radio
                            v-model="radio"
                            :label="scope.$index"
                            @change.native="getCurrentRow(scope.row)"
                            style="
                                color: #fff;
                                padding-left: 10px;
                                margin-right: -25px;
                            "
                            >{{ "" }}
                        </el-radio>
                    </template>
                </el-table-column>
            </el-table>
            <el-row type="flex" justify="center" style="margin-top: 20px">
                <el-button type="primary" @click="confirm">确 定</el-button>
                <el-button type="primary" @click="cancel">取 消</el-button>
            </el-row>
        </el-dialog>
    </div>
</template>
<script>
import { achievement } from '@/mook/observableData.js'
import { store, mutations } from './bus.js'
export default {
    data() {
        return {
            form: {
                time: '',
                type: ''
            },
            searchResult: [],
            radio: '',
            selectSearch: []
        }
    },
    computed: {
        dialogVisible() {
            return store.moreInfoVisible
        }
    },
    methods: {
        // 模拟搜索接口,模拟模糊查询
        search() {
            this.searchResult = [];
            if (!this.form.time && !this.form.type) {
                this.$message.error('请输入查询条件');
            } else if (this.form.time && this.form.type) {
                achievement.forEach(item => {
                    if (item.time.includes(this.form.time) && item.type.includes(this.form.type)) {
                        this.searchResult.push(item)
                    }
                })
            } else if (this.form.time && !this.form.type) {
                achievement.forEach(item => {
                    if (item.time.includes(this.form.time)) {
                        this.searchResult.push(item)
                    }
                })
            } else if (!this.form.time && this.form.type) {
                achievement.forEach(item => {
                    if (item.type.includes(this.form.type)) {
                        this.searchResult.push(item)
                    }
                })
            }
        },
        cancel() {
            // 关闭弹窗
            mutations.setMoreInfoVisible(false);
        },
        // 选中数据后,确认
        confirm() {
            // 如果没有选中,有报错提示
            if (!this.selectSearch.length) {
                this.$message.error('请先选中后再提交');
                return;
            }
            // 把数据存放到store
            mutations.setAchievementList(this.selectSearch);
            // 关闭弹窗
            mutations.setMoreInfoVisible(false);
        },
        // 选中搜索出来的数据(单选)
        getCurrentRow(row) {
            this.selectSearch = [];
            this.selectSearch.push({ ...row })
        },
        // 关闭弹窗触发的回调
        beforeClose() {
            mutations.setMoreInfoVisible(false);
        },
        // 打开弹窗触发的回调
        openDialog() {
            // 初始化
            this.searchResult = [];
            this.selectSearch = [];
        }
    },
}
</script>
<style scoped lang="less">
/deep/.el-radio__input.is-checked + .el-radio__label {
    color: #fff;
}
</style>

bus.js

import Vue from 'vue';
// 读取
const store =Vue.observable(
    {
        moreInfoVisible: false,
        achievementList:[],
    });
// 修改
const mutations = {
    setMoreInfoVisible(val){
        store.moreInfoVisible = val;
    },
    setAchievementList(array){
        store.achievementList = array;
    }
}
// 重置
const resetStore = {
    resetFunc(){
        store.moreInfoVisible = false;
        store.achievementList = [];
    }
}
export {
    store,
    mutations,
    resetStore
}

核心代码分析

组件MoreInfo弹窗的打开要依赖组件Modify的添加按钮。我把控制组件MoreInfo关闭的moreInfoVisible放在了bus.js里,引入了bus.js, 组件Modify页面就直接改变moreInfoVisible,组件MoreInfo可以直接读取moreInfoVisible来决定自己的打开和关闭。
对应参数achievementList也是同理,我需要在组件MoreInfo获取,然后存到bus.js的observable里,组件Modify监听bus.js里面的achievementList
最后想看我的源代码在github上:https://github.com/ineedyou1024/front-end-knowledge.git
最后可以互相fork一下,互相学习。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值