Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/472.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Vue.js+;Require.js扩展父级_Javascript_Requirejs_Vue.js - Fatal编程技术网

Javascript Vue.js+;Require.js扩展父级

Javascript Vue.js+;Require.js扩展父级,javascript,requirejs,vue.js,Javascript,Requirejs,Vue.js,我是Vue.js的新手,但正在努力掌握它。到目前为止,它进展顺利,我已经取得了相当大的进展,但我一直在扩展一个家长模板 我正在尝试制作扩展默认小部件布局的仪表板小部件(在Boostrap中)。请注意,下面的代码使用的是Vue、Require、下划线和Axios 父文件-\u Global.vue <template> <div class="panel panel-default"> <div class="panel-heading">

我是Vue.js的新手,但正在努力掌握它。到目前为止,它进展顺利,我已经取得了相当大的进展,但我一直在扩展一个家长模板

我正在尝试制作扩展默认小部件布局的仪表板小部件(在Boostrap中)。请注意,下面的代码使用的是Vue、Require、下划线和Axios

父文件-\u Global.vue

<template>
    <div class="panel panel-default">
        <div class="panel-heading">
            <b>{{ widgetTitle }}</b>
            <div class="pull-right">
                <a href="#" v-on:click="toggleMinimized"
                   v-bind:title="(isMinimized ? 'Show widget' : 'Hide widget')">
                    <i class="fa fa-fw" v-bind:class="isMinimized ? 'fa-plus' : 'fa-minus'"></i>
                </a>
            </div>
        </div>
        <div class="panel-body" v-if="!isMinimized">


            <div class="text-center text-muted" v-if="!isLoaded">
                <i class="fa fa-spin fa-circle-o-notch"></i><br />
            </div>

            <parent v-if="isLoaded">
                <!-- parent content should appear here when loaded -->
            </parent>
        </div>
    </div>
</template>
<script>
    export default {

        // setup our widget props
        props: {
            'minimized': {
                'default': false,
                'required': false,
                'type': Boolean
            }
        },

        // define our data
        data: function () {
            return {
                widgetTitle: 'Set widget title in data',
                isLoaded: false,
                isMinimized: this.$props.minimized
            }
        },

        // when vue is mounted, open our widget
        mounted: function () {
            if(!this.isMinimized) {
                this.opened();
            }
        },

        // define our methods
        methods: {

            // store our widget state to database
            storeWidgetState: function () {

                // set our data to send
                let data = {
                    'action' : 'toggleWidget',
                    'widget' : this.$options._componentTag,
                    'state' : !this.isMinimized
                };

                // post our data to our endpoint
                axios.post(axios.endpoint, data);
            },

            // toggle our minimized data
            toggleMinimized: function (e) {

                // prevent default
                e.preventDefault();

                // toggle our minimized state
                this.isMinimized = !this.isMinimized;

                // trigger opened if we aren't minimized
                if(!this.isMinimized) this.opened();

                // save our widget state to database
                this.storeWidgetState();
            },

            // triggered when opened from being minimized
            opened: function () {
                console.log('opened() method is where all widget logic should be placed');
            }
        }

    }
</script>

当前,我的父模板正在完全覆盖我的子视图。我能让它工作的唯一方法是在components->parent:{}中显式定义模板参数,但我不想这样做…?

好的,感谢Gerardo Rosciano为我指明了正确的方向。我习惯于用老虎机来想出最终的解决办法。然后,我们访问父方法和数据属性,以使一切正常工作

示例.vue-我们的示例小部件

<template>
    <div>
        <widget-wrapper>
            <span slot="header">Example widget</span>
            <div slot="content">
                <img v-bind:src="image.src" v-bind:alt="image.alt"
                     v-if="image.src" class="img-responsive" style="margin: 0 auto" />

                {{ content }}
            </div>
        </widget-wrapper>
    </div>
