Self-study front-end development - VUE framework (2): template reference, event processing, form input binding, life cycle, listener, component foundation

@[TOC](Self-study front-end development - VUE framework (2) event processing, form input binding, life cycle, listener, component basics)

template reference

A template reference is a direct access to a template object instance . The most commonly used examples are methods using element objects or component objects . If you are using native DOM objects, you can also use JS to obtain element objects (for example, using the getElementByIdmethod). For VUE component objects, you need to use template references .

Set template reference

When using template references, you need to set a special attribute on the element or component ref, which can obtain a direct reference to the element or component after it is mounted.

<input ref="input">
<el-table ref="table">

Access template reference

After setting special properties , they can be accessed refthrough the properties of the application object.$refs

<script>
export default {
      
      
  mounted() {
      
      
    this.$refs.input.focus()
  }
}
</script>

<template>
  <input ref="input" />
</template>

Note that the template reference can only be accessed after the component is mounted .

use array

When v-fora template reference is used in a , the value contained in the corresponding reference is an array

<script>
export default {
      
      
  data() {
      
      
    return {
      
      
      list: [
        /* ... */
      ]
    }
  },
  mounted() {
      
      
    console.log(this.$refs.items)
  }
}
</script>

<template>
  <ul>
    <li v-for="item in list" ref="items">
      {
   
   { item }}
    </li>
  </ul>
</template>

Note that the ref array is not guaranteed to be in the same order as the source array.

function template reference

In addition to using a string value as a name, the ref attribute can also be bound to a function that will be called every time the component is updated. The function receives an element reference as its first argument:

<input :ref="el => { /* 将 el 赋值给一个数据属性或 ref 变量 */ }">

This will ensure the correct order when using arrays

    <li v-for="(item, index) in list" :ref="el => items[index] = el">
      {
   
   { item }}
    </li>

It should be noted that only dynamic :refbinding can be used to pass in a function. When the bound element is unloaded, the function will also be called once, and the el parameter will be null. It is also possible to bind a component method instead of an inline function.

In addition , the value of the bound ref attribute can be used without being defined. This value will actually be used as this.$refsthe key of this object to save the reference. When using :ref, you must use a function template reference, and the variables used inside the function must be defined and exposed, otherwise the reference will not be accessed normally.

user target audience

You can also use functions to assign template references to members of objects, so that several components can be classified

<script>
export default {
      
      
	data() {
      
      
		return {
      
      
			inputRefs: ref({
      
      })
		}
	},
	mounted() {
      
      
		console.log(this.$refs.inputRefs)
	}
}
</script>

<template>
    <input name='address' :ref="el => inputRefs['address'] = el" />
    <input name='age' :ref="el => inputRefs['age'] = el" />
</template>

Directly defined as an object or array member

refIt is not possible to directly set object members to properties of , for example

<input name='age' ref="input['age']" />

vue will input['age']treat it as a whole string instead of an object and its properties, when it is called this.$refs."input['age']". The same goes for arrays.

event handling

You can use v-onthe directive (abbreviated as @) to listen to DOM events and execute the corresponding JavaScript when the event is triggered. Usage: v-on:click="methodName"or @click="handler". Event handler values ​​can be:

  • Inline event handler : An inline JavaScript statement that is executed when the event is triggered (similar to onclick).
  • Method event handler : a property name or path pointing to a method defined on the component.

Inline event handler

Inline event handlers are typically used in simple scenarios such as:

data() {
    
    
  return {
    
    
    count: 0
  }
}
<button @click="count++">Add 1</button>
<p>Count is: {
   
   { count }}</p>

method event handler

As the logic of event handlers becomes more complex, the inline code approach becomes less flexible. Therefore, v-onit is also possible to accept a method name or a call to a method.

