new vue()、vue.extend、 component、vue.use、render的理解
new Vue({}), Vue.extend, 和 Vue.component 是 Vue.js 框架中用于创建和管理组件的核心方法,它们在构建 Vue 应用时扮演着不同的角色。下面分别解释这三个方法的用途和用法:
1. new Vue({})
- 作用: 创建并返回一个Vue实例。这是启动Vue应用的常见方式,通过指定选项如
el、data、methods等配置Vue实例的行为。 - 使用场景: 作为应用程序的主要入口点,负责挂载Vue实例到DOM中的某个元素,并管理数据、模板、方法等
这是创建一个 Vue 实例的最直接方式。当你初始化一个 Vue 应用时,基本上就是在创建一个根 Vue 实例。这个实例是整个应用的入口点,可以挂载到 DOM 中的一个元素上,并且可以包含数据、计算属性、方法、生命周期钩子等。
用法示例:
var app = new Vue({
el: '#app', // 指定挂载元素
data: { // 数据对象
message: 'Hello Vue!'
},
methods: { // 方法集合
reverseMessage: function() {
this.message = this.message.split('').reverse().join('')
}
}
})
2. Vue.extend()
- 作用: 创建一个Vue构造函数的子类,用于扩展Vue的基本功能,为创建可复用的组件构造器提供基础。通过扩展,可以向组件添加默认属性、方法等。
- 使用场景: 当你需要定义具有特定配置的组件模板,并希望在多个地方复用时,可以先使用
Vue.extend定义组件构造器,再实例化使用。
Vue.extend() 方法用于创建一个 Vue 的子类,即扩展一个基础的 Vue 构造器。这个方法主要用于定义可复用的组件构造器。通过扩展 Vue 构造器,你可以添加自定义的选项和默认值,然后使用这个扩展过的构造器来创建组件实例。
用法示例:
// 定义一个基组件构造器
var MyComponent = Vue.extend({
template: '<div>我是基础组件内容</div>',
data: function() {
return {
customData: '自定义数据'
}
}
});
// 使用扩展后的构造器创建组件实例
var myComponentInstance = new MyComponent().$mount('#my-component');
3. Vue.component()
- 作用: 全局注册组件。允许你在应用的任何地方使用该组件,无需再次导入或局部注册。
- 使用场景: 当一个组件需要被频繁复用,并且希望在整个应用中都能直接通过标签名访问时,使用此方法进行全局注册。
Vue.component() 是全局注册组件的方法。它接受两个参数:第一个是组件的名称(字符串),第二个是组件的选项对象或扩展构造器。这个方法使你可以在整个 Vue 应用中使用该组件,而不需要每次使用时都手动导入和注册。
用法示例:
Vue.component('my-component', {
template: `<div>我是全局注册的组件</div>`
});
// 然后在任何 Vue 模板中直接使用 <my-component></my-component>
new Vue({
el: '#app'
});
4. Vue.use()
-
作用: 注册或安装Vue插件。Vue插件可以为Vue增加全局功能或改变Vue的行为。
-
使用场景: 当你需要在应用中使用第三方库或自定义插件(如Vuex、Vue Router)时,使用
Vue.use(Plugin)来安装并配置插件。// myPlugin.js const MyPlugin = { install(Vue, options) { // 1. 添加全局方法或属性 Vue.myGlobalMethod = function() { console.log('Hello from my global method'); }; // 2. 添加全局资源 (指令/过滤器等) Vue.directive('my-directive', { bind(el, binding, vnode) { // 在指令第一次绑定到元素时调用 el.textContent = `Custom directive bound with value: ${binding.value}`; } }); // 3. 添加实例方法 Vue.prototype.$myMethod = function() { console.log('Called myMethod from instance'); }; // 可以根据options进行一些初始化设置 if (options && options.someOption) { console.log('Options someOption:', options.someOption); } } }; export default MyPlugin; Vue.use(MyPlugin)
5. render函数
-
作用: 提供一个更灵活的方式来生成Vue实例的虚拟DOM结构。相比于模板字符串,
render函数提供了程序化的DOM生成方式,适用于复杂的动态渲染逻辑或与第三方库集成的场景。 -
使用场景: 当模板表达能力不足以满足需求,或者需要根据条件动态渲染完全不同的DOM结构时,可以使用
render函数来自定义渲染逻辑。
案例使用:
简单使用
let TempConstructor = Vue.extend({
template: "<div @click='handleClick'>我是extend组件内容</div>",
data: function () {
return {
customData: "自定义数据",
};
},
methods: {
handleClick: function () {
console.log(this.customData, "customData");
},
},
});
let instance = new TempConstructor({
data: function () {
return {
customData1: "自定义数据",
};
},
});
instance.vm = instance.$mount();
document.body.appendChild(instance.vm.$el);
console.log(instance, "instance");
Vue.extend 命令式弹窗
<!--
Messagebox弹框,基于element-Dialog
全局居中显示
中间内容为文字
【传参说明】
见data
【使用示例】
this.$MessageBox({
type: 'info', //类型,默认info
title: '提示', //必填项
content: '此操作将永久删除该文件, 是否继续?' //非必填项
btnText: ['取消', '去编辑'] //非必填项
})
.then(() => {
setTimeout(() => {
console.log('删除成功啦!')
}, 2000)
})
.catch(() => {
console.log('取消删除啦')
})
-->
<template>
<el-dialog
:append-to-body="true"
custom-class="custom-messagebox"
class="custom-messagebox-wrapper"
:visible="dialogVisible"
:width="width"
@close="close"
>
<div class="message-title font16 bold">
<svg-icon
:icon-class="iconObj.icon"
class-name="icon-size-24"
:style="{'color': iconObj.color}"
/>
<span class="title-text ml8">{{ title }}</span>
</div>
<div class="mt16 pl32 font14" v-if="content">
<span v-html="htmlContent"></span>
{{ content }}
</div>
<span slot="footer" class="dialog-footer">
<el-button @click.stop="handleClose" size="small">{{
btnText[0]
}}</el-button>
<el-button v-if="btnText[1]"
:loading="comfirmLoading"
type="primary"
@click.stop="handleEvent"
size="small"
>{{ btnText[1] }}</el-button
>
</span>
</el-dialog>
</template>
<script>
export default {
name: "Messagebox",
model: {
prop: "visible",
event: "change",
},
props: {
// 显示,在子组件v-model传入
visible: {
type: Boolean,
default: false,
},
},
watch: {
visible(val) {
this.dialogVisible = val;
},
},
data() {
return {
type: 'info', //提示类型,可选值:info/warning/error/ask
dialogVisible: false,
title: "", // 标题,String类型,必传
content: "", // message的内容
width: "480px", // 弹框宽度,默认480px
btnText: ["取消", "确认"], // footer的两个按钮文字,数组类型,默认为['取消','确认']
comfirmLoading: false,
htmlContent: '',//自定义内容节点
};
},
created() {
this.iconMap = {
info: { //提示
icon: 'icon_tips_dark',
color: '#397BFD'
},
warning: { //警告
icon: 'icon_tips_dark',
color: '#ffba00'
},
error: { //错误
icon: 'icon_close_dark',
color: '#ff4949'
},
ask: { //询问
icon: 'icon_help_dark',
color: '#397BFD'
}
}
},
computed: {
iconObj() {
return this.iconMap[this.type]
}
},
methods: {
// 关闭
close() {
this.comfirmLoading = false
this.dialogVisible = false;
},
// 取消按钮
handleClose() {},
// 确认按钮
handleEvent() {},
},
};
</script>
<style lang="scss">
.custom-messagebox-wrapper {
.custom-messagebox {
margin-top: 0 !important;
top: 50%;
transform: translateY(-50%);
.el-dialog__body {
padding: 24px 40px 24px 32px;
}
.message-title {
display: flex;
color: $font-main;
line-height: 24px;
.title-text {
width: 0;
flex: 1;
}
}
.message-content {
color: $font-minor;
line-height: 22px;
}
.el-dialog__footer{
border: 0;
}
}
}
</style>
// Vue.extend
import MessageBox from './index.vue'
let instance = null
let showToast = false
const mMessageBox = {
install(Vue, options = {}) {
let opt = MessageBox.data()
Object.assign(opt, options)
Vue.prototype.$MessageBox = (message) => {
return new Promise((resolve, reject) => {
if (message) {
opt = {
...message,
}
}
// 判断当前实例是否已存在
if (!instance) {
let TempConstructor = Vue.extend(MessageBox)
instance = new TempConstructor({
data: opt,
})
instance.vm = instance.$mount()
document.body.appendChild(instance.vm.$el)
} else {
Object.assign(instance, MessageBox.data(), opt)
}
instance.vm.dialogVisible = showToast = true
instance.handleClose = function () {
reject()
instance.vm.dialogVisible = showToast = false
}
instance.handleEvent = function () {
instance.vm.comfirmLoading = true
resolve()
setTimeout(() => {
instance.vm.dialogVisible = showToast = false
})
}
})
}
},
}
export default mMessageBox
new Vue创建弹窗
<template>
<el-dialog
title="提示"
:visible.sync="dialogVisible"
width="30%"
:before-close="handleClose"
>
<span>这是一段信息</span>
<span slot="footer" class="dialog-footer">
<el-button @click="handleClose">取 消</el-button>
<el-button type="primary" @click="handleSubmit">确 定</el-button>
</span>
</el-dialog>
</template>
<script>
export default {
model: {
prop: 'visible',
event: 'change',
},
props: {
// modal的显示,在父组件v-model传入
visible: {
type: Boolean,
default: false,
},
// 认领id
id: {
type: [Number, String],
default: '',
},
},
data() {
return {
dialogVisible: false,
}
},
watch: {
visible(val) {
this.dialogVisible = val
},
},
methods: {
handleClose() {
this.$emit('handleClose', false)
},
handleSubmit() {
this.$emit('handleSubmit', this.id)
},
},
}
</script>
<template>
<el-button @click="handleShow">点击开启弹窗</el-button>
</template>
<script>
import myDialog from './myDialog.vue'
import Vue from 'vue'
import store from '@/store'
export default {
data() {
return {
visible: false,
}
},
methods: {
// 发起弹窗
handleShow() {
// 弹窗已经存在,不再挂载
if (this.divName) {
this.visible = true
return
}
this.divName = 'main-mount-div'
// 创建
let instance = new Vue({
el: document.createElement('div'),
store,
render: (h) =>
h(myDialog, {
class: this.divName,
props: {
id: '111',
visible: this.visible,
},
on: {
handleSubmit: this.submitEdit,
handleClose: this.closeEditDialog,
},
}),
})
document.body.appendChild(instance.$el)
this.$nextTick(() => {
this.visible = true
})
},
submitEdit(params) {
console.log(params)
this.divName = ''
this.visible = false
},
closeEditDialog(value) {
console.log(value)
this.divName = ''
this.visible = false
},
},
}
</script>