Vue基础

data

在组件内,data 必须是返回一个对象的函数

xxcomponent.vue
<script>
  export default {
    data(){
      return {}
    }
  }
</>

特别的,cli 中 App.vue 的 data 也是一个函数。
data 中的属性值不被期望为函数,如果写成函数不会被执行,需要手动调用。
如果需要对数据进行一些操作或者变化,可以写在 computed 或者 methods 中改变或者

template
  <div> {{xx()}} </div>
/template
<script>
  export default {
    data (){
      return {
        xx : () => 'hello, vue'
      }
    }
  }
</script>

深入响应式原理

  1. 深入响应式原理:数据劫持和订阅发布

  2. 底层原理:
    数据劫持:watch底层将data内的属性遍历使用Object.defienProperty()方法,将所有属性设置get(){return value}set(val){}函数变成可监听的响应式。
    订阅发布:自定义事件声明vm.$on和触发vm.emit

  3. 表现
    v-model默认绑定表单元素的value值,当get或者set表单的value值时触发watcher,更新VDOM,然后通过render函数生成真实DOM响应变化。

  4. 手动实现:Vue响应式实现深入Vue实现原理,实现一个响应式框架

非响应式属性

  1. 概念:
    普通数据在绑定到DOM后再发生改变,DOM并不会响应随着改变。
    只有在data内的才是响应式,在data外的都不是响应式的。
  2. 转换方法:
    实例外:Vue.set(Obj,key,value)
    实例内:this.$set || vm.$set
  3. 底层原理:利用Object.assign()方法合并对象
数组检测

数组更新检测不到直接的操作,如 arr[0]=‘A’ 不会检测到更新。
由于 js 本身的一些原因, vue 中


watch

官网描述:
一个对象,键是需要观察的表达式,值是对应回调函数。值也可以是方法名,或者包含选项的对象。
Vue 实例将会在实例化时调用 $watch(),遍历 watch 对象的每一个属性。

思考:watch对象中的key就是响应式数据,value为函数,有可能是写入setter内的东西,因为

  1. watch内所有属性名都是data 中对应的属性名
  2. 属性值可以是一个函数,字符串,数组,对象
new Vue({
  el:'#app',
  data:{
  	msg:'msg',
  	list:[]
  },
  methods:{
    logChange(){console.log('methods')}
  },
  watch:{
  watch内所有属性名都为data中对应的属性名,属性值可以为methods内的方法,可以为函数,也可以为对象或者数组
    msg(val){},
    msg:'logChange',
    list:{
      deep:true,
      handler(val,oldval){}
    }
  }
})

computed vs watch

  1. computed内变量名不能与data内变量重复,而watch内变量名要与data一致

  2. computed=data中数据+一些逻辑计算,然后return出一个新值,然后将变量当作data内的变量一样来使用

  3. 异步操作,开销较大,逻辑复杂,强调点对点数据变化用watch

  4. 操作逻辑,并不复杂选computed

  5. 坑:

    1. watch内不写getset,有handle函数(虽然说用了监听机制,settergetter什么的)
    2. computed内像get一样需要return出值
    3. computed中只通过get获取参数值,没有set无法改变参数值。当v-model的是计算属性时改变inptu的value会报错:Computed property "xxx" was assigned to but it has no setter.

组件

Vue.extend()
  1. Vue.extend 返回一个子类构造函数,也就是带有预设参数的组件实例构造器。它的目的是创建一个Vue的子类并且返回相应的 constructor 。
  2. Vue.extend是构造一个组件的语法器. 你给它参数 他给你一个组件 然后这个组件你可以作用到Vue.component 这个全局注册方法里, 也可以在任意vue模板里使用apple组件
  3. 后可使用vue.component进行实例化,或new extendName().$mount(query)方式进行实例化
  4. Vue.component()实际上是一个类似于Vue.directive() 和 Vue.filter()的注册方法,它的目的是给指定的一个constructor一个String类型的ID。实际上当你直接传递选项给Vue.component()的时候,它会在背后调用Vue.extend()
  5. Vue.extend() 继承于 Vue(),所以他们用法类似,都有data methods 钩子函数等属性
标准写法
html部分:
	<div id="mount-point"></div>
