Vue 选项式API

yuhuo2022-05-14开发库框架库

功能选项

name

显式声明组件展示时的名称。

export default {
    name: "MyComponent",
};

name选项 | Vue.js (vuejs.org)open in new window

template

字符串模板

export default {
    /* html */
    template: `<div>count is {{ count }}</div>`,
};

ID 选择器模板

<template id="component_app">
	<div>count is {{ count }}</div>
</template>
export default {
    template: "#component_app",
};

DOM 模板解析注意事项open in new window

template 标签模板

<template>
	<span>{{ message + getMessage() + 1 }}</span>
    <span>{{ message ? 'YES' : 'NO' }}</span>
    <span>{{ message.split('').reverse().join('') }}</span>
</template>
<script>
export default {
    // 不需要template字段
};
</script>

components

局部注册组件

<template>
	<div class="app">
        <MyDialog />
        <MyDialog></MyDialog>
    </div>    
</template>
<script>
import MyDialog from './MyDialog.vue'
export default {
  	components: { MyDialog },
}
</script>

expose

指定当前组件暴露到其他组件的属性和方法,未指定时默认全部暴露。

<!-- 父组件 -->
<template>
	<div class="parent">
		<Child ref="child"></Child>
    </div>
</template>
<script>
import Child from './Child.vue'
export default {
  	components: { Child },
    expose: ['status', 'say'],
    data() {
        return {
            status: 1,
            message: "信息",
        };
    },
    methods: {
        say() {},
        run() {},
    },
    mounted() {
        // 获取子组件对象
        const child = this.$refs.child;
        // 访问子组件对象的属性方法
        console.log(child.type);
        console.log(child.name); // 子组件的 expose 未指定,返回 undefined
        child.show();
        child.hide(); // 子组件的 expose 未指定,报错提示:child.hide is not a function
    },
}
</script>
<!-- 子组件 -->
<template>
	<div class="child"></div>
</template>
<script>
export default {
  	expose: ['type', 'show'],
    data() {
        return {
            type: 1,
            name: "名称",
        };
    },
    methods: {
        show() {},
        hide() {},
    },
    mounted() {
        // 获取父组件对象
        const parent = this.$parent;
        // 访问父组件对象的属性方法
        console.log(parent.status);
        console.log(parent.message); // 父组件的 expose 未指定,返回 undefined
        parent.say();
        parent.run(); // 父组件的 expose 未指定,报错提示:parent.run is not a function
    },
}
</script>

props

父组件给子组件传递数据

<!-- 父组件 -->
<template>
	<div class="parent">
        <!-- 动态 -->
		<Child :message="message" v-bind="post"></Child>
        
        <!-- 静态:需要使用 v-bind 使其作为 JavaScript 表达式,而不是字符串-->
        <Child 
               :likes="42"
               :is-published="false"
               :comment-ids="[234, 266, 273]"
               :author="{
                	name: 'Veronica',
                	company: 'Veridian Dynamics'
              	}"
               >
    	</Child>
    </div>
</template>
<script>
import Child from './Child.vue'
export default {
  	components: { Child },
    data() {
        return {
            message: "信息",
            post: {
                id: 1,
                title: 'My Journey with Vue'
        	}
        };
    },
}
</script>
<!-- 子组件 -->
<template>
	<div class="child">{{ message }}</div>
</template>
<script>
export default {
    // prop是只读的
  	props: ['message'],
    data() {
        return {
            // 作为初始值定义为数据以便更改
        	msg: this.message,
        }
	},
    computed: {
        // 使用计算属性进行转换
        trimMessage() {
        	return this.message.trim();
        }
	}
}
</script>

emits

<!-- 父组件 -->
<template>
	<div class="parent">
        <!-- 监听子组件的自定义事件 -->
		<Child @enlarge="handle"></Child>
    </div>
</template>
<script>
import Child from './Child.vue'
export default {
  	components: { Child },
    methods: {
        handle(param1, param2) {
            // doSomething
        },
    },
}
</script>
<!-- 子组件 -->
<template>
	<button @click="show()">按钮</button>
</template>
<script>
export default {
    // 声明自定义事件(当与原生事件重名时可以避免被当成原生事件)
  	emits: ['enlarge'],
    methods: {
        show() {
            // 触发事件
            this.$emit('enlarge', "参数1", "参数2")
        },
    },
}
</script>

