Modular API

What is a composite API

The official address

As projects grow and functions become more complex, defined data and operations on its data are placed in different places, such as methods and Watch, and fragmentation makes it difficult to understand and maintain complex components. The separation of options masks a potential logical problem. In addition, when dealing with a single logical concern, we have to constantly “jump” to blocks of options for related code, hence the emergence of composite apis

use

The composite API is implemented in VUe3 through the setup function, which takes props and context

When the setup function is executed, the instance is not created, so there is no reference to this in the setup function

parameter

  • props

    export default {
      props: {
        title: String
      },
      setup(props) {
        console.log(props.title)
    
    		// If you want to use structure assignment
    		const { title } = toRefs(props)
      }
    }
    Copy the code
  • context

    Context is a plain JavaScript object that exposes the component’s three properties

    export default {
      setup(props, context) {
        // Attribute (non-responsive object)
        console.log(context.attrs)
    
        // slot (non-responsive object)
        console.log(context.slots)
    
        // Trigger event (method)
        console.log(context.emit)
      }
    }
    Copy the code

Responsive foundation

Change data to reactive data, now ref, reactive

  • The ref function changes the basic data type into responsive data, essentially a proxy object, a reference object

    import { ref } from 'vue'
    
    const counter = ref(0)
    
    console.log(counter) // Proxy {value: 0}
    console.log(counter.value) / / 0
    
    counter.value++
    console.log(counter.value) / / 1
    Copy the code

    The ref function can also retrieve HTML objects from the template

    <div ref='homeDiv'>home</div>
    
    setup() {
    	const homeDiv = ref(null)
    	// Get the DOM element after the mount
    	onMounted(() = > {
    	   console.log(homeDiv.value)
    	})
    	return {
    		// Remember to export it
    		homeDiv
    	}
    }
    Copy the code
  • Reactive functions that turn objects into reactive data and return a reactive copy of the object

    import { reactive } from 'vue'
    
    const person = reactive({
    	name: 'Joe'.age: 22.languages: ['English'.'Chinese']})return {
    	// toRefs converts reactive objects to normal objects, where each property of the resulting object is a ref pointing to the corresponding property of the original object. toRefs(person) }Copy the code
  • ToRef function

    Create a new REF for a property on the source responsive object. The REF can then be passed, maintaining a reactive connection to its source property

    const state = reactive({
      foo: 1.bar: 2
    })
    
    const fooRef = toRef(state, 'foo')
    
    fooRef.value++
    console.log(state.foo) / / 2
    
    state.foo++
    console.log(fooRef.value) / / 3
    Copy the code
  • Calculate attribute

    Takes a getter function and returns an immutable reactive ref object from the value returned by the getter

    const count = ref(1)
    const plusOne = computed(() = > count.value + 1)
    
    console.log(plusOne.value) / / 2
    
    plusOne.value++ // error
    Copy the code

    You can also accept objects from the get and set functions

    const count = ref(1)
    const plusOne = computed({
      get: () = > count.value + 1.set: val= > {
        count.value = val - 1
      }
    })
    
    plusOne.value = 1
    console.log(count.value) / / 0
    return {
    	count,
    	plusOne
    }
    Copy the code
  • Monitor properties

    You can listen directly on a ref object or a getter function with a return value

    // Listen for a getter
    const state = reactive({ count: 0 })
    watch(
      () = > state.count,
      (count, prevCount) = > {
        console.log(count)
      }
    )
    
    // Listen directly on a ref
    const count = ref(0)
    watch(count, (count, prevCount) = > {
      console.log(count)
    })
    Copy the code

    Multiple objects can be monitored

    watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) = > {
      / *... * /
    })
    Copy the code

    The life cycle

    Since no component instance is created when the setup function is created, there are no beforeCreate and Created lifecycle hooks, and operations that occur in either lifecycle can be performed in the Setup function

    onBeforeMount(() = > {
    	console.log('onBeforeMount')
    })
    onMounted(() = > {
       console.log('mounted! ')
     })
    onBeforeUpdate(() = > {
    	console.log('onBeforeUpdate! ')
    })
    onUpdated(() = > {
      console.log('updated! ')
    })
    onUnmounted(() = > {
      console.log('unmounted! ')})Copy the code

    Dojo.provide and inject

    Used when passing values between components

    • The provide function allows you to define property, name, and value with two parameters
    provide: {
        location: 'North Pole'.geolocation: {
          longitude: 90.latitude: 135}}Copy the code
    • The Inject function allows you to take two arguments, the name of the property to inject and the default value

    You can make it responsive, or you can decorate it with readonly if you want the passed value to remain unchanged

    const location = ref('North Pole')
    const geolocation = reactive({
      longitude: 90.latitude: 135
    })
    
    provide('location', readonly(location))
    provide('geolocation', geolocation)
    Copy the code

    The instance

    A tosdolist component is made, which inputs a value and displays it in the list below. It can be separated from the logic to make the whole logic clearer

    <ul>
       <li v-for="(item, index) in list" :key="index">
          <div v-if="item.edit" style="margin-right: 10px">{{ item.val }}</div>
            <el-input
              style="width: 300px"
              v-else
              v-model="item.val"
              @blur="item.edit = ! item.edit"
            />
           <div>
              <el-button @click="edit(index)" type="primary">The editor</el-button>
              <el-button @click="remove(index)" type="primary">delete</el-button>
           </div>
         </li>
      </ul>
    
    setup() {
    	const {state, handleChange, edit, remove} = useState()
    	return {
    		...toRefs(state),
        handleChange,
        edit,
        remove,
    	}
    }
    Copy the code
    import { reactive} from "vue";
    import Home from "@/model/home";
    type stateType = {
    	state: Home,
    	handleChange: () = > void.edit: (val: number) = > void.remove: (val: number) = > void
    }
    export function useState() :stateType {
      const state: Home = reactive({
        input: "".list: [],});const handleChange = () = > {
    		state.list.push({
    			edit: true.val: state.input,
    		});
    		state.input = "";
    	};
    	const edit = (index: number) = > {
    		state.list[index].edit = false;
    	};
    	const remove = (index: number) = > {
    		state.list.splice(index, 1);
    	};
    	return {
    		state, 
    		handleChange,
    		edit,
    		remove
    	}
    }
    Copy the code