js部分:
	1. 通过extend预设组件,得到组件类
	var Profile = Vue.extend({
	  template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
	  data: function () {
	    return {
	      firstName: 'Walter',
	      lastName: 'White',
	      alias: 'Heisenberg'
	    }
	  }
	})
	
	2. 创建 Profile 实例,并挂载到一个元素上。
	new Profile().$mount('#mount-point')
	3. 或者进行全局注册或局部注册
		3.1 局部注册
		new vue({
		  el:'#app',
		  components:{
		    Hello:Profile
		  }
		})
		3.2 全局注册
		Vue.component('Hello',Profile)
	
结果:
	<p>Walter White aka Heisenberg</p>
Vue 2.0简写
	Vue.component('Hello', {
		这里相当于vue.extend({})
	})

钩子

钩子函数顺序:beforeCreate>created>beforeMounte>bind>inserted>mounted
更新时:directiveupdated > instanceupdated
实例中的updated hook没有el参数
自定义指令中的updated hookel,binding参数


Instance hook

beforeCreate:组件创建前的准备工作, 初始化事件和生命周期, 为事件的发布和订阅做准备。拿不到data,拿不到dom。

created:组件创建结束, 数据可以拿到 , DOM 拿不到。可以进行数据请求和默认数据修改, 一般进行数据的请求和数据的修改

beforeMounted:真实DOM存在,模版未渲染。此时DOM中的数据,如{{ msg }}还没有被正确渲染,但是DOM结构已存在。一般用来数据请求

mounted:组件实现挂载, DOM渲染正确。一般用来操作第三方库的实例化,但是在使用swiper中存在轮播图划不动的情况,需要把实例化代码放在setTimeout()中,进行实例化

beforeUpdate:虚拟DOM更新,真实DOM未被render函数完全渲染,此时model最新的,view未更新

updated:此时modelview同步,render函数执行完毕


Vue-directive(自定义指令)

自定义vue指令,通过v-name调用。这个函数接受两个参数,第一个为自定义指令的名称,第二个为一个配置项

简写:在很多时候,你可能想在 bind 和 update 时触发相同行为,而不关心其它的钩子。比如这样写
	Vue.directive('name',(el, binding)=>{
		el.style.backgroundColor = binding.value
		console.log('bind & update hook')
	});
	
	Vue.directive('name',{
		bind(el,binding){},	// 样式写这里
		inserted(){},	// 行为写这里
		update(){},
		unbind(){},
		...
	});

bind 钩子函数内,el.focus() 并未生效,这是因为在 bind 钩子函数被调用时,虽然能够通过 bind 的第一个参数 el 拿到对应的 DOM 元素,但是此刻该 DOM 元素还未被插入进 DOM 树中,因此在这个时候执行 el.focus() 是无效的

  1. 问题:对比这里生成的 inptu 是直接在 dom 中的吗?对比在 vue bind钩子内的 el.focus() 有何区别
  2. 思考:document.createElement 可能掉用的时候就在 dom 中了,后边的 appendChild 只是插入在哪的问题
	var box = document.querySelector('#app');
	var input = document.createElement('input');
	input.autofocus = 'autofocus';
	box.appendChild(input)
指令

指令能在=后双引号内传递参数而不是用{{}}是因为指令钩子内有binding对象,binding对象的value属性和express属性可以拿到""内的值
基于此我们可以通过自定义指令完全模拟vue的自带指令

DOM
<input v-focus=" 'red' ">
js

new Vue({
  directives:{
  
    focus:{
		inserted(el,binding){
			binding.value--red 字符串类型
			binding.express--'red'
			el.style.color=binding.value  
		}
	}
	
	当只在bind和update钩子上操作时候,可以简写
	focus(el,binding){xxx}
	
  }
})
自定义指令

在vue中输入框如果想自动获取焦点,传统的autofocus不管用

directives:{
	focus:{
		// 指令钩子,当被绑定的元素插入到 DOM 中时
		inserted(el){
			el.focus()
		}
	}
}

v-bind
模版内标签属性默认是不会解析变量的,如果需要将属性与数据绑定,需要用到 v-bind 指令

<input title=" msg " >	默认不解析
< input :title=" msg ">	绑定使用
data:{
  msg:' myInput '
}