</template>
<script>

    // import our widgets globals
    import WidgetWrapper from './_Widget.vue'

    export default {

        // setup our components
        components: {
            'widget-wrapper': WidgetWrapper
        },

        // set our elements props
        props: {
            'minimized': {
                'type': Boolean,
                'default': false,
                'required': false
            }
        },

        // setup our methods for this widget
        methods: {

            loadContent: _.debounce(function () {

                // make sure this can only be opened once
                if(this.hasBeenOpened) return;
                this.hasBeenOpened = true;

                // temporarily allow axios to make external requests
                let axiosHeaders = axios.defaults.headers.common;
                let vm = this;
                axios.defaults.headers.common = {};

                axios.get('https://yesno.wtf/api')
                    .then(function (res) {

                        // set our content
                        vm.content = null;

                        // set our image content
                        vm.image.src = res.data.image;
                        vm.image.alt = res.data.answer;

                    })
                    .catch(function (err) {

                        // set our error text
                        vm.content = String(err);

                    })
                    .then(function () {

                        // this will always hit..
                        vm.isLoaded = true;

                    });

                // restore our axios headers for security
                axios.defaults.headers.common = axiosHeaders;
            }, 300)
        },

        // additional data
        data: function () {
            return {

                // global param for parent
                isLoaded: false,

                // logic for the specific widget
                hasBeenOpened: false,
                content: 'Loaded and ready to go...',
                image: {
                    src: false,
                    alt: null
                }
            };
        },

    }
</script>

示例小部件
{{content}}
//导入我们的小部件全局
从“./\u Widget.vue”导入WidgetWrapper
导出默认值{
//设置我们的组件
组成部分:{
“小部件包装器”:WidgetWrapper
},
//设置我们的元素道具
道具:{
“最小化”:{
“类型”:布尔值,
“默认值”:false,
“必需”:false
}
},
//设置此小部件的方法
方法:{
loadContent:u.debounce(函数(){
//确保此文件只能打开一次
如果(此项已被取消)返回;
this.hasbeennopen=true;
//暂时允许axios发出外部请求
让axioheaders=axios.defaults.headers.common;
让vm=这个;
axios.defaults.headers.common={};
axios.get()https://yesno.wtf/api')
.然后(功能(res){
//设置我们的内容
vm.content=null;
//设置我们的图像内容
vm.image.src=res.data.image;
vm.image.alt=res.data.answer;
})
.catch(函数(err){
//设置我们的错误文本
vm.content=字符串(err);
})
.然后(函数(){
//这将永远击中。。
vm.isLoaded=true;
});
//恢复我们的axios头以确保安全
axios.defaults.headers.common=axioheaders;
}, 300)
},
//附加数据
数据:函数(){
返回{
//父级的全局参数
isLoaded:false,
//特定小部件的逻辑
已打开:错误,
内容:“已加载并准备就绪…”,
图片:{
src:错,
alt:null
}
};
},
}
\u Widget.vue-我们扩展的基本小部件

<template>
    <div class="panel panel-default">
        <div class="panel-heading">
            <b><slot name="header">Slot header title</slot></b>
            <div class="pull-right">
                <a href="#" v-on:click="toggleMinimized"
                   v-bind:title="(minimized ? 'Show widget' : 'Hide widget')">
                    <i class="fa fa-fw" v-bind:class="minimized ? 'fa-plus' : 'fa-minus'"></i>
                </a>
            </div>
        </div>
        <div class="panel-body" v-if="!minimized">
            <div class="text-center text-muted" v-if="!isLoaded">
                <i class="fa fa-spin fa-circle-o-notch"></i><br />
                Loading...
            </div>
            <div v-else>
                <slot name="content"></slot>
            </div>
        </div>
    </div>
</template>

<script>
    export default {

        // get loaded state from our parent
        computed: {
            isLoaded: function () {
                return this.$parent.isLoaded;
            }
        },

        // set our data element
        data: function () {
            return {
                minimized: false
            }
        },

        // when the widget is mounted, trigger open state
        mounted: function () {
            this.minimized = this.$parent.minimized;
            if(!this.minimized) this.opened();
        },

        // methods to manipulate our widget
        methods: {

            // save our widget state to database
            storeWidgetState: function () {

                // set our data to send
                let data = {
                    'action' : 'toggleWidget',
                    'widget' : this.$parent.$options._componentTag,
                    'state' : !this.minimized
                };

                // post this data to our endpoint
                axios.post(axios.endpoint, data);
            },

            // toggle our minimized state
            toggleMinimized: function (e) {

                // prevent default
                e.preventDefault();

                // toggle our minimized state
                this.minimized = !this.minimized;

                // trigger opened if we aren't minimized
                if(!this.minimized) this.opened();

                // save our widget state to database
                this.storeWidgetState();
            },

            // when widget is opened, load content
            opened: function () {

                // make sure we have a valid loadContent method
                if(typeof this.$parent.loadContent === "function") {
                    this.$parent.loadContent();
                } else {
                    console.log('You need to define a loadContent() method on the widget');
                }
            }
        }
    }
