vue实例

Posted 前端js动力节点

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue实例相关的知识,希望对你有一定的参考价值。

vue实例(三)
vue实例(三)

今天教大家动手做个vue插件,这个技能也是必须要掌握的,在项目中肯定用得到。

这节课的干货有点多,大家做好心理准备,一次看不完的话可分两次或三次看,千万别勉强哦~~

vue实例(三)
vue实例(三)

那么熟悉jquery的同学都知道,封装一个jquery插件,都是有一套固定规则的,按照这套规则走就ok,比如是酱紫的:


(function (${
 $.fn.myPlugin = function ({
   //你自己的插件代码
};
})(jQuery);

那么vue呢?

其实也是一样的,他也有这么一套固定的规则,我们先来看一下手册是怎么说的:

vue实例(三)

其实我们只要提取这样几点信息就好:

1.公开方法install

2.install方法第一个参数是vue构造器

3.在vue构造器上可以追加自定义方法

具体应该怎么来写呢?我们以比较常用的一个插件——toast,为例来讲解一下。

我们新建一个plugins目录,后面与插件有关的文件都放在这里。

vue实例(三)

toast.js:

var Toast = {};
Toast.installfunction (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-top60px;
}
</style>

运行一下:

vue实例(三)

看来已经生效了哈~~

以上就是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个步骤:

创建组件构造器、注册组件和使用组件。

如下图所示:

vue实例(三)

注意

1. Vue.extend()是Vue构造器的扩展,调用Vue.extend()创建的是一个组件构造器,而不是一个具体的组件实例。 

2. Vue.extend()构造器有一个options选项对象,options对象的template属性用于定义组件要渲染的HTML。 

3. 使用Vue.component()注册组件时,需要提供2个参数。第1个参数时组件的标签,第2个参数是组件构造器。 

4. Vue.component()方法内部会调用组件构造器,创建一个组件实例。 

5. 组件应该挂载到某个Vue实例下,否则它不会生效。

看下手册是怎么说的:

vue实例(三)

官方示例:

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-top60px;
}
</style>

仍旧是通过this即可调用。我们看一下效果:

vue实例(三)

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进来的组件,发现是酱紫的:

vue实例(三)

其实就是个object对象。瞅着这样儿吧,跟Vue.extend(options)里面的options对象差不多,你看也有datanamemounted等信息,但好像没有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-top60px;
}
</style>

运行一下:

vue实例(三)

哈哈,成功了~~

到这里,大家是否已经掌握封装插件的技巧了呢?

如果自我感觉良好,可以趁热打个铁,赶紧动手把前面讲过的loading效果也封装成插件吧,相信你一定可以做的很好很好哒~~

最后,大家都早点睡觉哈~~

vue实例(三)

以上是关于vue实例的主要内容,如果未能解决你的问题,请参考以下文章

VSCode自定义代码片段1——vue主模板

VSCode自定义代码片段——.vue文件的模板

VSCode自定义代码片段(vue主模板)

VSCode自定义代码片段11——vue路由的配置

VSCode自定义代码片段11——vue路由的配置

VSCode自定义代码片段11——vue路由的配置