v-text和 {{}} 的区别:
共同:

  1. 都不会解析数据内的字符串标签,对比 v-html
    区别:
  2. v-text 默认没有闪烁问题,{{}}有闪烁问题要配合 v-clock
  3. v-text中间不能插入其它文本,默认会被覆盖掉,而插值表达式可以配合使用
<p v-clock> {{msg}} </p>
<p v-text="msg" />

事件修饰符
.stop:阻止冒泡
.prevent:阻止冒泡
.capture:添加事件监听时使用事件捕获
.once:只有一次


表单元素双向绑定
input(radio text address email …) select checkbox textare

<select v-model="opt">
  <options value="+">+</options>
  <options value="-">-</options>
  <options value="*">*</options>
  <options value="/">/</options>
</select>

v-for
注意:v-for 需要绑定 :key 来添加唯一标识符( number/string )

v-for=" i in 9 "    								如果迭代数组,i 从1开始
v-for=" ( item, index ) in lists "			
v-for=" ( val, key, index ) in obj"

样式绑定

  1. 数组
:class = "[ '类名',  条件 ? 'class_name':'class_name' ]"    三元表达式
  1. 对象
:class="{ 类名: boolean }"    
  1. 数组对象
:class="[ '类名',  { '类名': flag }]"    代替三元表达式,简化代码逻辑提高可读性

内联样式

  1. 直接给一个对象
:style="{ color: 'red', 'font-size':'14px' }"    这里用字符串 ' font-size' 或者 fontSize
否则js会将 - 解析为减
也可将对象写在data内
:style=" styleObj "
  1. 数组
:style="[ obj1, obj2 ]"

条件渲染

v-if=" flag " @click=" flag=!flag "			删除DOM,用于极少切换
v-show=" flag " @click=" flag=!flag "		改变display,用于频繁切换

过滤器

过滤器只能用在 v-bind 和 {{}}中,其他地方不可以使用。用管道符表示
{{ str | myFilter() }}


生命周期
  1. 初始化阶段()
    beforeCreate(){}:在beforeCeated中,vue实例存在,但未创建完成。所以data等数据拿不到
    created(){}:实例创建完毕,所以是最早的可以改变data的钩子,是我们常用来获取数据的地方
    ceated(){} 后做了什么事情?

1.是否有 el 的 options,没有等待被挂载
2.是否有 template,有渲染没有将挂载 DOM 编译成模版渲染

beforeMount(){}:模版已在内存中,尚未挂载到页面

以上为vue实例化,模版编译阶段,最终在内存中生成一个编译好的字符串模版,然后把这个模版渲染为内存中的DOM。此时只存在与内从中,渲染好了并没有挂载到真正的页面中去

mounted(){}:内存中的模版已经挂载到真实页面中,页面已经渲染好了。实例创建期间的最后一个周期函数,当执行完毕后,这个实例就被完全创建好了,如果没有其他操作的话,这个实例就静静的躺在我们的内存中一动不动。

  1. 运行期
    beforeUpdate(){}:当data数据改变时触发,M改变,VM做事情,将要改变V。当触发这个钩子时,V层旧数据,M层更新。虚拟DOM根据数据更新,然后re-render and patch(挂载),完成从M成到V层的更新
    updated(){}:表示V层更新完成

  2. 销毁期
    beforeDestory(){}:销毁前
    Destory(){}:组件完全销毁,所有数据方法过滤器等消失。


过渡

组件切换过度动画,Vue提供了transition标签实现过渡动画。注意首次加载时无过渡动画,可以通过给 transition 标签设置 appear 属性实现首次加载动画
transition 标签只能在单标签实现过渡动画, can only be used on a single element。像列表循环那样需要使用transition-group

v-enter,v-leave
v-enter-to,v-leave-to

.v-leave-to,.v-enter{
  opacity:0;
  transform:translateX(150px);
}
.v-enter-active,.v-leave-active{
  transition: all 0.4s ease;
}

在同一个组件内,所有transform标签内共用该类,如果想要个性化需要transform设置name属性

<transform name="my">
css:
.my-enter,.my-leave-to{
  opacity:0;
  transform:translateY(150px);
}
.my-enter-active,.my-leave-active{
  transition: all 0.4s ease;
}