inheritAttrs

透传属性继承

透传属性

父组件中定义子组件的属性,没有在子组件中 props 声明,则会透传成子组件的属性。

父组件中定义子组件的事件监听器,没有在子组件中 emits 声明,则会透传成子组件的原生事件监听器属性。

<!-- 父组件 -->
<template>
	<div class="parent">
		<Child class="message" @click="show"></Child>
    </div>
</template>
<script>
import Child from './Child.vue'
export default {
  	components: { Child },
    methods: {
        show() {}
    }
}
</script>
<!-- 单根节点子组件 -->
<template>
	<div class="child"></div>
	<!-- 继承了透传属性 class 和 onClick -->
	<!-- <div class="child  message" onClick="ƒ"></div> -->
</template>
<script>
export default {
    inheritAttrs: true, // 是否继承透传属性,默认 true
    mounted() {
      	// 获取透传属性(不管是否继承)
      	console.log(this.$attrs);
        // {class: 'message', onClick: ƒ}
  	}
}
</script>
<!-- 多根节点子组件 -->
<template>
	<header></header>
	<!-- 无法继承透传属性,需要显示指定 v-bind="$attrs" -->
	<!-- 或者设置 inheritAttrs: false,否则会有警告 -->
    <main v-bind="$attrs"></main>
    <footer></footer>
</template>
<script>
export default {
    inheritAttrs: false,
}
</script>

provide

为后代组件供给数据

// keys.js
export default {
    message: Symbol(),
    info: Symbol(),
}
import { computed } from 'vue'
import keys from './keys.js'

export default {
    // 对象形式
  	provide: {
    	message: "hello",
        // symbol注入名
        [keys.message]: "value",
  	},
    // 函数形式
    provide() {
        return {
            // 可以访问到 `this`
          	message: this.message
            // 使用计算属性保存响应性
      		message: computed(() => this.message)
        }
    },
    data() {
    	return {
      		message: 'hello!'
    	}
  	},
}

inject

注入祖先组件供给的数据

import keys from './keys.js'
export default {
    // 直接注入
    inject: ['message'],
    // 配置注入
    inject: {
        // 别名
    	localMessage: {
      		from: 'message', // 原名
            default: 'default value', // 默认值
    	}
        myMessage: {
      		from: keys.message, // symbol形式原名
            default: () => ({ name: 'John' }) // 函数形式默认值
    	}
  	}
    data() {
    	return {
            // data 可以访问到注入的数据
      		info: this.message,
    	}
  	},
}

data

数据

export default {
    data() {
        return {
            name: 'John',
        };
    },
};

computed

计算属性

export default {
    data() {
        return {
            count: 0,
            firstName: 'John',
			lastName: 'Doe'
        };
    },
    computed: {
        // 只读计算属性
        doubleCount() {
            return this.count * 2;
        },
        // 读写计算属性
        fullName: {
          get() {
            return this.firstName + ' ' + this.lastName
          },
          set(value) {
            [this.firstName, this.lastName] = value.split(' ')
          }
        }
    },
};

watch

侦听器

export default {
	data() {
    	return {
      		message: '',
        	user: {
                name: "",
            },
    	}
  	},
  	watch: {
        // 基本侦听
    	message(newValue, oldValue) {
        	// doSomething
    	},
        "user.name"(newValue, oldValue) {
        	// doSomething
    	}
        // 侦听配置
        user: {
        	// 侦听回调
            handler(newValue, oldValue) {
            	// doSomething
          	},
    		// 深层侦听对象以及对象里的属性变化
          	deep: true,
			// 创建侦听器时,立即执行一遍回调
			immediate: true,
            // 刷新时机:pre 组件更新之前(默认),post 组件更新之后,sync 异步
            flush: 'post',
        }
  	},
}

filters

过滤器

<template>
	{{ score | omit(999999) }}
</template>
<script>
export default {
    data: function () {
        return {
            score: 123,
        };
    },
  	filters: {
        omit: function (value, max) {
            return value > max ? max + "+" : value;
        },
    },
}
</script>

methods

方法

methods: {
	increment() {
		this.count++;
	}
},

