vue实例
Posted 前端js动力节点
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue实例相关的知识,希望对你有一定的参考价值。
今天教大家动手做个vue插件,这个技能也是必须要掌握的,在项目中肯定用得到。
这节课的干货有点多,大家做好心理准备,一次看不完的话可分两次或三次看,千万别勉强哦~~
那么熟悉jquery的同学都知道,封装一个jquery插件,都是有一套固定规则的,按照这套规则走就ok,比如是酱紫的:
(function ($) {
$.fn.myPlugin = function () {
//你自己的插件代码
};
})(jQuery);
那么vue呢?
其实也是一样的,他也有这么一套固定的规则,我们先来看一下手册是怎么说的:
其实我们只要提取这样几点信息就好:
1.公开方法install。
2.install方法第一个参数是vue构造器。
3.在vue构造器上可以追加自定义方法。
具体应该怎么来写呢?我们以比较常用的一个插件——toast,为例来讲解一下。
我们新建一个plugins目录,后面与插件有关的文件都放在这里。
toast.js:
var Toast = {};
Toast.install = function (Vue, options) {
Vue.prototype.$toast = function(){
alert('hello,world');
};
}
export default Toast;
这个肥肠煎蛋,就是在vue的原型prototype上挂载了一个方法。
既然是挂在prototype上的方法,那必须要实例化才能访问了。那么vue在哪里做的实例化呢?肯定是入口main.js了。
main.js:
import Vue from 'vue'
import App from './App'
import router from './router'
import Toast from './plugins/toast'
Vue.use(Toast);
new Vue({
el: '#app',
router,
template: '<App/>',
components: { App }
})
通过调用Vue.use()方法,就可以把Toast插件包含到全局Vue;然后进行vue实例化后,任何组件都可以通过this调用到Toast了。
我们在入口组件App.vue调用下看看:
App.vue:
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'app',
mounted(){
this.$toast();// 通过this即可调用到
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
运行一下:
看来已经生效了哈~~
以上就是vue插件的基本套路,大家已经明白了吧?
既然懂了的套路,下面我们就可以真正做一个Toast插件出来了吧?
先别急,既然这里涉及到了vue构造器,我们先来玩一下这个玩意。
那么一个组件到底是如何渲染到页面上的呢?我们看个简单的例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue构造器</title>
<script src="https://cdn.bootcss.com/vue/2.4.2/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 3. #app是Vue实例挂载的元素,应该在挂载元素范围内使用组件-->
<my-component></my-component>
</div>
</body>
</html>
<script>
// 1.创建一个组件构造器
var myComponent = Vue.extend({
template: '<div>这是一个组件</div>'
})
// 2.注册组件,并指定组件的标签,组件的HTML标签为<my-component>
Vue.component('my-component', myComponent)
//3.实例化
var vueobj = new Vue({
el: '#app'
});
//如何访问到dom节点?
console.log(vueobj.$el);
</script>
Vue.js的组件的使用有3个步骤:
创建组件构造器、注册组件和使用组件。
如下图所示:
注意
1. Vue.extend()是Vue构造器的扩展,调用Vue.extend()创建的是一个组件构造器,而不是一个具体的组件实例。
2. Vue.extend()构造器有一个options选项对象,options对象的template属性用于定义组件要渲染的HTML。
3. 使用Vue.component()注册组件时,需要提供2个参数。第1个参数时组件的标签,第2个参数是组件构造器。
4. Vue.component()方法内部会调用组件构造器,创建一个组件实例。
5. 组件应该挂载到某个Vue实例下,否则它不会生效。
看下手册是怎么说的:
官方示例:
注册组件我们还可以这么写:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue构造器</title>
<script src="https://cdn.bootcss.com/vue/2.4.2/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 3. #app是Vue实例挂载的元素,应该在挂载元素范围内使用组件-->
<my-component></my-component>
</div>
</body>
</html>
<script>
var myComponent = Vue.extend({
template: '<div>这是一个组件</div>'
})
var vueobj = new Vue({
el: '#app',
components: {
'my-component': myComponent
}
});
console.log(vueobj.$el);
</script>
当Vue实例不指定el属性时,则该实例尚没有挂载到某个dom中。此时我们可以调用$mount()方法来手动挂载。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue构造器</title>
<script src="https://cdn.bootcss.com/vue/2.4.2/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 3. #app是Vue实例挂载的元素,应该在挂载元素范围内使用组件-->
<my-component></my-component>
</div>
</body>
</html>
<script>
// 1.创建一个组件构造器
var myComponent = Vue.extend({
template: '<div>这是一个组件</div>'
});
// 2.注册组件,并指定组件的标签,组件的HTML标签为<my-component>
Vue.component('my-component', myComponent);
//3.实例化,不指定el
var vueobj = new Vue();
vueobj.$mount('#app');//手动挂载
//如何访问到dom节点?
console.log(vueobj.$mount('#app').$el);
</script>
那么如果不注册组件,直接实例化组件构造器可不可以呢?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue构造器</title>
<script src="https://cdn.bootcss.com/vue/2.4.2/vue.js"></script>
</head>
<body>
<div id="app">
<div id="comp"></div>
</div>
</body>
</html>
<script>
// 1.创建一个组件构造器
var myComponent = Vue.extend({
template: '<div>这是一个组件</div>'
})
var vueobj = new myComponent().$mount('#comp');//挂载组件
//如何访问到dom节点?
console.log(vueobj.$el);
</script>
甚至不指定挂载的dom,用原生js的方式追加节点呢?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue构造器</title>
<script src="https://cdn.bootcss.com/vue/2.4.2/vue.js"></script>
</head>
<body>
<div id="app">
</div>
</body>
</html>
<script>
// 1.创建一个组件构造器
var myComponent = Vue.extend({
template: '<div>这是一个组件</div>'
})
var vueobj = new myComponent().$mount();//挂载
//如何访问到dom节点?
console.log(vueobj.$el);
var app = document.getElementById('app');
app.appendChild(vueobj.$el);
</script>
那是否可以在组件实例化的时候传参呢?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue构造器</title>
<script src="https://cdn.bootcss.com/vue/2.4.2/vue.js"></script>
</head>
<body>
<div id="app">
</div>
</body>
</html>
<script>
// 1.创建一个组件构造器
var myComponent = Vue.extend({
template: '<div>{{tips}}</div>'
})
var dataobj = {
data(){
return {
tips: 'hello,world'
}
}
};
var vueobj = new myComponent(dataobj).$mount();//挂载
//如何访问到dom节点?
console.log(vueobj.$el);
var app = document.getElementById('app');
app.appendChild(vueobj.$el);
</script>
统统都是ok的。
这几种写法,大家要仔细把玩对比一下。代码比较简单,这里不多赘述。
回归主题,我们继续来写toast效果。
toast.js:
var Toast = {};
Toast.install = function (Vue, options) {
Vue.prototype.$toast = (tips) => {
let toastComponent = Vue.extend({ // 1、创建构造器,定义好提示信息的模板
template: '<div class="vue-toast">' + tips + '</div>'
});
let tpl = new toastComponent().$mount().$el; // 2、创建实例
document.body.appendChild(tpl); // 3、把创建的实例添加到body中
setTimeout(function () { // 4、延迟2秒后移除该提示
document.body.removeChild(tpl);
}, 2000)
}
}
export default Toast;
有了前面的知识储备,这里就能看懂了吧?
这里有个vue-toast样式,该怎么引入呢?
main.js:
import Vue from 'vue'
import App from './App'
import router from './router'
import "./assets/style.css"
import Toast from './plugins/toast'
Vue.use(Toast);
new Vue({
el: '#app',
router,
template: '<App/>',
components: { App }
})
我们将样式作为模块引入即可。
style.css:
.vue-toast{
width:200px;
height:30px;
line-height:30px;
text-align:center;
color:#fff;
background:#000;
margin:0 auto;
}
App.vue:
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'app',
mounted(){
this.$toast("出错了");// 通过this即可调用到
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
仍旧是通过this即可调用。我们看一下效果:
css样式大家可以完善一下哈。
这样虽然是实现了,但还不能算完美。
因为这个例子的dom只有一个div,我们可以直接在构造器的template里面拼接字符串,但如果dom比较多呢?
况且toast组件本就应该是一整体,我们这么搞就破坏了组件的整体性。
下面我们将toast封装为组件。
plugins->toast.vue:
<template>
<div class="vue-toast" v-if="isShow">{{tips}}</div>
</template>
<script>
export default {
name:'toastCom',
data () {
return {
tips: '',
time: 2000,
isShow: true
}
},
mounted () {
this.close()
},
methods: {
close () {
var that = this;
setTimeout(function() {
that.isShow = false
}, this.time);
}
}
}
</script>
<style scoped>
.vue-toast{
width:200px;
height:30px;
line-height:30px;
text-align:center;
color:#fff;
background:#000;
margin:0 auto;
}
</style>
让toast加载后几秒钟消失,这个功能本来就是组件本身的,这样设计是再合适不过啦!
组件声明好了,又该如何调用呢?我们看一下toast.js
plugins->toast.js:
import toastCom from './toast.vue'
console.log(toastCom);//object
var Toast = {};
Toast.install = function (Vue, options) {
Vue.prototype.$toast = function(tips){
let ToastComponent = Vue.extend(toastCom);
var dataobj = {
data(){
return {
tips: tips
}
}
};
let tpl = new ToastComponent(dataobj).$mount().$el; // 2、创建实例
document.body.appendChild(tpl); // 3、把创建的实例添加到body中
};
};
export default Toast;
我们打印一下import进来的组件,发现是酱紫的:
其实就是个object对象。瞅着这样儿吧,跟Vue.extend(options)里面的options对象差不多,你看也有data、name、mounted等信息,但好像没有template,那这样能否直接塞入构造器Vue.extend()里面呢?
没关系,咱们塞一下试试。假如能成功,通过前面的小例子我们知道,我们可以在实例化组件时动态传入data信息,这样的话这个功能也就ok了。
main.js:
import Vue from 'vue'
import App from './App'
import router from './router'
import Toast from './plugins/toast'
Vue.use(Toast);
new Vue({
el: '#app',
router,
template: '<App/>',
components: { App }
})
App.vue:
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'app',
mounted(){
this.$toast("出错了");// 通过this即可调用到
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
运行一下:
哈哈,成功了~~
到这里,大家是否已经掌握封装插件的技巧了呢?
如果自我感觉良好,可以趁热打个铁,赶紧动手把前面讲过的loading效果也封装成插件吧,相信你一定可以做的很好很好哒~~
最后,大家都早点睡觉哈~~
以上是关于vue实例的主要内容,如果未能解决你的问题,请参考以下文章