v-enter是进入前,v-leave-to是离开后

使用 animate.css:

<transition enter-active-class="animated enter_class" leave-acitve-class="animated leave_class">
  <h3 v-if="flag"> 过渡测试 </h3>
<transition >

可以简写为:
<transition enter-active-class="enter_class" leave-acitve-class="leave_class">
  <h3 v-if="flag" class="animated"> 过渡测试 </h3>
<transition >

<transition :duration="300">  为入场和离场时间
:duration="{enter:300,leave:400}"    指定时常


半场动画:只有进入没有离开。前两种都无法实现半场动画(购物车添加动画)
动画生命周期钩子:

template:

<transition
  @before-enter="beforeEnter"
  @enter="enter"
  @after-enter="afterEnter"
>
  <div class="boll" v-if="bollFlag"></div>
</transition>

js:

methods:{
  beforeEnter(el){
    el.style.transform="translate(0,0)";
  },
  enter(el, done ){
    el.offsetWidth		注意这句话虽然没什么实际意义,但是不加没动画 offsetTop Left Height都可以
    el.style.transform="translate(150px,450px)";
    el.style.transition="all 1s ease"
    done()		注意如果为纯js实现过度这里的done必须要写
  }
}

列表过渡:如果需要动态添加的循环上存在过度动画,transition标签无效,使用transition-group,该标签默认渲染为span标签不复合w3c规范,可以通过tag属性直接改为ul标签
添加动画:

css:

.v-enter,.v-leave-to{
  opacity: 0;
  transform: translateX(150px)
}
.v-enter-active,.v-leave-active{
  transition: all 0.4s ease
}
li:hover{background:red}
template:


<transition-group appear tag="ul">
  <li v-for="item in lists" :key="item.id">
    name : {{item.name}}------age : {{item.age}}
  </li>
</transition-group >

删除动画:
列表删除过渡时候会出现当前元素过渡,其他元素位置不变等待过渡结束才位移到正确位置的问题。解决方案:

css:增加以下类名
实现列表平滑过渡核心代码
.v-move{
  transition: all 0.4s ease
}
.v-leave-active{
  position: absolute;
}
li{
  width: 100%	如果不加的话删除时li标签宽度会塌陷,因为position:absolute的原因
}


实现列表添加删除,购物车小球等完整过度动画代码

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

  <title>Document</title>
  <style>
    .v-enter,.v-leave-to{
      opacity: 0;
      transform: translateX(150px)
    }
    .v-enter-active,.v-leave-active{
      transition: all 0.4s ease
    }
    .v-move{
      transition: all 0.4s ease
    }
    .v-leave-active{
      position: absolute;
    }
    .boll{
      width: 30px;
      height: 30px;
      border-radius: 50%;
      background: red;
    }
    .lists{
      list-style: none;
      border: 1px dotted green;
      padding: 0 10px;
      margin: 10px;
      line-height: 35px;
    }
    li:hover{
      background: deeppink;
    }
    li{
      width: 100%
    }
  </style>
</head>

<body>
  <div id="app">
    <div>
      <input type="button" value="targg" @click="flag=!flag">

      <transition appear>
        <h1 v-if="flag">{{msg}}</h1>
      </transition>

      <input type="button" value="快到碗里来" @click="bollFlag=!bollFlag">
      <transition
        @before-enter="beforeEnter"
        @enter="enter"
        @after-enter="afterEnter"
      >
        <div class="boll" v-if="bollFlag" :css="false"></div>
      </transition>

      <br>
      
      <label for="">
        <input type="text" v-model="name">
        <input type="text" v-model="age">
        <input type="button" value="添加" @click="add">
      </label>
      <ul>
        <transition-group appear>
          <li v-for="(item,i) in lists" :key="item.id" class="lists" @click="del(i)">
            name : {{item.name}}------age : {{item.age}}
          </li>
        </transition-group>
      </ul>
    </div>
  </div>
</body>