mixins

一个选项对象的数组,这些对象都将被混入到当前组件的实例中。

const mixin = {
  created() {
    console.log(1)
  }
}

createApp({
  created() {
    console.log(2)
  },
  mixins: [mixin]
})

// => 1
// => 2

extends

要继承的“基类”组件。

const CompA = { ... }

const CompB = {
  extends: CompA,
  ...
}

directives

自定义指令

<template>
	<!-- 使用 v-focus 指令 -->
	<input v-focus/>
</template>
<script>
export default {
  	directives: {
        // 定义 v-focus 指令
    	focus: {
            // 在绑定元素的 attribute 前或事件监听器应用前调用
          	created(el, binding, vnode, prevVnode) {},
          	// 在元素被插入到 DOM 前调用
         	beforeMount() {},
          	// 在绑定元素的父组件及他自己的所有子节点都挂载完成后调用
          	mounted(el) {
              	el.focus();
          	},
          	// 绑定元素的父组件更新前调用
          	beforeUpdate() {},
          	// 在绑定元素的父组件及他自己的所有子节点都更新后调用
          	updated() {},
          	// 绑定元素的父组件卸载前调用
          	beforeUnmount() {},
          	// 绑定元素的父组件卸载后调用
          	unmounted() {}
        }
  	}
}
</script>

钩子参数

  • el:指令绑定到的元素。这可以用于直接操作 DOM。
  • binding:一个对象,包含以下 property。
    • value:传递给指令的值。例如在 v-my-directive="1 + 1" 中,值是 2
    • oldValue:之前的值,仅在 beforeUpdateupdated 中可用。无论值是否更改,它都可用。
    • arg:传递给指令的参数 (如果有的话)。例如在 v-my-directive:foo 中,参数是 "foo"
    • modifiers:一个包含修饰符的对象 (如果有的话)。例如在 v-my-directive.foo.bar 中,修饰符对象是 { foo: true, bar: true }
    • instance:使用该指令的组件实例。
    • dir:指令的定义对象。
  • vnode:代表绑定元素的底层 VNode。
  • prevNode:之前的渲染中代表指令所绑定元素的 VNode。仅在 beforeUpdateupdated 钩子中可用。

render

以编程式来创建组件虚拟 DOM 树的函数,比 template 拥有更高的优先级。

compilerOptions

配置组件模板的运行时编译器选项。

参考:应用实例 / config.compilerOptions

生命周期钩子

beforeCreate

在组件实例初始化完成之后立即调用(Options API 还未初始化)

export default {
    beforeCreate() {},
};

created

在组件实例处理完所有与状态相关的选项后调用(Options API 已初始化)

export default {
    created() {},
};

beforeMount

在组件被挂载之前调用(DOM 还未渲染)

export default {
    beforeMount() {},
};

mounted

在组件被挂载之后调用(DOM 已渲染)

export default {
    mounted() {},
};

beforeUpdate

在组件即将因为一个响应式状态变更而更新其 DOM 树之前调用

export default {
    beforeUpdate() {},
};

updated

在组件即将因为一个响应式状态变更而更新其 DOM 树之前调用

export default {
    updated() {},
};

beforeUnmount

在一个组件实例被卸载之前调用

export default {
    beforeUnmount() {},
};

unmounted

在一个组件实例被卸载之后调用

export default {
    unmounted() {},
};

errorCaptured

在捕获了后代组件传递的错误时调用

export default {
    errorCaptured() {},
};

activated

若组件实例是若组件实例是 <KeepAlive> 缓存树的一部分,当组件被插入到 DOM 中时调用

export default {
    activated() {},
};

deactivated

若组件实例是若组件实例是 <KeepAlive> 缓存树的一部分,当组件从 DOM 中被移除时调用

export default {
    deactivated() {},
};

renderTracked

在一个响应式依赖被组件的渲染作用追踪后调用 Dev only

export default {
    renderTracked() {},
};

renderTriggered

在一个响应式依赖被组件触发了重新渲染之后调用 Dev only

export default {
    renderTriggered() {},
};

serverPrefetch

当组件实例在服务器上被渲染之前要完成的异步函数 SSR only

export default {
    serverPrefetch() {},
};

Last Updated 2024/3/14 09:51:53