x-chat
x-chat copied to clipboard
不太明白你封装的toast组件为什么分开写了一个.vue和.js文件
- 你封装的组件为什么是分开的呢?这样有什么好处?
- 我也不明白这里为什么要这么写?
import Vue from "vue";
const ToastConstructor = Vue.extend(require('./toast.vue'));
let instance = new ToastConstructor().$mount('');
document.body.appendChild(instance.$el);
翻看文档知道这里意思是想渲染在app元素之外,为什么要这么弄呢?
我这样写的好处就是既实现了事件管理又易于复用。其实怎么写应该根据你的项目和习惯去做。可参考知乎上的回答:https://www.zhihu.com/question/35820643
全部写在一个不是也可以复用吗?这样写在什么情况下易于复用呢?
如果是按照vue组件的规范写在一个vue文件里面,注册为全局组件,此时就需要通过vue所提倡的状态管理,而不是事件管理了。同时为了规范需要把状态保存到vuex的store中,我不太喜欢这样的形式去管理这种多处使用的小组件。这样写,如果别的项目也用到直接copy就好了,不用再去store增加状态管理
emmm,让我理解下,
import Vue from "vue";
const ToastConstructor = Vue.extend(require('./toast.vue'));
let instance = new ToastConstructor().$mount('');
document.body.appendChild(instance.$el);
这样的写法,貌似这个toast就是一个单独的vm实例,跟app下的那个实例还不一样?这个实例挂载在toast相关的html上?唯一的联系就是这个实例时app vm原型的一个方法?是这个意思么? 另外还有那里为什么$mount(''),里面是空的是什么意思?
上面代码其实就是做了下面3步:
- 创建VUE子类
- 将实例挂载。
vm.$mount('')
代表elementOrSelector
参数为空,模板将被渲染为文档之外的的元素,必须使用原生 DOM API 把它插入文档中 - 用原生插入到body中
如果写成一个VUE文件:
全局注册 Vue.component(tagName, options) =>
放在根组件内 => 使用状态管理 或者$refs
去获取元素实例
第一种使用:
store.commit('showModel','some message...',2000);
第二种使用
this.$refs.model.show('some message...',2000);
emmmmm,写成一个VUE文件我能想到的就这两种方式。个人觉得这两种方式都不太好。
不好意思,这两天都在看这方面的东西,那个知乎看了几遍了,现在才想起你这里的回复,不过现在再来看你的回复能看懂了。
像这个vm.$mount('')
是我没仔细看文档,文档都有,我看了知乎那篇文章后,觉得像toast这种只是简单提示的,是可以放在body下的。
按照你说的写成一个vue文件,然后放在app组件下,之后用你说的两种方式调用,第一种我觉得要引入vuex或者eventbus是不太好,
但是第二种在某个子组件使用的话使用this.$refs没法直接获取跟组件下的弹窗组件吧?第二种的不太好指的哪里呢?
另外像你的做法如果想引入slot来定制内容怎么做?异步插入没法引入slot吧?我想的就是这种情况需要注册为全局组件然后引入到子组件中定制slot,接着在这个全局组件绑定事件和传入需要的prop,不知道是不是这样做呢?
第二种方式的确不能获取根组件下的,我之前描述错了。需要在每个用到的组件下引用。这样就不能确保单例。所以不太好使。 如果想引入slot,模版渲染就成了一个难题,知乎的回答上已经有人做了回答——参考Jim Liu 和agileago的回答。 个人认为需要slot的组件都是难以复用的组件,最好还是特殊对待。像alert,propmt这样的组件在业务逻辑不是很复杂的情况下 可以考虑放在根组件下。可参考https://segmentfault.com/a/1190000011650003
segmentfault那个也是你写的吧?知乎那俩大神写的方案没给出具体事例不知道具体怎么实现, 你的推荐那篇文章中
return new Promise(function(resolve,reject) {
instance.$refs.cancelBtn.addEventListener('click',function() {
instance.show = false;
resolve(false);
});
instance.$refs.okBtn.addEventListener('click',function() {
instance.show = false;
resolve(true);
})
})
这里我是用instance.$on('')来监听组件中$emit的事件的,你这样写貌似也可以,不过这两者是有什么深层的区别?或者优缺点?另外你有没有写过需要引入slot的?
emmmmm,我之前写这个组件的时候没有想到用instance.$on('');哈哈,经验不够,看来还得努力学习。我觉得用instance.$on('')更好一些. 知乎说的插件vue-dom-portal,其实就是一个slot。你可以在任何地方写一个slot——它的指令v-dom-portal就相当于slot。然后指定一个位置插入就可以了。 比如我在test.vue中写了一个
<template>
<div class="bg-grey">
<div v-dom-portal="'body'" style="background-color: blue;position: fixed; z-index:100;width: 200px;height:200px;">
<p style="text-align: center;color:#fff;">我可以被插入当DOM的任何位置</p>
</div>
</div>
</template>
我给它传的portal是body,所以他会被渲染到body中;
<body class="half-border">
<div id="app">
<div class="bg-grey child-view"><!----></div>
</div>
<div style="background-color: blue; position: fixed; z-index: 100; width: 200px; height: 200px;">
<p style="text-align: center; color: rgb(255, 255, 255);">我可以被插入当DOM的任何位置</p>
</div>
</body>
这样就实现了全局的slot,你把portal换成全局的alert,propmt这种组件,便可以实现你想要得效果啦