</html>
<script>
  new Vue({
    el: '#app',
    data: {
      name:'',
      age:'',
      msg: 'hello',
      flag: true,
      bollFlag:false,
      lists:[
        {id:1,name:'张三',age:23},
        {id:2,name:'李四',age:33},
        {id:3,name:'王五',age:13},
        {id:4,name:'赵六',age:26}
      ]
    },
    methods:{
      add(){
        this.lists.push({
          id:this.lists.length+1,
          name:this.name,
          age:this.age
        })
        this.name=this.age=''
      },
      del(i){
        this.lists.splice(i,1)
      },
      beforeEnter(el){
        el.style.transform="translate(0,0)";
      },
      enter(el,done){
        el.offsetWidth
        el.style.transform="translate(150px,450px)";
        el.style.transition="all 1s ease"
        done()
      },
      afterEnter(){
        this.bollFlag=!this.bollFlag;
      }
    }
  })
</script>

组件

Vue.extend({})返回组件的类构造器,。参数是一个包含组件选项的对象
必须通过Vue.component(‘name’, class )或局部注册后使用

创建组件的三种方式

第一种:
var x = Vue.extend({
  template:'<div>自定义模版</div>',
  data(){
    msg:'msg'
  }
})
Vue.component( 'myvue', x )

第二种:
Vue.component( 'myvue', {
  template:'<div>自定义模版</div>'
})

第三种:在app根实例外
<template id="tmp">
  <div>
    <h1>第三种组件创建方式</h1>
  </div>
</template>
Vue.component('mycomponent', {
  template:'#tmp'
})


组件的data必须是一个函数返回一个对象

<template id="comp">
  <div>自定义组件</div>
<template>

在组件内注册
new Vue({
  el:'#app',
  components:{
    这里一个对象就是一个组件
    mycomp:{
      template:'#comp',    指定 ID 类似el挂载html结构
      data(){
        return {
          msg:'newmsg'
        }
      }
    }
  }
})


渲染组件的两种方式

在vue脚手架中 main.js就是通过render函数渲染(在vue结合webpack使用必须通过render渲染组件,通过components然后标签的方式不成功)
render渲染:render渲染只能覆盖指定的容器,虽然router-view也是写在#app的盒子内,但是他独立于这之外,路由组件通过路由监听渲染出来

import App from './App.vue'

new Vue({
  render: h => h(App),
}).$mount('#app')
第一种常规方式:通过组件内components中注册或者通过Vue.component()全局注册,然后以标签的形式使用
template:
<div id="app">
  <Login></Login>    	通过标签
</div>

js:
var Login = {
  template:'<h3>注册模版</h3>'
}
new Vue({
  components:{Login}    局部注册
})

第二种:使用render函数
template:
<div id="app"></div>

js:
var Login = {
  template: '<h3>登录组件</h3>'
}