data() {
    
    
  return {
    
    
    name: 'Vue.js'
  }
},
methods: {
    
    
  greet(event) {
    
    
    // 方法中的 `this` 指向当前活跃的组件实例
    alert(`Hello ${
      
      this.name}!`)
    // `event` 是 DOM 原生事件
    if (event) {
    
    
      alert(event.target.tagName)
    }
  }
}
<!-- `greet` 是上面定义过的方法名 -->
<button @click="greet">Greet</button>

Method event handlers automatically receive native DOM events and trigger execution. event.target.tagNameIn the above example, we can access the DOM element through the triggered event .

Pass parameters to method event handler

In addition to directly binding the method name, you can also call methods in inline event handlers. This allows us to pass custom parameters to methods in place of native events:

methods: {
    
    
  say(message) {
    
    
    alert(message)
  }
}
<button @click="say('hello')">Say hello</button>
<button @click="say('bye')">Say bye</button>

Access event parameters in inline event handler

Sometimes we need to access native DOM events in inline event handlers. You can pass a special $eventvariable to the handler method, or use an inline arrow function:

<!-- 使用特殊的 $event 变量 -->
<button @click="warn('Form cannot be submitted yet.', $event)">
  Submit
</button>

<!-- 使用内联箭头函数 -->
<button @click="(event) => warn('Form cannot be submitted yet.', event)">
  Submit
</button>
methods: {
    
    
  warn(message, event) {
    
    
    // 这里可以访问 DOM 原生事件
    if (event) {
    
    
      event.preventDefault()
    }
    alert(message)
  }
}

event modifier

It is common to call event.preventDefault()or when handling an event . event.stopPropagation()Although we could call it directly within the method, it would be better if the method could focus more on the data logic without having to deal with the details of DOM events. To solve this problem, Vue v-onprovides event modifiers for . Modifiers are .directive suffixes represented by and include the following:

  • .stop - called event.stopPropagation().
  • .prevent - call event.preventDefault().
  • .self – Handlers are only triggered if the event originates from the element itself.
  • .capture – Add event listeners in capture mode.
  • .once - trigger the processing function at most once.
  • .passive - by { passive: true }attaching a DOM event.
<!-- 单击事件将停止传递 -->
<a @click.stop="doThis"></a>

<!-- 提交事件将不再重新加载页面 -->
<form @submit.prevent="onSubmit"></form>

<!-- 修饰语可以使用链式书写 -->
<a @click.stop.prevent="doThat"></a>

<!-- 也可以只有修饰符 -->
<form @submit.prevent></form>

<!-- 仅当 event.target 是元素本身时才会触发事件处理器 -->
<!-- 例如:事件处理器不来自子元素 -->
<div @click.self="doThat">...</div>

Key modifier

When listening for keyboard events, you often need to check for specific keystrokes. Vue allows adding key modifiers when listening to key events v-onor .@

<!-- 仅在 `key` 为 `Enter` 时调用 `submit` -->
<input @keyup.enter="submit" />

Key alias

Vue provides aliases for some commonly used keys:

  • .enter
  • .tab
  • .delete (captures the "Delete" and "Backspace" keys)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

System key modifier

The system key modifier is used to trigger the mouse or keyboard event listener, which will only be triggered when the key is pressed.

  • .ctrl
  • .alt
  • .shift
  • .meta

for example

<!-- Alt + Enter -->
<input @keyup.alt.enter="clear" />

<!-- Ctrl + 点击 -->
<div @click.ctrl="doSomething">Do something</div>

.exactmodifier

.exactModifiers allow control of a certain combination of system key modifiers required to trigger an event.

<!-- 当按下 Ctrl 时,即使同时按下 Alt 或 Shift 也会触发 -->
<button @click.ctrl="onClick">A</button>

<!-- 仅当按下 Ctrl 且未按任何其他键时才会触发 -->
<button @click.ctrl.exact="onCtrlClick">A</button>

<!-- 仅当没有按下任何系统按键时触发 -->
<button @click.exact="onClick">A</button>

Mouse button modifier

These modifiers limit the handler to events triggered by specific mouse buttons:

  • .left
  • .right
  • .middle

