Basic example
<! -- Counter. Vue: Define Counter component --><template>
<button @click="inc">I got clicked {{count}} times</button>
</template>
<script>
export default {
data() { return { count: 0 }},
methods: {
inc() { this.count++; }}}</script>
Copy the code
<! -- App.vue --><template>
<div>
<counter style="margin-right: 5px;"/>
<counter />
</div>
</template>
<script>
import Counter from './Counter';
export defaults {
components: { Counter }
}
</script>
Copy the code
- Can be reused, different instances of the same component do not affect each other
- Enhanced semantics:
<div id="counter">
VS<counter >
Multi-component development fundamentals
- One file per component, with suffix
.vue
At the end, usually putsrc\components
directory - The component file name is usually the name of the component, using the camel name convention, such as
Counter.vue
.ItemCounter.vue
Parent component, child component
- Suppose there are two components A and B in
B
ComponentA
Component, two file contents - Component B is called the parent of component A
- The parent component needs to import child component modules:
import AComponent from './A'
- The parent component needs to be declared
components
Properties,components: { AComponent, CComponent }
- The parent component needs to import child component modules:
- Component A is called A child of component B
<! -- A.vue --><template>
<h1>Component A</h1>
</template><! -- B.vue --><template>
<div>
<a-component v-for="i in [1, 2]" :key="i" />
</div>
</template>
<script>
import AComponent from './A'
export default {
components: { AComponent }
}
</script>
Copy the code
The parent component passes properties to the child component
- The child component evaluates and renders differently depending on the value passed in
- In most scenarios, attributes need to be passed to child components for reuse purposes
- Child components:
- use
props
Array receives properties passed by the parent component prop
Properties anddata
The properties generated by the method are identical in usage- A template has the same syntax as an instruction, for example
v-for="item in items"
.{{ name }}
等 - in
<script>
Use to addthis
, such asthis.items
- A template has the same syntax as an instruction, for example
- use
- The parent component:
- Property values to be passed to child components, such as
:items="user.items"
.:name="user.name"
- Property values to be passed to child components, such as
<! -- Child component: child.vue --><template>
<div>
<h3>There are {{count}} items in {{name}}</h3>
<ul>
<li v-for="item in items" :key="item.id"> {{ item.text }} </li>
</ul>
</div>
</template>
<script>
export default {
props: ['name'.'items'].computed: {
count() {
return this.items.length
}
}
}
</script><! -- Parent component: parent.vue --><template>
<div>
<child :items="user.items" :name="user.name" />
</div>
</template>
<script>
import Child from './Child'
export default {
components: { Child },
data() {
return {
user: {
name: 'zhangsan'.items: [{id: 1.text: 'Study hard'},
{id: 2.text: "Up every day"}]}}}}</script>
Copy the code
Routing: the Vue – the Router
- Before routing: Compose applications by combining components
- The page address is always index.html and the specific path associated with the content cannot be displayed
<template>
<div>
<div id="navbar">
<button @click="select('about')">About me</button>
<button @click="select('learn')">Travel diary</button>
</div>
<div>
<about v-if="selected === 'about'" />
<travel v-if="selected === 'travel'" />
</div>
</div>
</template>
<script>
export default {
data() { return { selected: 'about' }},
methods: {
select(value) { this.selected === value; }}}</script>
Copy the code
- Once you have components: map components to routes, and then tell the Vue Router where to render them
- Install vue-Router library in project root directory
yarn add vue-router
ornpm install --Save vue-router
- Install vue-Router library in project root directory
<template>
<div>
<div id="navbar">
<! -- Use router-link to navigate -->
<! -- Use the to attribute to specify the link to be removed -->
<router-link to="/about">About me</router-link>
<router-link to="/travel">Travel diary</router-link>
</div>
<div>
<! -- Route exit -->
<! -- Routing matching components will be rendered here -->
<router-view></router-view>
</div>
</div>
</template>
<script>
import About from './components/about'
import Travel from './components/travel'
import VueRouter from './vue-router'
const routes = [
{ path: '/about'.component: About },
{ path: '/travel'.component: Travel }
]
const router = new VueRouter({ routes })
</script>
Copy the code
HTML 5 History pattern
-
Vue-router uses hash mode by default. It uses the HASH of URL to simulate a complete URL
- Hash: indicates a position in the web page
<div id="print">... </div>
<a href="#print">
- When an anchor point is clicked, no request is sent to the server
- When the URL changes, the page does not reload
- Hash: indicates a position in the web page
-
You can use history mode instead of hash mode
const router = new VueRouter({ mode: 'history'.routes: [...]. })Copy the code
- Urls in history mode are more like normal urls
Status management: Vuex
- Vuex is a state management mode developed specifically for vue.js applications
- Centralized storage is used to manage the state of all application components
Status management mode
-
Let’s start with a simple counting application
<! -- view --> <template> <div>{{ count }}</div> </template> <script> export default { // state data() { return { count: 0}; }, // actions methods: { inc() { this.count++; } } } </script>Copy the code
-
Vue applications generally include
- State: data that drives the application
- View: map state to the view declaratively
- Actions: Changes in state in response to user input on the view
-
For simple applications (single component applications and simple multi-component applications), data flow is easy to manage
- However, when the application encountersMultiple components share the same state 时
- Multiple views depend on the same state
- Parameters are passed through multiple layers to reach the underlying component
- There is nothing you can do about the state between sibling components
- Actions from different views need to change the same state
- Events can be used to change and synchronize state, but maintenance is poor
- Multiple views depend on the same state
- So, think about itState shared by different components is extracted and managed as a global singleton
- The component tree is a huge view
- Any node in the component tree can read the state and trigger the behavior
- Applicable situations
- Large single-page applications
- For simple applications, consider the Store model
Store model
- Put all shared states in the state object
- All shared state operations are placed in the Store object
var store = {
debug: true.state: {
message: 'Hello! '
},
setMessageAction (newValue) {
if (this.debug) console.log('setMessageAction triggered with', newValue)
this.state.message = newValue
},
clearMessageAction () {
if (this.debug) console.log('clearMessageAction triggered')
this.state.message = ' '}}Copy the code
- Components can use shared state or have their own private state
- Components cannot directly modify the state of the share. Instead, they execute actions to notify the store of the change
Vuex core concept: State
-
Single state tree: Each application contains only one store instance
- Remain responsive: The DOM of all components is updated as soon as the state in the Store changes
-
Get the Vuex state in the Vue component
-
Using computed properties
- Problem: Each component is directly dependent on global state
const Counter = { template: `<div>{{ count}}</div>`, computed: { count() { return store.state.count; }}}Copy the code
-
Inject state into child components from the root component
- Register the store from the root component:
const app = new Vue({ store })
- Child component through
this.$store
For a visit - Problem: When a component requires more than one state, these computed properties can be repetitive and redundant
const Counter = { template: `<div>{{ count}}</div>`, computed: { count() { return this.$store.state.count; }}}Copy the code
- Register the store from the root component:
-
Use the mapState function
import { mapState } from 'vuex' const Counter = { template: `<div>{{ count}}</div>`.computed: mapState({ count: state= > state.count }) } Copy the code
- If the name of the evaluated property is the same as the name of the state property
const Counter = { template: `<div>{{ count}}</div>`.computed: mapState([ // Map this.count to store.state.count 'count'])}Copy the code
- The mapState function returns an object, so how can it be mixed with local computed properties
- Use extension operators
const Counter = { template: `<div>{{ count}}</div>`.computed: { ...mapState([ // Map this.count to store.state.count 'count' ]), localComputed(){... }}}Copy the code
-
Vuex core concept: Getter
-
Derive some state from the store state
computed: { doneTodosCount() { return this.$store.state.todos.filter(todo= >todo.done).length; }}Copy the code