</script>

槽标题

加载。。。 导出默认值{ //从父级获取已加载状态 计算:{ isLoaded:函数(){ 返回此。$parent.isLoaded; } }, //设置我们的数据元素 数据:函数(){ 返回{ 最小化:false } }, //挂载小部件时,触发打开状态 挂载:函数(){ this.minimized=this.$parent.minimized; 如果(!this.minimized)this.opened(); }, //方法来操作我们的小部件 方法:{ //将小部件状态保存到数据库 storeWidgetState:函数(){ //设置要发送的数据 让数据={ “操作”:“toggleWidget”, “小部件”:此.$parent.$options.\u componentTag, 'state':!this.minimized }; //将此数据发布到我们的端点 post(axios.endpoint,数据); }, //切换我们的最小化状态 切换最小化:函数(e){ //防止违约 e、 预防默认值(); //切换我们的最小化状态 this.minimized=!this.minimized; //如果我们没有最小化,触发器就会打开 如果(!this.minimized)this.opened(); //将小部件状态保存到数据库 这个.storeWidgetState(); }, //当小部件打开时,加载内容 已打开:函数(){ //确保我们有一个有效的loadContent方法 if(此类型的$parent.loadContent==“函数”){ 这是.$parent.loadContent(); }否则{ log('您需要在小部件上定义loadContent()方法'); } } } }
嘿,克里斯,你已经试过老虎机了吗@GerardoRosciano看起来非常接近我想要的,但我不太确定是否要重构我现有的代码。。。例如,我还能用那个调味品吗??我可以有许多不同名称的模板。问题是,每当我创建带有标记的.vue文件时,它都会完全覆盖主模板…@chis,我不确定是否使用混合。我要做的是反转compos,我会使用一个叫做using和ins的小部件组件
<template>
    <div class="panel panel-default">
        <div class="panel-heading">
            <b><slot name="header">Slot header title</slot></b>
            <div class="pull-right">
                <a href="#" v-on:click="toggleMinimized"
                   v-bind:title="(minimized ? 'Show widget' : 'Hide widget')">
                    <i class="fa fa-fw" v-bind:class="minimized ? 'fa-plus' : 'fa-minus'"></i>
                </a>
            </div>
        </div>
        <div class="panel-body" v-if="!minimized">
            <div class="text-center text-muted" v-if="!isLoaded">
                <i class="fa fa-spin fa-circle-o-notch"></i><br />
                Loading...
            </div>
            <div v-else>
                <slot name="content"></slot>
            </div>
        </div>
    </div>
</template>

<script>
    export default {

        // get loaded state from our parent
        computed: {
            isLoaded: function () {
                return this.$parent.isLoaded;
            }
        },

        // set our data element
        data: function () {
            return {
                minimized: false
            }
        },

        // when the widget is mounted, trigger open state
        mounted: function () {
            this.minimized = this.$parent.minimized;
            if(!this.minimized) this.opened();
        },

        // methods to manipulate our widget
        methods: {

            // save our widget state to database
            storeWidgetState: function () {

                // set our data to send
                let data = {
                    'action' : 'toggleWidget',
                    'widget' : this.$parent.$options._componentTag,
                    'state' : !this.minimized
                };

                // post this data to our endpoint
                axios.post(axios.endpoint, data);
            },

            // toggle our minimized state
            toggleMinimized: function (e) {

                // prevent default
                e.preventDefault();

                // toggle our minimized state
                this.minimized = !this.minimized;

                // trigger opened if we aren't minimized
                if(!this.minimized) this.opened();

                // save our widget state to database
                this.storeWidgetState();
            },

            // when widget is opened, load content
            opened: function () {

                // make sure we have a valid loadContent method
                if(typeof this.$parent.loadContent === "function") {
                    this.$parent.loadContent();
                } else {
                    console.log('You need to define a loadContent() method on the widget');
                }
            }
        }
    }
</script>