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