Vue 3-ComponentAPI(コンビネーションAPI-共通部分)
84483 ワード
Composition API
解決:従来のoption api(オプション)構成方法でコンポーネントを書くときの問題は、ビジネスの複雑さがますます高くなるにつれて、コード量が増加し続けます.関連業務のコードはoptionの構成に従って特定の領域に書く必要があるため、後続のメンテナンスが非常に複雑であり、コードの多重性が高くない.
いくつかの関数があります.
setup:すべての組合せAPI関数はここで使用され、初期化時にのみ が実行される.関数オブジェクトを返す場合、オブジェクト内の属性またはメソッドは、 を直接使用することができる.
実行タイミング:
beforeCreateの前に実行(一度だけ実行)する場合、コンポーネントオブジェクトはまだ作成されていません.すなわち、thisはundefinedであり、thisによってdata/computed/methods/propsにアクセスすることはできません.すべてのcomposition API関連コールバック関数でもできません.
パラメータ: setup(props, context)/setup(props, {attrs, slots, emit}) props:props構成宣言および受信したすべての属性を含むオブジェクト . attrs:props構成で宣言されていない属性を含むオブジェクト.this.$に相当します.attrs slots:this.$に相当するすべての入力スロットの内容を含むオブジェクトslots emit:this.$に相当するカスタムイベントを配布するための関数emit
戻り値:は一般的にhtmlテンプレートにデータを提供するオブジェクトを返します. 戻りオブジェクトの属性はdata関数戻りオブジェクトの属性と結合してコンポーネントオブジェクトの属性となる. オブジェクトに戻るメソッドはmethodsのメソッドと成功したコンポーネントオブジェクトをマージするメソッドであり、重複名があればsetupが優先される.
注意:『できるだけ混ぜて使わないで!』-methodsではsetupが提供する属性とメソッドにアクセスできますが、setupメソッドではdataとmethodsにアクセスできません(thisオブジェクトはありません). setupはasync関数ではありません.戻り値はreturnのオブジェクトではなくpromiseなので、テンプレートにはreturnオブジェクトの属性データが見えません. 以下のコードは@vue/cli 4.5.10 に基づく部分TS(Typescript学習)構文
refとreactive
ref:基本タイプの応答データを定義します.応答式データを含む参照オブジェクトを返し、操作データを使用する.valueプロパティ、テンプレートには必要ありません.value
reactive:複数のデータの応答式を定義する. const proxy=reactive(obj):通常オブジェクトobjを受信し、その通常オブジェクトobjの応答型エージェントオブジェクトを返す. 応答変換は「深層」です.オブジェクト内部のネストされたすべての属性に影響します. 内部のES 6に基づくProxy実装は、プロキシオブジェクトによって操作するソースオブジェクトの内部データが応答式である.
refとreactiveの詳細: refは、基本タイプのデータを処理するために用いる、reactiveは、オブジェクト(再帰的深度応答式) を処理するために用いる.オブジェクト/配列にrefを入れると、内部で自動的にオブジェクト/配列がreactiveのプロキシオブジェクト に変換されます. ref内部:value属性に を実現する. reactive内部: を操作する. refのデータ操作:jsで行う.value、テンプレートに不要(内部解析テンプレートの場合.valueが自動的に追加されます)
vue 2とvue 3の応答式を比較する
vue 2の応答式:オブジェクト:definePropertyによってオブジェクトの既存の属性値の読み取りと変更をハイジャック(監視/ブロック)する配列:配列更新配列の一連の更新要素を書き換える方法によって要素修正のハイジャックを実現する.
Vue 3の応答式:Proxy(プロキシ):dataの任意の属性に対する任意(13種類)の操作をブロックし、属性値の読み書き、属性の追加、属性の削除などを含む...Reflect(反射):被プロキシオブジェクトの対応する属性を動的に特定する操作.
vue 2応答欠陥:オブジェクトが直接追加した属性または既存の属性を削除する場合、インタフェースは自動的に を更新しません.は直接下付きで要素を置換したりlengthを更新したりして、インタフェースはarr[1]={} を自動的に更新しません.
計算プロパティと監視
computed関数watch関数watchEffect関数
ライフサイクルフック関数
vue 2とvue 3の比較:
beforeCreate->setup()created->setup()beforeMount->onBeforeMounted->onMounted beforeUpdate->onBeforeUpdate->onUpdate->onUpdated beforeDestroy->onBeforeUnmounted destroyed->onUnmounted
カスタムhoos関数
hooks関数とは,
次のように呼び出されます.
toRefs
応答型オブジェクトを通常オブジェクトに変換します.この通常オブジェクトの各propertyはrefオブジェクトです.
解決:従来のoption api(オプション)構成方法でコンポーネントを書くときの問題は、ビジネスの複雑さがますます高くなるにつれて、コード量が増加し続けます.関連業務のコードはoptionの構成に従って特定の領域に書く必要があるため、後続のメンテナンスが非常に複雑であり、コードの多重性が高くない.
いくつかの関数があります.
setup
ref
reactive
watchEffect
computed
toRefs
hooks
...
setup:
html
で実行タイミング:
beforeCreateの前に実行(一度だけ実行)する場合、コンポーネントオブジェクトはまだ作成されていません.すなわち、thisはundefinedであり、thisによってdata/computed/methods/propsにアクセスすることはできません.すべてのcomposition API関連コールバック関数でもできません.
パラメータ:
戻り値:
注意:
// App.vue
<template>
<h2>App </h2>
<h4>{
{
msg}}</h4>
<hr>
<Child :msg=msg @XXX="XXX"/> <!-- msg2=' ' -->
<button @click="updateMsg">up-</button>
<button @click="msg += '======'">up=</button>
</template>
<script lang="ts">
import {
defineComponent,ref, reactive } from 'vue';
import Child from './components/Child.vue'
export default defineComponent({
name: 'App',
components: {
Child
},
setup() {
const msg = ref('what are you doing?')
function updateMsg() {
msg.value+='-------'
}
function XXX(txt: string) {
msg.value+=txt
}
return{
msg,
updateMsg,
XXX
}
}
})
</script>
// Child.vue
<template>
<h3>Child </h3>
<h5>{
{
msg}}</h5>
<h5>count:{
{
count}}</h5>
<button @click="emitXX"> emit</button>
</template>
<script>
import {
defineComponent} from 'vue'
export default defineComponent({
name: 'Child',
data() {
return{
count: 10
}
},
props: ['msg'],
beforeCreate() {
console.log('beforeCreate ...');
},
inheritAttrs: false, // ( vue warn)
setup(props, context) {
console.log('props:', props);console.log('props.msg:', props.msg);
console.log('context:', context);
// console.log('context.attrs:', context.attrs.msg2);
console.log('setup ... this:', this);
const showMsg1 = ()=>{
console.log('setup showMsg1 ...');
}
//
function emitXX() {
context.emit('XXX','1234') // msg
}
return{
showMsg1,
emitXX
}
},
//
mounted() {
console.log('mounted ... this:',this);
},
//
methods: {
showMsg2() {
console.log('methods showMsg2 ...');
}
}
})
</script>
refとreactive
ref:基本タイプの応答データを定義します.応答式データを含む参照オブジェクトを返し、操作データを使用する.valueプロパティ、テンプレートには必要ありません.value
reactive:複数のデータの応答式を定義する.
// App.vue
<template>
<div>hello Vue3!</div>
<!-- <button @click="add">
Count is: {
{
count }}
</button> -->
<button @click="updateuser">
updateuser
</button>
<h2>name:{
{
user.name}}</h2>
<h2>age:{
{
user.age}}</h2>
<h2>hsb:{
{
user.hsb}}</h2>
</template>
<script lang="ts">
// api
import {
defineComponent,ref, reactive } from 'vue';
export default defineComponent({
name: 'App',
//
// vue2:
// data(){
// return {
// count: 0
// }
// },
// methods: {
// add (){
// this.count++;
// }
// }
// vue3:
setup(){
// API ,
// let number = 10 // ( : , )
const number = ref(10) // ref
// console.log(number);
function add() {
number.value ++
}
/**
* :
const proxy = reactive(obj): obj obj
“ ”:
ES6 Proxy ,
*/
const obj ={
name: 'y',
age: 24,
hsb: {
name: 'z',
age: 24,
car: [' ','BWM',' ']
}
}
// , , proxy , obj
const user = reactive(obj)
// user ,obj
console.log(user);
const updateuser = ()=>{
user.name+='--'
user.age-=1
user.hsb.name+='---'
user.hsb.car[0]=' '
}
return {
// setup , ,
number,
add2:add,
user,
updateuser
}
}
});
</script>
refとreactiveの詳細:
getter/setter
を追加することによってデータのハイジャックProxy
を用いる対象内部の全てのデータのハイジャックを実現し、Reflect
により対象内部データ<template>
<h2>ref _ reactive </h2>
<h3>m1:{
{
m1}}</h3>
<h3>m2:{
{
m2}}</h3>
<h3>m3:{
{
m3}}</h3>
<hr>
<button @click="update">upda</button>
</template>
<script lang="ts">
import {
defineComponent,ref, reactive } from 'vue';
export default defineComponent({
name: 'App',
setup() {
const m1 = ref('abc')
const m2 = reactive({
name: 'xiaox',
wife: {
name: 'hah'
}
})
const m3 = ref({
name: 'aa',
wife: {
name: 'bb'
}
})
console.log('m3',m3); // ref / reactive
const update = () =>{
m1.value += '111111'
m2.wife.name += '222222'
m3.value.name += '333333'
}
return{
m1,
m2,
m3,
update
}
}
})
</script>
vue 2とvue 3の応答式を比較する
vue 2の応答式:オブジェクト:definePropertyによってオブジェクトの既存の属性値の読み取りと変更をハイジャック(監視/ブロック)する配列:配列更新配列の一連の更新要素を書き換える方法によって要素修正のハイジャックを実現する.
Object.defineProperty(data, 'count', {
get () {
},
set () {
}
})
Vue 3の応答式:Proxy(プロキシ):dataの任意の属性に対する任意(13種類)の操作をブロックし、属性値の読み書き、属性の追加、属性の削除などを含む...Reflect(反射):被プロキシオブジェクトの対応する属性を動的に特定する操作.
<script>
const user = {
name: ' ',
age: 19,
wife: {
name: ' ',
age: 18,
}
}
const proxyUser = new Proxy(user, {
get(target, prop) {
console.log('get ..');
return Reflect.get(target, prop)
},
set(target, prop, val) {
console.log('set ..');
return Reflect.set(target, prop, val)
},
deleteProperty(target, prop) {
console.log('delete ..');
return Reflect.deleteProperty(target, prop)
}
})
//
console.log(proxyUser.name);
//
proxyUser.name = ' 2'
console.log(user.name);
//
proxyUser.gender = ' '
console.log(user);
//
delete proxyUser.age
console.log(user);
//
proxyUser.wife.name = ' 2'
console.log(user);
</script>
vue 2応答欠陥:
計算プロパティと監視
computed関数watch関数watchEffect関数
<template>
<h2> </h2>
<fieldset>
<legend> </legend>
:<input type="text" placeholder=" " v-model="user.lastName"><br>
:<input type="text" placeholder=" " v-model="user.firstName"><br>
</fieldset>
<fieldset>
<legend> </legend>
fullName1:<input type="text" placeholder=" " v-model="fullName1"><br>
fullName2: <input type="text" placeholder=" " v-model="fullName2"><br>
fullName3:<input type="text" placeholder=" " v-model="fullName3"><br>
</fieldset>
</template>
<script lang="ts">
import {
defineComponent,computed, watch, watchEffect, ref, reactive } from 'vue';
export default defineComponent({
name: 'App',
setup() {
const user = reactive({
//
lastName: ' ',
//
firstName: ' '
})
//
// vue3: computed , get
const fullName1 = computed(()=>{
// ref
console.log('fullName1 get...');
return `${
user.lastName}_${
user.firstName}`
})
// computed , get set
const fullName2 = computed({
get() {
// console.log('fullName2 get...');
return `${
user.lastName}_${
user.firstName}`
},
set(val: string) {
console.log('fullName2 set...');
const name = val.split('_')
user.lastName = name[0]
user.firstName = name[1]
}
})
// :
const fullName3 = ref('')
watch(user, ({
lastName, firstName})=>{
fullName3.value = lastName + '_' + firstName
}, {
immediate: true, deep: true}) // watch,
// watchEffect(()=>{ //
// fullName3.value = user.lastName + '_' + user.firstName
// })
watch(fullName3, ()=>{
const name = fullName3.value.split('_')
user.lastName = name[0]
user.firstName = name[1]
}, {
immediate: true, deep: true})
// watchEffect(()=>{
// const name = fullName3.value.split('_')
// user.lastName = name[0]
// user.firstName = name[1]
// })
// watch :
// 1, :
watch([user, fullName3], ()=>{
console.log(' ...');
})
// 2, :
watch([()=>user.lastName, ()=>user.firstName], ()=>{
console.log(' ...');
})
return {
user,
fullName1,
fullName2,
fullName3
}
}
})
</script>
ライフサイクルフック関数
vue 2とvue 3の比較:
beforeCreate->setup()created->setup()beforeMount->onBeforeMounted->onMounted beforeUpdate->onBeforeUpdate->onUpdate->onUpdated beforeDestroy->onBeforeUnmounted destroyed->onUnmounted
カスタムhoos関数
hooks関数とは,
class
を用いずに状態データを管理し,論理的思考を抽出する多重機能関数である.// useMousePosition.ts
//
import {
ref, onMounted, onBeforeUnmount } from 'vue'
export default function () {
const x = ref(-1)
const y = ref(-1)
const clickCB = (event: MouseEvent) => {
x.value = event.pageX
y.value = event.pageY
}
// , API
onMounted(() => {
window.addEventListener('click', clickCB)
})
// API
onBeforeUnmount(() => {
window.removeEventListener('click', clickCB)
})
return{
x,
y
}
}
// useRequest.ts
//
import axios from 'axios';
import {
ref } from "vue";
// ajax
// TS
export default function <T>(url: string) {
const loading = ref(true)
const data = ref<T | null>(null)
const errMsg = ref('')
//
axios.get(url).then(res=>{
loading.value = false
data.value = res.data
}).catch(err=>{
loading.value = false
errMsg.value = err.message || ' '
})
return{
loading, //
data, //
errMsg //
}
}
次のように呼び出されます.
// App.vue
<template>
<h2> hook </h2>
<h4> class </h4>
<h3>x: {
{
x}}、y: {
{
y}}</h3>
<hr>
<h3 v-if="loading"> ...</h3>
<h3 v-else-if="errMsg"> : {
{
errMsg}}</h3>
<ul v-else>
<li>id: {
{
data.id}}</li>
<li>address: {
{
data.address}}</li>
<li>distance: {
{
data.distance}}</li>
</ul>
<hr>
<!-- -->
<ul v-for="item in data" :key="item.id">
<li>id: {
{
item.id}}</li>
<li>title: {
{
item.title}}</li>
<li>price: {
{
item.price}}</li>
</ul>
</template>
<script lang="ts">
//
interface AddressData{
id: number;
address: string;
distance: string;
}
interface ProductsData{
id: string;
title: string;
price: number;
}
import {
defineComponent, watch } from 'vue'
import useMousePosition from './hooks/useMousePosition'
import useRequest from './hooks/useRequest'
export default defineComponent({
name: 'App',
setup(){
//
const {
x, y} = useMousePosition()
//
// const {loading, data, errMsg} = useRequest('/data/address.json') //
const {
loading, data, errMsg} = useRequest<ProductsData[]>('/data/products.json') //
//
watch(data, ()=>{
if (data.value) {
console.log(data.value.length);
}
})
return {
x,
y,
loading,
data,
errMsg
}
}
})
</script>
toRefs
応答型オブジェクトを通常オブジェクトに変換します.この通常オブジェクトの各propertyはrefオブジェクトです.
<template>
<h2>toRefs </h2>
<h4> , property ref </h4>
<h3>name: {
{
state.name}}</h3>
<h3>age: {
{
state.age}}</h3>
<h3>name: {
{
name}}</h3>
<h3>age: {
{
age}}</h3>
<hr>
</template>
<script lang="ts">
import {
defineComponent, reactive, toRefs, ref} from 'vue'
export default defineComponent({
name: 'App',
setup(){
const state = reactive({
name: ' ',
age: 20
})
// const state2 = toRefs(state)
// console.log('state: ', state);
// console.log('state2: ', state2);
const {
name, age} = toRefs(state)
//
setInterval(() => {
state.name += "1"
state.age += 1
// state2.name.value += "2"
// state2.age.value += 2
// name += '3' // error
// age += 3 // error
}, 1500);
return{
state,
// ...state, //
// ...state2,
name,
age
}
}
})
</script>