new Vue({
  el: '#app',    使用render函数会覆盖div#app(消失)
  render(createElement){   createElement方法可以把指定的组件渲染为html结构
    return createElement(Login)    这里返回的结果会替换页面中el挂载的容器(覆盖div#app)
  }
  简写:
  render: h => h(App)    return省略{} 箭头省略()
})

区别:render会清空内容,只能放一个组件。传动方式渲染不会覆盖,可放多个组件。


组件切换

第一种方式:通过条件渲染配合开关思想

<button @click="flag=!flag"></button>

<login v-if="flag" />
<register v-else="flag">

Vue.component( 'login', {
  template:'<h1>登录组件</h1>'
})
Vue.component( 'register', {
  template:'<h1>注册组件</h1>'
})
data:{
  flag:true
}

第二种方式:
vue提供的component标签,通过绑定is属性来展示对应的组件

<a href="" @click.prevent="componentName='login'">登录</a>
<a href="" @click.prevent="componentName='register'">注册</a>
<component :is=" componentName " />

data:{
  componentName:'login'
}
props

data是组件内私有的状态,props并不是私有的而是父组件传递过来的
data可读写,props只读
在Vue中,父组件通过v-bind形式给子组件传递数据,子组件需props属性接受。props是建议更改的,如果需要,在data中定义
父组件方法通过v-on事件绑定机制传递,当自定义一个事件类型之后,子组件通过 自己的事件处理函数通过this.$emit触发该方法


组件通讯

父子通讯

1.父组件v-bind绑定属性,在子组件身上,子组件内通过props属性接受一个数组,数组内用字符串填充属性名

2.父组件通过this.$children访问子组件数据

父:
<Son :msg="msg"></Son>
子:
props:['msg']

<input v-model="$parent.data">

子父通讯
1.父组件通过事件绑定一个自定义事件类型,值为父组件内的方法。子组件通过绑定事件函数通过this.$emit('父自定义事件名',参数)触发父组件事件

2.子组件内 this.$parent访问当父组件内的数据

3.this.$root 作为所有组件共享的全局 store

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <title>Document</title>
</head>
<body>
  <div id="app">
    父:{{msg}}
    <Son @change_father_name="change"></Son>
  </div>
  <template id="son">
    <div>
      <input type="text" @input="change">
    </div>
  </template>
</body>
</html>
<script>
  var Son = {
    template: '#son',
    methods: {
      change(e) {
        this.$emit('change_father_name', e.target.value)
      }
    },
  }
  new Vue({
    el: '#app',
    data: { msg: 'fathers msg' },
    methods: {
      change(data) {
        this.msg = data
      }
    },
    components: { Son }
  })
</script>

跨组件通信

https://cn.vuejs.org/v2/guide/components-edge-cases.html

1.ref

1.在普通 dom 标签上绑定 ref 获取的是 dom 元素
<div ref="box"></>
console.log(this.$refs.box)

-> <div></>

2.在子组件标签绑定 ref 获取组件实例属性和方法
<Title ref = titleComponent>
console.log(this.$refs.titleComponent)

-> VueComponent{}

2.bus总线



计算属性

computed依赖缓存,用于为了在模版上不呈现过于复杂的逻辑代码,我们把需要处理复杂逻辑的数据写在computed内并且return出来。

不会根据时间改变
computed:{
  now(){    这里的now当作变量使用
    return Date.now()
  }
}
watch

watch可以看作是computed和methods的结合体,可以监听虚拟的东西,比如路由的变化。(只要是实例内的数据都可以被监听到,所以可以用来监听路由)


webpack结合vue

安装vue
在普通网页中使用vue开发:通过script标签引入完整的vue 文件

在webpack内通过 import Vue from ’ vue '不是完整的vue文件,只是node-modules下的vue文件夹下的package.json中的main属性指定的地址,是vue-runtime-only形式,不完整。我们可以直接给完整文件的路径import Vue from '../node_modules/vue/dist/vue.js'

1.安装vue: cnpm i vue -S
2.安装vue的loader:cnpm i vue-loeader vue-template-complier -D
3.在main.js中导入vue模块:import Vue from 'vue'
4.定义vue文件:三部分
5.导入组件:import App from './App.vue'
6.创建实例:var vm = new Vue({ el:'#app',render:h=>h(App) })
7.创建div#app做挂载容器

安装vue-router

import VueRouter from 'vue-router'
Vue.ues(VueRouter)
var routes=[
  {},{}
]
var router = new VueRouter({
  routes,
  mode:'history'
})

在一个模块中,export default 和 export 可以同时存在,区别:

1.exprot default只能暴露一次,直接接收不需要{},变量名不需要对应
const text = {name:'zhangsan'}
export default text
import txt from './text.js'

2.exprot可以导出多次,引入任意。引入时只能使用{}且必须对应属性名。这种形式叫做按需导出。
如果改变默认属性名,需要使用as重命名
export  var init ={name:'init'}
export  var show ={name:'show'}

import { show as s } from './text.js'

饿了么 MintUI

MintUI不同于MUI,是真正的组件库,是使用Vue技术封装出来的成套的组件,可以无缝的和Vue项目进行集成开发。而MUI和Bootscrap类似一套好用的代码片段。
MintUI分为js 组件 css组件和表单组件三类
import Mint from 'mint-ui'时css组件都可以用,js组件如果需要使用则必须单独引入js

全部引入
当完全引入的时候,相当于把所有的组件都注册到全局下,所以我们可以直接在模版内使用组件标签
import Vue from 'vue'
import Mint from 'mint-ui'
Vue.use(Mint)

<mt-button></mt-button>


按需引入
import { Button } from 'mint-ui'
Vue.component(name, obj)        组件注册
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值