form input binding

When processing forms on the front end, we often need to synchronize the content of the form input box to the corresponding variables in JavaScript. Manually connecting value bindings and change event listeners can be cumbersome:

<input
  :value="text"
  @input="event => text = event.target.value">

v-modelThe directive simplifies this step for us:

<input v-model="text">

v-modelThe directive can be used on most form elements and will automatically use the corresponding combination of DOM properties and events based on the element used. v-modelInitial value, checked, or selected attributes on any form element are ignored. It will always treat the currently bound JavaScript state as the correct source of the data. dataYou should declare this initial value in JavaScript using the option.

value binding

For radio buttons, checkboxes and selector options, the value bound to v-model is usually a static string (or boolean for checkboxes):

<!-- `picked` 在被选择时是字符串 "a" -->
<input type="radio" v-model="picked" value="a" />

<!-- `toggle` 只会为 true 或 false -->
<input type="checkbox" v-model="toggle" />

<!-- `selected` 在第一项被选中时为字符串 "abc" -->
<select v-model="selected">
  <option value="abc">ABC</option>
</select>

But sometimes we may want to bind that value to dynamic data on the current component instance. This can be achieved using v-bind. Additionally, using v-bind allows us to bind option values ​​to non-string data types.

checkbox

<input
  type="checkbox"
  v-model="toggle"
  true-value="yes"
  false-value="no" />

true-valueand false-valueare unique properties of Vue and are only supported v-modelfor use with . The value of the toggle attribute here will be set to when selected 'yes'and to when deselected 'no'. You can also v-bindbind it to other dynamic values ​​by:

<input
  type="checkbox"
  v-model="toggle"
  :true-value="dynamicTrueValue"
  :false-value="dynamicFalseValue" />

true-valueThe and false-valueattributes do not affect the value attribute because the browser does not include unselected checkboxes when the form is submitted. To ensure that one of the two values ​​(for example: "yes" and "no") is submitted by the form, use radio buttons instead.

single button

<input type="radio" v-model="pick" :value="first" />
<input type="radio" v-model="pick" :value="second" />

pick will be set to first when the first button is selected and to second when the second button is selected.

Selector options

<select v-model="selected">
  <!-- 内联对象字面量 -->
  <option :value="{ number: 123 }">123</option>
</select>

v-modelValue binding for non-string types is also supported! In the above example, when an option is selected, selected will be set to the object literal value { number: 123 }.

modifier

v-modelModifiers that can be used are:

  • .lazyBy
    default, v-modelthe data will be updated after each input event (except for the status of the IME spelling phase). You can add .lazya modifier to update the data after each change event instead:
<!-- 在 "change" 事件后同步更新而不是 "input" -->
<input v-model.lazy="msg" />
  • .number
    If you want user input to be automatically converted to numbers, you can v-modeladd the .number modifier after to manage the input. If the value cannot be parseFloat()processed, the original value will be returned. .numberModifiers are type="number"sometimes .
<input v-model.number="age" />
  • .trim
    If you want to automatically remove spaces at both ends of user input by default, you can v-modeladd .trimthe modifier after:
<input v-model.trim="msg" />

v-model on component

life cycle

Each Vue component instance needs to go through a series of initialization steps when it is created, such as setting up data listening, compiling templates, mounting the instance to the DOM, and updating the DOM when the data changes. Along the way, it also runs functions called lifecycle hooks, giving developers the opportunity to run their own code at specific stages.

The life cycle of vue application components

The life cycle of a vue application is:

  1. Setup (create code, not yet enter the life cycle)
  2. Initialization event (beginning of life cycle)
  3. Create objects and inject reactive state (Init Options API)
  4. Template preprocessing (pre-compile template)
  5. Initialize and render the template, replace data (initial render)
  6. The component is mounted (Mounted) and re-rendered as needed (re-render)
  7. The red box in the component unmounted
    Insert image description here
    icon is the hook in the life cycle.

