# 七.特殊窗口(对话框)
前言 --> 弹框组件特点
- 下拉菜单组件应该由两部分组成:
- 选中项的文本
- 待选菜单(默认隐藏)
- 它的主要功能包括:
- 鼠标经过下拉菜单组件,显示待选菜单
- 鼠标滑出下拉菜单组件,隐藏待选菜单
- 鼠标点击待选菜单中的条目,选中项文本更新,组件派发 change 事件
# 1.目录结构
├── dialog
│ ├── dialog.vue
│ └── index.js
2
3
# 1.使用场景
平时我们开发时我们写的组件基本上都是通过#app 实现挂载在页面的。
import Vue from "vue"
import App from "./app.vue"
new Vue({
el: "#app",
render: (h) => h(App),
})
2
3
4
5
6
这样的组建使用方式,有几个特点:
- 所有的内容,都是在
#app
节点内渲染的 - 组件的模板,是事先定义好的
- 由于组件的特性,注册的组件只能在当前位置渲染
如果在一些特殊的场景下就比较局限了:
- 组件的模板是通过调用接口从服务端获取的,需要动态渲染组件
- 实现类似原生
window.alert()
的提示框组件,它的位置是在<body>
下,而非<div id="app">
,并且不会通过常规的组件自定义标签的形式使用,而是像 JS 调用函数一样使用。
一般来说,在我们访问页面时,组件就已经渲染好了,对于第一个场景,组件的渲染是异步的,甚至预先不知道模板是什么。对于第二个场景,通过操作 dom 很容易实现。对于这两种场景,在 vue 中我们可以通过 Vue.extend 和 vm.$mount 来实现
# 2.用法
创建一个 vue 实例,都会有一个选项el
,来指定实例的根节点,如果不写el
选项,那组件就处于未挂载状态。Vue.extend
的作用,就是基于 Vue 构造器,创建一个子类,它的参数和new Vue
的基本一致,但data
要和组件一样,是个函数,再配合$mount
,就可以让组件渲染,并且挂载到任意指定的节点上。
创建一个构造器,解决异步获取 template 模板的问题
import Vue from "vue"
const AlertComponent = Vue.extend({
template: "<div>{{message}}</div>",
data() {
return {
message: "hello",
}
},
})
2
3
4
5
6
7
8
9
手动渲染组件,并且挂载到 body 下
const component = new AlertComponent().$mount()
document.body.appendChild(component.$el)
2
当然,除了 body,你还可以挂载到其他节点上
$mount
也有一些快捷的挂载方式,以下两种都是可以的
// 在$mount里写参数来指定挂载的节点
new AlertComponent().$mount("#app")
// 不用$mount,直接在创建实例是指定el选项
new AlertComponent({ el: "#app" })
2
3
4
除了用 extend 外,也可以直接创建 Vue 实例,并且用一个 Render 函数来渲染一个.vue 文件:
import Vue from "vue"
import Notification from "./notification.vue"
const props = {}
const Instance = new Vue({
render(h) {
return h(Notification, {
props: props,
})
},
})
const component = Instance.$mount()
document.body.appendChild(component.$el)
2
3
4
5
6
7
8
9
10
11
12
13
14
这样既可以使用.vue 来写复杂的组件,还可以根据需要传入适当的 props。渲染后,如果想操作 Render 的Notfication
实例,也是很简单的:
const notification = Instance.$children[0]
因为 Instance 下只 render 了 Notification 一个子组件,所以可以额用$children[0]
访问到
需要注意的是,我们使用$mount
手动渲染组件,如果要销毁,也要用$destory
来手动销毁实例,必要时,也可以用removeChild
把节点从 DOM 中移除
使用场景
我们在写 Vue.js 时,不论是用 CDN 的方式还是在 Webpack 里用 npm 引入 Vue.js,都会有一个根节点,并且创建一个根实例,比如:
<body>
<div id="app"></div>
</body>
<script>
const app = new Vue({
el: "#app",
})
</script>
2
3
4
5
6
7
8
Webpack 也类似,一般在入口文件 main.js 里,最后会创建一个实列:
import Vue from "vue"
import App from "./app.vue"
new Vue({
el: "#app",
render: (h) => App,
})
2
3
4
5
6
7
因为用 Webpack 基本都是前端路由的,它的 html 里一般都只有一个根节点<div id="app"></div>
,其余都是通过 JavaScript 完成,也就是许多的 Vue.js 组件(每个页面也是一个)。
有了初始化的实例,之后所有的页面,都由 vue-router 帮我们管理,组件也都是用import
导入后局部注册(也有在 main.js 全局注册的),不管哪种方式,组件(或页面)的创建过程我们是无需关心的,只是写好.vue
文件并导入即可。这样的组件使用方式,有几个特点:
- 1.所有的内容,都是在
#app
节点内渲染的; - 2.组件的模板,是事先定义好的
- 3.由于组件的特性,注册的组件只能在当前位置渲染
← 六.导航(菜单) 七.特殊窗口(警告提示) →