本人是个新手,写下博客用于自我复习、自我总结。
如有错误之处,请各位大佬指出。
学习资料来源于:尚硅谷
大家只要进入到Vue官网,就会知道一个信息:
何为渐进式?Vue的库分为核心库以及相关的插件,核心库比较小,能实现一些基本的功能。显然做项目时,只有核心库肯定不够,需要时就要用其他相关的插件。
所以渐进式就是:我们先只用核心库,当我们需要用到某些特定的功能时,我们就添加我们所需要的这些插件。
Vue的作用:动态构建用户界面。即将后台的数据,在前台的界面上动态渲染显示出来。
vue-cli:帮我们下载基于Vue的项目,而且项目里写好了配置,设置好了依赖。
这里用的Vue版本是2.x版本,目前大部分情况用的也是2.x版本。
如何下载:https://blog.csdn.net/qq_42345237/article/details/80888518
(在这里需要说的是,Vue的中文官网也是配有教程讲解的,如果遇到什么问题查阅官方文档很方便)
Vue.js存放的目录:
在这里,如果之前学了AngularJS,那么对这里的理解就很方便了,而且语法也十分相近,比如,在Angular中,用的是ng-model
,这里用的就是v-model
。同时可以用{{}}
来获取属性。
数据绑定: 数据从一个位置自动流向另一个位置。
View–>Model
Model–>View
单向数据绑定: 只支持一个方向。
双向数据绑定:数据可以从View(视图层)流向Model(模型),也可以从Model流向View。
和Angular中一样,v-model
是双向数据绑定, 而{{}}
是单向数据绑定。如果有需要,可以去我之前的AngularJS博文简单的看一看数据绑定部分,因为很好理解且是很简单的语法。
test.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>01_HelloWorldtitle>
head>
<body>
<div id="test">
<input type="text" v-model="msg">
<br>
<input type="text" v-model="msg">
<p>hello {{msg}}p>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
// 创建Vue示例
const vm = new Vue({ // 配置对象 options
// 配置选项(option)
el: '#test', // element: 指定用vue来管理页面中的哪个标签区域
data: { // 数据 model
msg: 'hello'
}
})
script>
body>
html>
在Vue里,这个MVVM到底是什么,到底是如何办到上面代码效果的:
首先有一个监听,会监听这个输入框内容,当输入框中的内容发生了改变,监听器就触发。这个监听器的回调函数就会把输入框的内容保存到data里,同时将这个数据输出到页面里去显示。而这个过程就会用到DOM监听和数据绑定。具体的之后会有涉及。
MVVM:
model:模型,数据对象(data)
view:视图,模板页面
viewModel:视图模型(Vue的实例)
<html lang="en">
<head>
<meta charset="UTF-8">
<title>02_模板语法title>
head>
<body>
<div id="app">
<h2>1. 双大括号表达式h2>
<p>{{content}}p>
<p>{{content.toUpperCase()}}p>
<p v-text="content">p>
<p v-html="content2">p>
<h2>2. 指令一: 强制数据绑定h2>
<a href="url">访问指定站点a><br>
<a v-bind:href="url">访问指定站点2a><br>
<a :href="url">访问指定站点2a><br>
<h2>3. 指令二: 绑定事件监听h2>
<button v-on:click="test">点我1button>
<button @click="test2(content)">点我2button>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
content: 'I Love This Game',
content2: 'baidu',
url: 'http://www.baidu.com'
},
methods: {
test () {
alert('妙啊!!!')
},
test2(msg){
alert(msg)
}
}
})
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>03_计算属性和监视title>
head>
<body>
<div id="demo">
姓: <input type="text" placeholder="First Name" v-model="firstName"><br>
名: <input type="text" placeholder="Last Name" v-model="lastName"><br>
姓名1(单向): <input type="text" placeholder="Full Name1" v-model="fullName1"><br>
姓名2(单向): <input type="text" placeholder="Full Name2" v-model="fullName2"><br>
姓名3(双向): <input type="text" placeholder="Full Name3" v-model="fullName3"><br>
<p>{{fullName1}}p>
<p>{{fullName1}}p>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
const vm = new Vue({
el: '#demo',
data: {
firstName: 'A',
lastName: 'B',
/*
* 对于这第二种方式监听来说,如果输入框没有改动,它就不会去触发。
* 那么就需要传递一个初始值了,否则初始值就肯定是undefined。
* 而且第二种方式显然比较麻烦,所以通常使用第一种。
* */
fullName2: 'A-B'
},
// 计算属性配置: 值为对象
computed: {
// 什么时候执行:初始化显示/相关的data属性数据发生改变
fullName1 () { // 计算属性中的一个方法,方法的返回值作为属性值,相当于属性的get
return this.firstName + '-' + this.lastName
},
/*前两种实现方式都是单向的,第三种方式可以双向*/
fullName3: {
// 回调函数,当获取当前属性值时自动调用, 将返回值(根据相关的其它属性数据)作为属性值
get () {
return this.firstName + '-' + this.lastName
},
// 回调函数,当属性值发生了改变时自动调用, 监视当前属性值变化, 同步更新相关的其它属性值
set (value) {
// 更新firstName和lastName
const names = value.split('-')
this.firstName = names[0]
this.lastName = names[1]
}
}
},
/*监听的第一种方式*/
watch: {
// 配置监视firstName
firstName: function (value) { // 相当于属性的set
// 更新fullName2
this.fullName2 = value + '-' + this.lastName
}
}
})
/*监听的第二种方式*/
// 监视lastName
vm.$watch('lastName', function (value) {
// 更新fullName2
this.fullName2 = this.firstName + '-' + value
})
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>04_class与style绑定title>
<style>
.classA {
color: red;
}
.classB {
color: blue;
}
.classC {
font-size: 20px;
}
style>
head>
<body>
<div id="demo">
<h2>1. class绑定: :class='xxx'h2>
<p class="classC" :class="myClass">xxx是字符串p>
<p :class="{classA: hasClassA, classB: hasClassB}">xxx是对象p>
<p :class="['classA', 'classB']">xxx是数组p>
<h2>2. style绑定h2>
<p :style="{color:activeColor, fontSize: fontSize}">:style="{ color: activeColor, fontSize: fontSize }"p>
<button @click="update">更新button>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
new Vue({
el: '#demo',
data: {
myClass: 'classA',
hasClassA: true,
hasClassB: false,
activeColor: 'red',
fontSize: '20px'
},
methods: {
update () {
this.myClass = 'classB'
this.hasClassA = !this.hasClassA
this.hasClassB = !this.hasClassB
this.activeColor = 'yellow'
this.fontSize = '30px'
}
}
})
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>05_条件渲染title>
head>
<body>
<div id="demo">
<p v-if="ok">成功p>
<p v-else>失败p>
<hr>
<p v-show="ok">成功p>
<p v-show="!ok">失败p>
<button @click="ok=!ok">切换button>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
new Vue({
el: '#demo',
data: {
ok: true
}
})
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>06_列表渲染title>
head>
<body>
<div id="demo">
<h2>测试: v-for 遍历数组h2>
<ul>
<li v-for="(p, index) in persons" :key="index">
{{index}}--{{p.name}}--{{p.age}}
--<button @click="deleteP(index)">删除button>
--<button @click="updateP(index, {name:'Cat', age: 16})">更新button>
li>
ul>
<button @click="addP({name: 'xfzhang', age: 18})">添加button>
<h2>测试: v-for 遍历对象h2>
<ul>
<li v-for="(item, key) in persons" :key="key">{{key}}={{item}}li>
<br>
<li v-for="(item, key) in persons[1]" :key="key">{{key}}={{item}}li>
ul>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
new Vue({
el: '#demo',
data: {
persons: [
// vue本身只监视了persons的改变,没有监视数组内部数据的改变
{name: 'Tom', age:18},
{name: 'Jack', age:17},
{name: 'Bob', age:19},
{name: 'Mary', age:16}
]
},
methods: {
deleteP (index) {
//删除persons中指定index的p
/*
* 上面说到vue本身只监视persons的改变,那么splice方法也只是改变内部数据,为什么会被监听到?
* 因为这个splice已经不是数组本身的splice方法了,它已经是个变异方法了,即它只是对原方法的一个包装。
* 简单来说就是当你调用原来这个方法,vue就会对它重写,让它能够因为数组内部改变,而界面自动变化。
* */
this.persons.splice(index, 1)
},
updateP (index, newP) {
// 数组内部发生变化,但没有调用变异方法,所以不能使用这种方式
// this.persons[index] = newP
this.persons.splice(index, 1, newP)
//这个splice方法,不仅能删除,修改,还能增加:
//this.persons.splice(index,0,newP)
},
addP (newP) {
this.persons.push(newP)
}
}
})
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>06_列表渲染_过滤与排序title>
head>
<body>
<div id="demo">
<input type="text" v-model="searchName">
<ul>
<li v-for="(p, index) in filterPersons" :key="index">
{{index}}--{{p.name}}--{{p.age}}
li>
ul>
<div>
<button @click="setOrderType(2)">年龄升序button>
<button @click="setOrderType(1)">年龄降序button>
<button @click="setOrderType(0)">原本顺序button>
div>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
new Vue({
el: '#demo',
data: {
searchName: '',
orderType: 0, // 0代表不排序, 1代表降序, 2代表升序
persons: [
{name: 'Tom', age:18},
{name: 'Jack', age:17},
{name: 'Bob', age:19},
{name: 'Mary', age:16}
]
},
computed: {
filterPersons () {
// 取出相关数据
const {searchName, persons, orderType} = this
// 最终需要显示的数组
let arr = [...persons]
// 过滤数组
if(searchName.trim()) {
arr = persons.filter(p => p.name.indexOf(searchName)!==-1)
}
// 排序
if(orderType!==0) {
arr.sort(function (p1, p2) { // 如果返回负数,p1在前,返回正数,p2在前
if(orderType===1) { // 降序
return p2.age-p1.age
} else { // 升序
return p1.age-p2.age
}
})
}
return arr
}
},
methods: {
setOrderType (orderType) {
this.orderType = orderType
}
}
})
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>07_事件处理title>
head>
<body>
<div id="example">
<h2>1. 绑定监听h2>
<button @click="test1">test1button>
<button @click="test2('abc')">test2button>
<button @click="test3('abcd', $event)">test3button>
<h2>2. 事件修饰符h2>
<a href="http://www.baidu.com" @click.prevent="test4">百度一下a>
<div style="width: 200px;height: 200px;background: red " @click="test5">
<div style="width: 100px;height: 100px;background: blue" @click.stop="test6">div>
div>
<h2>3. 按键修饰符h2>
<input type="text" @keyup.13="test7">
<input type="text" @keyup.enter="test7">
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
new Vue({
el: '#example',
data: {
},
methods: {
test1(event) {
alert(event.target.innerHTML)
},
test2 (msg) {
alert(msg)
},
test3 (msg, event) {
alert(msg+'---'+event.target.textContent)
},
test4 () {
alert('点击了链接')
},
test5 () {
alert('out')
},
test6 () {
alert('inner')
},
test7 (event) {
console.log(event.keyCode)
alert(event.target.value)
}
}
})
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>08_表单输入绑定title>
head>
<body>
<div id="demo">
<form action="/xxx" @submit.prevent="handleSubmit">
<span>用户名: span>
<input type="text" v-model="username"><br>
<span>密码: span>
<input type="password" v-model="pwd"><br>
<span>性别: span>
<input type="radio" id="female" value="女" v-model="sex">
<label for="female">女label>
<input type="radio" id="male" value="男" v-model="sex">
<label for="male">男label><br>
<span>爱好: span>
<input type="checkbox" id="basket" value="basket" v-model="likes">
<label for="basket">篮球label>
<input type="checkbox" id="foot" value="foot" v-model="likes">
<label for="foot">足球label>
<input type="checkbox" id="pingpang" value="pingpang" v-model="likes">
<label for="pingpang">乒乓label><br>
<span>城市: span>
<select v-model="cityId">
<option value="">未选择option>
<option :value="city.id" v-for="(city, index) in allCitys" :key="city.id">{{city.name}}option>
select><br>
<span>介绍: span>
<textarea rows="10" v-model="info">textarea><br><br>
<input type="submit" value="注册">
form>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
new Vue({
el: '#demo',
data: {
username: '',
pwd: '',
sex: '男',
likes: ['foot'],
allCitys: [{id: 1, name: 'BJ'}, {id: 2, name: 'SS'}, {id: 3, name: 'SZ'}],
cityId: '2',
info: ''
},
methods: {
handleSubmit () {
console.log(this.username, this.pwd, this.sex, this.likes, this.cityId, this.info)
alert('提交注册的ajax请求')
}
}
})
script>
body>
html>
根据图示,我们可以看到Vue生命周期的几个阶段。首先,当建立了一个Vue实例后,马上就会调用beforeCreate
,之后Vue做一些准备工作:监视属性值的变化用来实现数据绑定以及初始化事件。之后调用created
。
接着就进行判断,就是判断我们用的el
有没有设置。当我们设置了,也就指定了Vue会为谁服务,假如我们不设置,也可以通过手动设置(显然,我们没必要手动设置,使用el
很简单)。然后判断是否设置了template
,像我们之前没有设置过,那它就会以el
指定的区域作为模板,来进行解析。在这里有一个概念叫批量处理。即在解析的时候并不是在页面上直接进行解析,而是先在内存中对所有内容进行解析处理(批量处理),编译好之后再一次性全部送回到页面。而送回之前就是beforeMount
,送回之后就是mounted
。 到这里为止是生命周期的第一个阶段,初始化显示。
生命周期的第二个阶段:更新。在数据发生改变之前就是beforeUpdate
,更新后就是updated
。
生命周期的第三个阶段:销毁 / 死亡。当调用到了vm.$destroy()
就意味着要开始进行销毁了。通常使用beforeDestroy
来做一些销毁前的工作,比如清除定时器。在Vue里销毁会把组件移除掉,页面中也许还会有显示,但是会失去绑定,失去交互。销毁后就是destroyed
。
<html lang="en">
<head>
<meta charset="UTF-8">
<title>09_Vue实例_生命周期title>
head>
<body>
<div id="test">
<button @click="destroyVue">destory vuebutton>
<p v-if="isShow">hellop>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
new Vue({
el: '#test',
data: {
isShow: true
},
mounted () { //初始化显示之后立即调用
// 执行异步任务
this.intervalId = setInterval(() => {
this.isShow = !this.isShow
}, 1000)
},
beforeDestroy() { //死亡之前调用1次
console.log('beforeDestroy()')
// 执行收尾的工作,清除定时器
clearInterval(this.intervalId)
},
methods: {
destroyVue () {
this.$destroy()
}
}
})
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>09_Vue实例_生命周期title>
head>
<body>
<div id="test">
<button @click="destroyVue">destory vuebutton>
<p v-if="isShow">hellop>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
new Vue({
el: '#test',
data: {
isShow: true
},
//1、初始化阶段
beforeCreate() {
console.log('beforeCreate()')
},
created() {
console.log('created()')
},
beforeMount() {
console.log('beforeMount()')
},
mounted () {/*常用*/
console.log('mounted()')
// 执行异步任务
this.intervalId = setInterval(() => {
this.isShow = !this.isShow
}, 1000)
},
//2、更新阶段
beforeUpdate() {
console.log('beforeUpdate()')
},
updated () {
console.log('updated()')
},
//3、死亡阶段
beforeDestroy() { /*常用*/
console.log('beforeDestroy()')
clearInterval(this.intervalId)
},
destroyed() {
console.log('destroyed()')
},
methods: {
destroyVue () {
this.$destroy()
}
}
})
script>
body>
html>
阶段输出示意图:(当点击了按钮才会触发销毁,否则肯定会更新无数次)
对于Vue里的过渡和动画,实际上操作的就是css的trasition或animation。
当我们想使用的时候,我们需要在在目标元素外包裹
(注意:这个name可以为任何值)。
先看一个简例,完整代码在下面。
<transition name="xxx">
<p v-show="show">hellop>
transition>
在这里想实现的效果就是hello的消失与出现。简单来看,这段代码貌似没有什么办法可以触发过渡和动画效果,实际上Vue帮我们做了一个事:给目标元素添加/移除特定的class。比如它的效果应该是这样的:
就像下图中展示的过程,在这里就以出现和消失举例,其他效果也是同理的。
当最开始的时候,元素是隐藏的状态,即Opacity:0
,它会给元素加一个类名:
xxx-enter
,也就是通过xxx-enter
来指定了元素隐藏时候的样式。元素要出现时(出现的过程),就会给它加xxx-enter-active
的类名,过渡/动画 效果结束的时候,就会给它加xxx-enter-to
的类名。
对于消失部分也是同样的,在要消失前是xxx-leave
,消失的过程是
xxx-leave-active
,消失后就是xxx-leave-to
,同时通过xxx-leave-to
来指定了元素隐藏时候的样式。
(当然 过渡/动画 效果不仅限于出现和消失,也会有其他效果,在这里以出现和消失举例,并不意味着这种方法只能实现出现和消失或者必须实现出现和消失)
所以通过整个过程的分析,也就不难看出,对于该元素来将:
xxx-enter
和xxx-leave-to
,都用来指定隐藏时的样式,只不过一个是出现前,一个是出现后,通常一起实现。
xxx-enter-active
和xxx-leave-active
,分别用来记录出现的过程和消失的过程,即用它们来指定过渡效果。
在这里需要注意的是,xxx-enter-to
和xxx-leave
只代表着 过渡/动画 效果结束时和元素准备实现动画效果这两个瞬间,即这两个类名不会长时间存在。所以通常也不实现它们。
(在这时,我本以为 对xxx-enter-to
加一些css样式就会在 过渡/动画 效果实现后触发,只要不触发leave
操作,这个类名就可以长时间存在。但是只要尝试后就会发现,确实是不行。)
<html lang="en">
<head>
<meta charset="UTF-8">
<title>10_过渡&动画1title>
<style>
/*指定过渡样式*/
.xxx-enter-active, .xxx-leave-active {
transition: opacity 1s;
}
/*指定隐藏时的样式*/
.xxx-enter, .xxx-leave-to {
opacity: 0;
}
.move-enter-active {
transition: all 1s
}
.move-leave-active {
transition: all 3s
}
.move-enter, .move-leave-to {
opacity: 0;
transform: translateX(20px)
}
style>
head>
<body>
<div id="demo">
<button @click="show = !show">Togglebutton>
<transition name="xxx">
<p v-show="show">hellop>
transition>
div>
<hr>
<div id="demo2">
<button @click="show = !show">Toggle2button>
<transition name="move">
<p v-show="show">hellop>
transition>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
new Vue({
el: '#demo',
data: {
show: true
}
})
new Vue({
el: '#demo2',
data: {
show: true
}
})
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>10_过渡&动画2title>
<style>
.bounce-enter-active {
animation: bounce-in .5s;
}
.bounce-leave-active {
animation: bounce-in .5s reverse;
}
@keyframes bounce-in {
0% {
transform: scale(0);
}
50% {
transform: scale(1.5);
}
100% {
transform: scale(1);
}
}
style>
head>
<body>
<div id="example-2">
<button @click="show = !show">Toggle showbutton>
<br>
<transition name="bounce">
<p v-if="show" style="display: inline-block">Loremp>
transition>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script>
new Vue({
el: '#example-2',
data: {
show: true
}
})
script>
body>
html>
对于具体moment.js的使用,大家可以去moment查看官方文档查看,这里就展示一下格式:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>11_过滤器title>
head>
<body>
<div id="test">
<h2>显示格式化的日期时间h2>
<p>{{time}}p>
<p>最完整的: {{time | dateString}}p>
<p>年月日: {{time | dateString('YYYY-MM-DD')}}p>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript" src="https://cdn.bootcss.com/moment.js/2.22.1/moment.js">script>
<script>
// 定义过滤器
Vue.filter('dateString', function (value, format='YYYY-MM-DD HH:mm:ss') {
return moment(value).format(format);
})
new Vue({
el: '#test',
data: {
time: new Date()
},
mounted () {
setInterval(() => {
this.time = new Date()
}, 1000)
}
})
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>12_指令_内置指令title>
<style>
[v-cloak] { display: none }
style>
head>
<body>
<div id="example">
<p v-cloak>{{content}}p>
<p v-text="content">p>
<p v-html="content">p>
<p ref="msg">abcdp>
<button @click="hint">提示button>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
new Vue({
el: '#example',
data: {
content: '百度一下'
},
methods: {
hint () {
alert(this.$refs.msg.innerHTML)
}
}
})
script>
body>
html>
在这里需要说一下v-cloak
:其实这些指令有一种特性就是:就是在页面被解析后,这些指令就消失了,如下图所示。而v-cloak
正是用了这样的特性,在没被解析之前,因为这个指令的存在,设置了css样式display:none
,所以指定的标签就不会出现,当页面被解析后,因为指令的消失从而让标签内容出现。
为什么需要这么用?当你去掉v-cloak
后,如果你第一次进网页(网页还没被解析时),你会看到它的表达式形式,即:{{content}}
。正常看大家可能看不出效果,可以在新建Vue对象前,加一个alert,看一下效果。也就是说,为了避免这种情况,我们就可以使用v-cloak
显然,Vue提供的指令可能不能满足所有需求,所以自定义指令的存在就格外重要了。
<html lang="en">
<head>
<meta charset="UTF-8">
<title>12_指令_自定义指令title>
head>
<body>
<div id="test">
<p v-upper-text="msg">p>
<p v-lower-text="msg">p>
div>
<div id="test2">
<p v-upper-text="msg">p>
<p v-lower-text="msg">p>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
// 注册一个全局指令
// el: 指令所在的标签对象
// binding: 包含指令相关数据的容器对象
Vue.directive('upper-text', function (el, binding) {
console.log(el, binding)
el.textContent = binding.value.toUpperCase()
})
new Vue({
el: '#test',
data: {
msg: "I Like You"
},
// 注册局部指令
directives: {
'lower-text'(el, binding) {
console.log(el, binding)
el.textContent = binding.value.toLowerCase()
}
}
})
new Vue({
el: '#test2',
data: {
msg: "I Like You Too"
}
})
script>
body>
html>
以后当我们想用其他人的插件的时候,就也需要用Vue.use()
<html lang="en">
<head>
<meta charset="UTF-8">
<title>17_插件title>
head>
<body>
<div id="test">
<p v-my-directive="msg">p>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript" src="vue-myPlugin.js">script>
<script type="text/javascript">
// 声明使用插件(安装插件: 调用插件的install())
Vue.use(MyPlugin) // 内部会调用插件对象的install()
const vm = new Vue({
el: '#test',
data: {
msg: 'HaHa'
}
})
Vue.myGlobalMethod()
vm.$myMethod()
script>
body>
html>
vue-myPlugin.js
(function (window) {
const MyPlugin = {}
MyPlugin.install = function (Vue, options) {
// 1. 添加全局方法或属性
Vue.myGlobalMethod = function () {
console.log('Vue函数对象的myGlobalMethod()')
}
// 2. 添加全局资源
Vue.directive('my-directive',function (el, binding) {
el.textContent = 'my-directive----'+binding.value
})
// 3. 添加实例方法
Vue.prototype.$myMethod = function () {
console.log('vm $myMethod()')
}
}
window.MyPlugin = MyPlugin
})(window)