Register cycle hook

For example, the mounted hook can be used to run code after the component has completed its initial rendering and created the DOM node:

export default {
    
    
  mounted() {
    
    
    console.log(`the component is now mounted.`)
  }
}

There are other hooks that are called at different stages of the instance life cycle, the most commonly used are created, mounted, updated and unmounted.

The this context of all life cycle hook functions will automatically point to the component instance currently calling it. Note: Avoid using arrow functions to define life cycle hooks, because then you will not be able to get the component instance through this in the function.

created

The created hook is called after the initialization is completed. At this time, the initialized data and other status information can already be obtained. Usually an ajax request (method in methods) is made at this stage and the required data is loaded into data.

mounted

The mounted hook is called after the component is mounted. At this time, the component has been rendered (the component has not been rendered or created before $el), and the rendered element and node information can be obtained. Therefore, the operation code for initializing the page is generally written at this stage .

updated

The updated hook is called after the reactive state has been changed. At this point the state has been changed and the results are re-rendered to the page. Generally, the ajax code that saves the data to the database synchronously is executed here.

If you need to complete some operations before rendering, such as determining whether the data is valid, you can do it in the beforeUpdate hook.

unmounted

The unmounted hook is called when the component is unmounted and is mainly used to recycle resources.

listener

Computed properties allow us to declaratively calculate derived values. However, in some cases, we need to perform some "side effects" when the state changes: such as changing the DOM, or modifying the state of another place based on the results of an asynchronous operation. The listener will monitor changes in the specified data and trigger a callback function.

basic listening

You can use the watch option to trigger a function every time a reactive property changes. The function name of this function is the name of the monitored data variable, and the parameters receive the value of the variable before and after the change.

export default {
    
    
  data() {
    
    
    return {
    
    
      question: '',
      answer: 'Questions usually contain a question mark. ;-)'
    }
  },
  watch: {
    
    
    // 每当 question 改变时,这个函数就会执行
    question(newQuestion, oldQuestion) {
    
    
      if (newQuestion.includes('?')) {
    
    
        this.getAnswer()
      }
    }
  },
  methods: {
    
    
    async getAnswer() {
    
    
      this.answer = 'Thinking...'
      try {
    
    
        const res = await fetch('https://yesno.wtf/api')
        this.answer = (await res.json()).answer
      } catch (error) {
    
    
        this.answer = 'Error! Could not reach the API. ' + error
      }
    }
  }
}
<p>
  Ask a yes/no question:
  <input v-model="question" />
</p>
<p>{
   
   { answer }}</p>

The watch option also supports setting keys to .paths separated by :

export default {
    
    
  data:{
    
     return {
    
    
    a: {
    
    
      b: {
    
    
        c: 'hello'
      }
    }
  }},
  watch: {
    
    
    // 注意:只能是简单的路径,不支持表达式。
    a.b.c(newValue, oldValue) {
    
    
      // ...
    }
  }
}

deep listener

Watch is shallow by default: the monitored property will only trigger the callback function when a new value is assigned - changes to nested properties will not trigger. If you want to listen to all nested changes, you need to use a deep listener:

export default {
    
    
  watch: {
    
    
    someObject: {
    
    
      handler(newValue, oldValue) {
    
    
        // 注意:在嵌套的变更中,
        // 只要没有替换对象本身,
        // 那么这里的 `newValue` 和 `oldValue` 相同
      },
      deep: true
    }
  }
}

It should be noted that deep listening needs to traverse all nested properties in the object being listened to, which is very expensive when used for large data structures. So use it only when necessary and keep an eye on performance.

Listener for immediate callback

Watch is lazy by default: the callback will only be executed when the data source changes. But in some scenarios, you want to execute the callback immediately when creating the listener. For example, you want to request some initial data, and then re-request the data when the relevant state changes.

We can declare the listener with an object that has handlermethods and immediate: trueoptions, which forces the callback function to execute immediately:

