gpt4 book ai didi

javascript - 从子项访问父项的 $refs - Vue.js

转载 作者:行者123 更新时间:2023-11-30 14:33:22 25 4
gpt4 key购买 nike

希望之前已经回答过这个问题 - 本质上,我正在尝试将一个 block (“CodeBlock.vue”)附加到 App.vue 中的一个元素,该事件来自 CodeBlock 的同级和 App 的子级内部触发的 onClick 事件。 vue,(“ButtonSidebar.vue”)。我对发出事件和/或使用 eventBus Vue 实例感到有点困惑,因此非常感谢任何指针:

到目前为止,我有以下内容。 CodeBlock.vue 将用作实例并附加到 App.vue 内的 div。

代码块.vue:

<template>
<div :class="type">
THIS IS A CODE BLOCK!!
</div>
</template>

<script>
export default {
name: 'CodeBlock',
props: [ 'type' ]
}
</script>

App.vue:

<template>
<div id="app" class="container">
<ButtonSidebar/>
<div id="pageBlocks" ref="container"></div>
</div>
</template>

<script>
import Vue from 'vue'
import BootstrapVue from 'bootstrap-vue'

// import { eventBus } from './main'

import AddTitle from './components/modules/AddTitle'
import AddSubTitle from './components/modules/AddSubTitle'
import ButtonSidebar from './components/modules/ButtonSidebar'
import CodeBlock from './components/modules/CodeBlock'

import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'

Vue.use(BootstrapVue)

export default {
name: 'App',
components: {
AddTitle,
AddSubTitle,
ButtonSidebar,
CodeBlock
}
}
</script>

<style>
#app {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #1f1f1f;
margin-top: 60px;
}

.no-border {
border: unset !important;
border: 0px !important;
}
</style>

ButtonSidebar.vue:

<template>
<div>
<b-button class="btn-circle absolute-float-tight text-dark" v-on:click="reveal=!reveal">
<font-awesome-icon v-if="!reveal" :icon="faPlusIcon" />
<font-awesome-icon v-if="reveal" :icon="faMinusIcon" />
</b-button>
<transition name="custom-classes-transition" enter-active-class="animated bounceInDown" leave-active-class="animated bounceOutRight">
<div v-if="reveal" class="absolute-float-reveal">
<b-button class="btn-circle text-dark" v-on:click="addCodeBlock"><font-awesome-icon :icon="faCodeIcon" /></b-button>
</div>
</transition>
</div>
</template>

<script>
import Vue from 'vue'

import FontAwesomeIcon from '@fortawesome/vue-fontawesome'
import faPlus from '@fortawesome/fontawesome-pro-regular/faPlus'
import faMinus from '@fortawesome/fontawesome-pro-regular/faMinus'
import faCode from '@fortawesome/fontawesome-pro-regular/faCode'

import CodeBlock from './CodeBlock'

export default {
name: 'ButtonSidebar',
computed: {
faPlusIcon () {
return faPlus
},
faMinusIcon () {
return faMinus
},
faCodeIcon () {
return faCode
}
},
components: {
FontAwesomeIcon,
CodeBlock
},
data () {
return {
reveal: false
}
},
props: ['codeBlocks'],
methods: {
addCodeBlock () {
var ComponentClass = Vue.extend(CodeBlock)
var instance = new ComponentClass({
propsData: { type: 'primary' }
})
instance.$mount()

this.$el.querySelector('#pageBlocks').appendChild(instance.$el)
}
}
}
</script>

<style scoped>

.absolute-float-tight {
left: 20px;
position: absolute;
}

.absolute-float-reveal {
left: 60px;
position: absolute;
}

.btn-circle {
background-color: transparent;
border-radius: 50%;
height: 34px;
padding: 0;
width: 34px;
}

</style>

围绕 this.$el.querySelector('#pageBlocks').appendChild(instance.$el) 部分,我开始有点松散情节......我很担心也许我必须剥离一切并重新开始?

最佳答案

您应该尽可能避免访问 DOM。数据的真实来源应该在您的组件中。refs 对于集成其他需要 DOM 元素的 js 库非常有用。

所以在你的情况下,假设 codeBlocks 在你的 App.vue 组件中可用, SidebarButton 需要在被点击时发出一个事件以便父 App.vue 可以添加一个新的 Codeblock:

(我删除了一些示例不需要的代码。CodeBlock.vue 保持不变)

App.vue

<template>
<div id="app" class="container">
<ButtonSidebar @add-block="addCodeBlock" />
<CodeBlock v-for="block in codeBlocks" :type="block.type" />
</div>
</template>

<script>
import ButtonSidebar from '../ButtonSidebar'
import CodeBlock from '../CodeBlock'

export default {
name: 'App',

components: {ButtonSidebar, CodeBlock},

data() {
return {
codeBlocks: []
}
},
methods: {
addCodeBlock() {
const newBlock = {type: 'whatever'}
this.codeBlocks.push(newBlock)
}
}
}
</script>

ButtonSideBar.vue

<template>
<div>
<b-button class="btn-circle text-dark" v-on:click="addCodeBlock</b-button>
</div>
</template>

<script>
export default {
name: 'ButtonSidebar',

data () {
return {
reveal: false
}
},

methods: {
addCodeBlock () {
this.$emit('add-block')
}
}
}
</script>

在 Vue 中遵循的一个很好的模式是将状态提升给 parent ,并在您想要在 parent 和 child 之间共享状态时将其作为 Prop 传递下去。

关于javascript - 从子项访问父项的 $refs - Vue.js,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50823961/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com