3、Vue 开发基础(二)
3.1、全局 API
3.1.1、Vue.directive
Vue 中有很多内置指令,如 v-model、v-for 和 v-bind 等。除了内置指令,开发人员也可以根据需求注册自定义指令。
通过自定义指令可以对低级 DOM 元素进行访问,为 DOM 元素添加新的特性。
<div id='root'>
<input type="text" v-focus='true' name="" id="">
</div>
<script>
Vue.directive('focus',{
// 第一个参数 el 表示当前自定义指令的元素,第二个参数 binding 表示指令的相关信息
inserted (el, binding) {
if(binding.value){
el.focus();
}
}
})
new Vue({
el: '#root',
data: {
name: '潘嘉龙'
}
})
</script>
可以看出,input 文本框使用自定义指令 v-focus 成功获取了焦点。
3.1.2、Vue.use
Vue.use 主要用于在 Vue 中安装插件,通过插件可以为 Vue 添加全局功能。
插件可以是一个对象或函数,如果是对象,必须提供 install() 方法,用来安装插件。
如果是一个函数则该函数将被当成 install() 方法。
<div v-my-directive id="app"></div>
<script>
// 定义一个 MyPlugin(自定义插件)对象
let MyPlugin = {}
// 编写插件对象的 install 方法
MyPlugin.install = function (Vue, options) {
console.log(options);
// 在插件中为 Vue 添加自定义指令
Vue.directive('my-directive', {
bind(el, binding) {
// 为自定义指令 v-my-directive 绑定的 DOM 元素设置 style 样式
el.style = 'width:100px;height:100px;background-color:#ccc;'
}
})
}
Vue.use(MyPlugin, { someOptions: true })
var vm = new Vue({
el: '#app',
})
</script>
提示
Vue.js 官方提供的一些插件(如 vue-router)在监测到 Vue 是可访问的全局变量时,会自动调用 Vue.use()。
但是在 CommonJS 等模块环境中,则始终需要 Vue.use() 显示调用。
var Vue = require('Vue')
var vueRouter = require('vue-router')
Vue.use(vueRouter)
3.1.3、Vue.extend
Vue.extend 用于基于 Vue 构造器创建一个 Vue 子类,可以对 Vue 构造器进行扩展。
它有一个 options 参数,表示包含组件选项的对象。
<div id='root1'>app1: {{title}}</div>
<div id='root2'>app2: {{title}}</div>
<script>
var Vue2 = Vue.extend({
data () {
return {
title: 'hello'
}
}
})
new Vue({
el: '#root1',
data: {
name: '潘嘉龙'
}
})
new Vue2({
el:'#root2'
})
</script>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0fwx00Md-1642646132122)(C:\Users\32912\AppData\Roaming\Typora\typora-user-images\image-20220119143624847.png)]
app1 对应 Vue 的实例 vm1,app2 对应 Vue2 的实例 vm2,从运行结果可以看出,在 vm2 中添加了初始数据 hello,vm1不受影响。并且在控制台中会看到 title 属性未定义的提示。
3.1.4、Vue.set
Vue 的核心具有一套响应式系统,简单来说就是通过监听器监听数据层的数据变化,当数据改变后,通知视图也自动更新。
Vue.set 用于向响应式对象中添加一个属性,并确保这个新属性同样是响应式的,且触发视图更新。
<div id='root'>
<div>{{a}}</div>
<div>{{obj.b}}</div>
</div>
<script>
new Vue({
el: '#root',
data: {
a: '潘嘉龙',
obj: {}
}
})
// 第一个参数 vm.obj 目标对象,第二个参数 b 表示属性名,第三个参数是属性值。
Vue.set(vm.obj, 'b', '我是 Vue.set 添加的响应式属性 obj.b')
</script>
注意
Vue 不允许动态添加根级响应式属性,因此必须在 data 中预先声明所有根级响应式属性。
3.1.5、Vue.mixin
Vue.mixin 用于全局注册一个混入,它将影响之后创建的每个 Vue 实例。
该接口主要是提供给插件作者使用,在插件中向组件注入自定义的行为。
该接口不推荐在应用代码中使用。
<div id='root'>
</div>
<script>
Vue.mixin({
created() {
var myOption = this.$options.myOption
if(myOption){
console.log(myOption.toUpperCase());
}
},
})
var vm = new Vue({
el: '#root',
data: {
name: '潘嘉龙'
},
myOption:'hello vue!'
})
</script>
3.2、实例属性
实例属性是指 Vue 实例对象的属性。
3.2.1、vm.$props
使用 vm.$props 属性可以接收上级组件向下传递的数据。
<div id='root'>
<!-- 父组件 -->
<my-parent></my-parent>
</div>
<!-- 父组件模板 -->
<template id="parent">
<div>
<h3>手机信息搜索</h3>
手机品牌:<input type="text" v-model='brand' name="" id="">
<!-- 子组件 -->
<my-child v-bind:name="brand"></my-child>
</div>
</template>
<!-- 子组件模板 -->
<template id="child">
<ul>
<li>手机品牌:{{show.brand}}</li>
<li>手机型号:{{show.type}}</li>
<li>市场价格:{{show.price}}</li>
</ul>
</template>
<script>
Vue.component('my-parent', {
template: '#parent',
data() {
return {
brand: ''
}
}
})
Vue.component('my-child', {
template: '#child',
data() {
return {
content: [
{ brand: '华为', type: 'Mate20', price: 3600 },
{ brand: '苹果', type: 'iPhone7', price: 2949 },
{ brand: '三星', type: 'Galaxy S8+', price: 3299 },
{ brand: 'vivo', type: 'Z5x', price: 1698 },
{ brand: '一加', type: 'OnePlus7', price: 2999 },
{ brand: '360', type: 'N7 Pro', price: 1099 },
{ brand: 'oppo', type: 'Reno', price: 2599 },
],
show: {
brand: '', type: '', price: ''
}
}
},
props:['name'],
watch:{
name(){
if(this.$props.name){
var found = false
this.content.forEach( (value,index) => {
if(value.brand === this.$props.name){
found = value
}
})
this.show = found ? found : {brand: '', type: '', price: ''}
}else{
return
}
}
}
})
var vm = new Vue({
el: '#root',
data: {
name: '潘嘉龙'
}
})
</script>
3.2.2、vm.$options
Vue 实例初始化时,除了传入指定的选项外,还可以传入自定义选项。
自定义选项的值可以是数组、对象、函数等,通过 vm.$options 来获取。
<div id='root'>
<p>{{base}}</p>
<p>{{noBase}}</p>
</div>
<script>
var vm = new Vue({
el: '#root',
customOption: '我是自定义数据',
data: {
base: '我是基础数据'
},
created () {
this.noBase = this.$options.customOption
}
})
</script>
customOption 是自定义数据,与 data 不同的是,它不具有响应特性。
3.2.3、vm.$el
vm.$el 用来访问 vm 实例使用的根 DOM 元素。
<div id='root'>
<p>我是跟标签结构</p>
</div>
<script>
var vm = new Vue({
el: '#root',
data: {
name: '潘嘉龙'
}
})
vm.$el.innerHTML ='<div>我是替换后的 div 标签</div>'
</script>
通过 vm.$el 获取到 DOM 对象后,将 innerHTML 属性修改为新的内容 “我是替换后的 div 标签”。
3.2.4、vm.$children
vm. c h i l d r e n 用 来 获 取 当 前 实 例 的 直 接 子 组 件 。 需 要 注 意 的 是 , children 用来获取当前实例的直接子组件。需要注意的是, children用来获取当前实例的直接子组件。需要注意的是,children 并不保证顺序,也不是响应式的。
<div id='root'>
<button @click='child'>查看子组件</button>
<my-component></my-component>
</div>
<script>
Vue.component('my-component',{
template: '<div>myComponent</div>'
})
var vm = new Vue({
el: '#root',
data: {
name: '潘嘉龙'
},
methods: {
child(){
console.log(this.$children);
}
},
})
</script>
通过 this.$children 可以得到当前实例的所有子组件实例集合。
3.2.5、vm.$root
vm.$root 用来获取当前组件树的根 Vue 实例,如果当前实例没有父实例,则获取到的是该实例本身。
<div id='root'>
<my-component></my-component>
</div>
<script>
Vue.component('my-component',{
template: '<button @click="root">查看根实例</button> ',
methods: {
root(){
console.log(this.$root);
console.log(this.$root === vm.$root);
}
}
})
new Vue({
el: '#root',
data: {
name: '潘嘉龙'
}
})
</script>
this. r o o t 和 v m . root 和 vm. root和vm.root 的比较结果为 true,说明使用 this.$root 可以获取到当前组件树的根 Vue 实例。
3.2.6、vm.$slots
Vue 中的组件中使用 template 模板定义 HTML 结构,为了方便使用 template 公共模板结构,Vue 提出了插槽的概念,插槽就是定义在组件内部的 template 模板,开头通过 $slots 动态获取。
<div id="root">
<my-component>你好</my-component>
<my-component>你好</my-component>
</div>
<template id="first">
<div>
<slot></slot>
</div>
</template>
<script>
Vue.component('my-component',{template: '#first'})
var vm = new Vue({
el: '#root',
data: {
name: '潘嘉龙'
}
})
</script>
3.2.7、vm.$attrs
vm.$attrs 可以获取组件的属性,但其获取的属性中不包含 class、style以及被声明为 props 的属性。
<div id='root'>
<my-component id="test"></my-component>
</div>
<script>
Vue.component('my-component',{
template:'<button @click="showAttrs">查看属性</button>',
methods:{
showAttrs(){
console.log(this.$attrs);
}
}
})
new Vue({
el: '#root',
data: {
name: '潘嘉龙'
}
})
</script>
3.3、全局配置
在开发环境下,Vue 提供了全局配置对象,通过配置可以实现生产信息提示、警告忽略等人性化处理。
3.3.1、productionTip
当在网页中加载了 vue.js 文件时,浏览器的控制台会出现英文的提示信息提醒用户 ”您正在开发模式下运行 Vue,在生产部署时,请确保打开生产模式”。
如果要打开生产模式,使用 vue.min.js 文件代替 vue.js 文件即可。
<script>
Vue.config.productionTip = false
</script>
3.3.2、silent
Vue 全局配置对象,silent 可以取消 Vue 日子和警告,值类型为 boolean,默认值为 false,设为 true 表示忽略警告和日志,否则不忽略。
<div id='root'>
{{msg}}
</div>
<script>
new Vue({
el: '#root',
data: {
name: '潘嘉龙'
}
})
</script>
<script>
Vue.config.silent = true;
new Vue({
el: '#root',
data: {
name: '潘嘉龙'
}
})
</script>
3.3.3、devtools
在 Vue 全局配置中可以对该工具进行配置,将 Vue.config.devtools 设为 true 表示允许调试,否则不允许调试。
<script>
Vue.config.devtools = false
</script>
默认情况下,页面允许使用 devtools 进行调试。
3.4、组件进阶
在 Vue 中,组件是对结构的抽象,组件可复用性很强,每个组件拥有组件的作用域,区域之间独立工作互不影响,从而降低了代码的耦合度。
Vue 还可以对组件的选项轻松完成合并,让组件的功能变得灵活,使用起来更加方便。
3.4.1、mixins
mixins 是一种分发 Vue 组件中可复用功能的方式。
mixins 对象可以包含任何组件选项,当组件使用 mixins 时,将定义的 mixins 对象引入组件中即可使用,mixins 中的所有选项将会混入到组件自己的选项中。
<script>
// 定义 myMixin 对象
var myMixin = {
created() {
this.hello()
},
methods: {
hello: function () {
console.log('hello from mixin!');
}
}
}
var Component = Vue.extend({
mixins: [myMixin]
})
var component = new Component
</script>
3.4.2、render
在 Vue 中可以使用 Vue.render() 实现对虚拟 DOM 的操作。
在 Vue 中一般使用 template 来创建 HTML,但这种方式编程性不强,而使用 Vue.render() 可以更好地发挥 JavaScript 的编程能力。
<div id='root'>
<my-component>成功渲染</my-component>
</div>
<script>
Vue.component('my-component',{
// 该函数接收 createElement 参数,用来创建元素
render(createElement){
// 第一个参数表示创建 p 元素,第二个参数为配置对象,在对象中配置了 p 元素的样式,第三个参数为插槽内容 “成功渲染”,
// 插槽内容可以通过 $slot 来获取
return createElement('p',{
style: {
color: 'red',
fontSize: '16px',
backgroundColor: '#eee'
}
}, this.$slots.default)
}
})
new Vue({
el: '#root',
data: {
name: '潘嘉龙'
}
})
</script>
3.4.3、createElement
createElement() 函数返回的并不是一个实际的 DOM 元素,它返回的其实是一个描述节点,用来告诉 Vue 在页面上需要渲染什么样的节点。
这个描述节点也可以称为虚拟节点,简写为 VNode。
createElement() 函数的使用非常灵活,它的第一个参数可以是一个 HTML 标签名或组件选项对象。
第二个参数是可选的,可以传入一个与模板中属性对应的数据对象。
第三个参数是由 createElement() 构建而成的子级虚拟节点。
<div id='root'>
<my-component>
<template v-slot:header>
<div style="background-color:#ccc;height: 50px;">
这里是导航栏
</div>
</template>
<template v-slot:content>
<div style="background-color:#ddd;height: 50px;">
这里图书展示信息
</div>
</template>
<template v-slot:footer>
<div style="background-color:#eee;height: 50px;">
这里是底部信息
</div>
</template>
</my-component>
</div>
<script>
Vue.component('my-component',{
render(createElement){
return createElement('div',[
createElement('header', this.$slots.header),
createElement('content', this.$slots.content),
createElement('footer', this.$slots.footer),
])
}
})
new Vue({
el: '#root',
data: {
name: '潘嘉龙'
}
})
</script>