export default {
    
    
  // ...
  watch: {
    
    
    question: {
    
    
      handler(newQuestion, oldQuestion) {
    
    
        // 在组件实例创建时会立即调用
        // 立即调用时,oldQuestion为 null
      },
      // 强制立即执行回调
      immediate: true
    }
  }
  // ...
}

The first execution of the callback function occurs just before the created hook. Vue has already processed the data, computed and methods options at this point, so these properties are available on the first call.

The triggering time of the callback

When reactive state is changed, it may trigger both Vue component updates and listener callbacks. By default, user-created listener callbacks will be called before the Vue component is updated. This means that the DOM accessed in the listener callback will be the state it was in before it was updated by Vue.

If you want to be able to access the DOM updated by Vue in the listener callback, you need to specify flush: 'post'the option:

export default {
    
    
  // ...
  watch: {
    
    
    key: {
    
    
      handler() {
    
    },
      flush: 'post'
    }
  }
}

this.$watch()

You can also $watch()create a listener imperatively using the component instance's method:

export default {
    
    
  created() {
    
    
    this.$watch('question', (newQuestion) => {
    
    
      // ...
    })
  }
}

This method is useful if you want to set up a listener under certain conditions, or only listen in response to user interaction. It also allows stopping the listener early.

Stop listener

$watch()Listeners declared with the watch option or instance methods will automatically stop when the host component is unloaded. Therefore, in most scenarios, there is no need to worry about how to stop it. In a few cases, you really need to stop a listener before the component is unloaded. In this case, you can call $watch()the function returned by the API:

const unwatch = this.$watch('foo', callback)

// ...当该侦听器不再需要时
unwatch()

Component Basics

Components allow us to divide the UI into independent, reusable parts and think about each part independently. Similar to how we nest HTML elements, Vue implements its own component model that allows us to encapsulate custom content and logic within each component. Even if the same component is reused, the components are independent of each other, allowing each component to maintain its own state independently.

define a component

When using the build step, we generally define the Vue component in a separate .vue file, which is called a single file component (SFC for short):

<script>
export default {
      
      
  data() {
      
      
    return {
      
      
      count: 0
    }
  }
}
</script>

<template>
  <button @click="count++">You clicked me {
   
   { count }} times.</button>
</template>

When not using a build step, a Vue component is defined as a JavaScript object containing Vue-specific options:

// 声明组件
// 注意,Vue 对象不是 vue 框架的类对象,而应该是 mount 后的 vm 应用实例对象。
Vue.component('组件名', {
    
    
  data() {
    
    		// 组件内部的数据
    ...
  },
  methods: {
    
    	// 组件内部的方法
  	...
  },
  template: ``,		// 组件的 html 代码
})

The template here is an inline JavaScript string that Vue will compile at runtime. You can also use the ID selector to point to an element (usually a native <template>element), and Vue will use its content as the template source.

The above example defines a component and exports itself in a .js file by default, but you can also export multiple components in one file through named export.

Use of components

The use of components is divided into global registration and local registration.

Global registration

Global registration is registered directly in the parent component, for example

// 定义一个子组件
const cpt = {
    
    
	data() {
    
     ... },
	methods: {
    
     ... },
	template: ``,
}
// 定义根组件(父组件)
let app = Vue.createApp({
    
    
	data() {
    
     ... },
	methods: {
    
     ... },
});
// 注册子组件到父组件内
app.component('子组件名', cpt);
// 挂载根组件
app.mount('#app');
<!-- 在模板中渲染子组件 -->
<div id='app'>
	<子组件名></子组件名>
</div>

partial registration

To use a child component locally, you need to import it in the parent component. Assuming that the counter component is placed in a ButtonCounter.vuefile called, this component will be exposed to the outside in the form of default export.

<script>
import ButtonCounter from './ButtonCounter.vue'

export default {
      
      
  components: {
      
      			// 局部注册
    'ButtonCounter': ButtonCounter 		// 组件名称
    // ButtonCounter			// js 中属性名和属性值都是同一个变量名,可以简写
  }
}
</script>

<template>
  <h1>Here is a child component!</h1>
  <!-- 使用时会转换成小写加 - 的形式,需注意 -->
  <button-counter/>
</template>

To expose an imported component to a template, you need to register it on the components option. This component will use its registered name as the tag name in the template.

Built-in component Transition

<Transition>Animation is applied when an element or component enters and leaves the DOM. <Transition>It is a built-in component, which means it can be used in any other component without registration. It can apply entry and exit animations to elements or components passed to it through the default slot. Entry or exit can be triggered by one of the following conditions:

  • Switch triggered by v-if
  • Switch triggered by v-show
  • <component>Dynamic components toggled by special elements

Basic usage

<button @click="show = !show">Toggle</button>
<Transition>
  <p v-if="show">hello</p>
</Transition>
.v-enter-active,
.v-leave-active {
    
    
  transition: opacity 0.5s ease;
}

.v-enter-from,
.v-leave-to {
    
    
  opacity: 0;
}

When an element is inserted or removed from a <Transition>component, the following things happen:

  • Vue will automatically detect whether the target element has CSS transitions or animations applied. If so, some CSS transition classes will be added and removed at appropriate times.
  • If there are JavaScript hooks that act as listeners, these hook functions will be called at the appropriate time.
  • If no CSS transition or animation is detected, and no JavaScript hook is provided, the insertion and deletion operations of the DOM will be performed after the browser's next animation frame.

CSS-based transition effects

The Transition component has a total of 6 CSS classes that are used for entering and leaving transition effects.

  1. v-enter-from: Enter the starting state of the animation. Added before the element is inserted and removed on the next frame after the element is inserted.
  2. v-enter-active: Enter the animation's active state. Applies to the entire entry animation stage. Added before the element is inserted and removed after the transition or animation is complete. This class can be used to define the duration, delay and speed curve type of the entry animation.
  3. v-enter-to: Enter the end state of the animation. It is added the next frame after the element is inserted (i.e. at the same time v-enter-from is removed), and removed after the transition or animation is complete.
  4. v-leave-from: Leave the starting state of the animation. Added immediately when the leaving transition effect is triggered, and removed one frame later.
  5. v-leave-active: Leave the active state of the animation. Applies to the entire leaving animation phase. Added immediately when the leaving transition effect is triggered, removed after the transition or animation completes. This class can be used to define the duration, delay and speed curve type of the exit animation.
  6. v-leave-to: Leave the end state of the animation. Added the next frame after a leave animation is triggered (that is, at the same time v-leave-from is removed), and removed after the transition or animation is complete.

You can pass a name attribute to <Transition>the component to declare a transition effect name:

<Transition name="fade">
  ...
</Transition>

For a named transition effect, the transition class that acts on it will be prefixed with its name rather than v. For example, the applied class in the example above would be fade-enter-active instead v-enter-active. The class for this "fade" transition should look like this:

.fade-enter-active,
.fade-leave-active {
    
    
  transition: opacity 0.5s ease;
}

.fade-enter-from,
.fade-leave-to {
    
    
  opacity: 0;
}

<Transition>Usually used with native CSS transitions, as in the example above. The transition CSS property is a shorthand for defining every aspect of a transition at once, including the properties that need to be animated, the duration, and the velocity curve.

<Transition name="slide-fade">
  <p v-if="show">hello</p>
</Transition>
/*
  进入和离开动画可以使用不同
  持续时间和速度曲线。
*/
.slide-fade-enter-active {
    
    
  transition: all 0.3s ease-out;
}

.slide-fade-leave-active {
    
    
  transition: all 0.8s cubic-bezier(1, 0.5, 0.8, 1);
}

.slide-fade-enter-from,
.slide-fade-leave-to {
    
    
  transform: translateX(20px);
  opacity: 0;
}

Guess you like

Origin blog.csdn.net/runsong911/article/details/127842002