The article is transferred from Youdao Cloud Notes to the csdn blog. If there is a problem or error in the picture loss, you can read the original text and the message, thank you!
Article Directory
I learned vue for a while and made a simple project. I used vue after more than half a year. I have forgotten about it. I have always left a trace of what I learned, and it is also convenient for later turning over. Take a look at the review.
Compared with traditional JS development, vue has the biggest difference in personal experience, which is also an advantage.
- The data can be bound in one-way or two-way response, which can avoid the frequent manipulation of DOM by traditional JS;
- Can be componentized to improve the reusability of UI;
- View, data, and structure can be well separated, which is closer to the idea of MVVM;
- Because it is a single page, the loading speed will be faster and smoother than traditional html pages, and the experience will be better.
Vue project structure
vue single file structure
<!--template节点 一级节点-->
<template>
<div id="container">
<!--html内容结构区,所有的内容都写这个div容器内,而且只能一个根节点容器-->
<img alt="Vue logo" src="./assets/logo.png">
<!--使用子组件 ,当前vue可以称为父组件-->
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div>
</template>
<script>
/*通过ES6模块化语句import导入vue组件,又称为子组件 */
import HelloWorld from './components/HelloWorld.vue'
/*export用于声明可以导出vue组件,会在main.js导入使用 ES6模块化语句*/
export default {
name: 'vue',
/*声明注册组件,HelloWorld是组件名称,可以在html结构中使用*/
components: {
HelloWorld
},
created: () => {
console.log("App.vue")
},
mounted: () => {
}
}
</script>
<style>
<!--样式编辑区-->
</style>
Since there is the name of the parent-child component, of course, the data interaction between the two is indispensable, which will be introduced later.
Project structure
├── README.md 项目介绍
├── index.html 入口页面
├── build 构建脚本目录
│ ├── build-server.js 运行本地构建服务器,可以访问构建后的页面
│ ├── build.js 生产环境构建脚本
│ ├── dev-client.js 开发服务器热重载脚本,主要用来实现开发阶段的页面自动刷新
│ ├── dev-server.js 运行本地开发服务器
│ ├── utils.js 构建相关工具方法
│ ├── webpack.base.conf.js wabpack基础配置
│ ├── webpack.dev.conf.js wabpack开发环境配置
│ └── webpack.prod.conf.js wabpack生产环境配置
├── config 项目配置
│ ├── dev.env.js 开发环境变量
│ ├── index.js 项目配置文件
│ ├── prod.env.js 生产环境变量
│ └── test.env.js 测试环境变量
├── mock mock数据目录
│ └── hello.js
├── package.json npm包配置文件,里面定义了项目的npm脚本,依赖包等信息
├── src 源码目录
│ ├── main.js 入口js文件
│ ├── app.vue 根组件
│ ├── components 公共组件目录(高复用业务组件、纯样式组件)
│ │ └── title.vue
│ ├── assets 资源目录,这里的资源会被wabpack构建
│ │ └── images
│ │ └── logo.png
│ ├── routes 前端路由
│ │ └── index.js
│ ├── store 应用级数据(state)
│ │ └── index.js
│ └── views 页面目录
│ ├── hello.vue
│ └── notfound.vue
├── static 纯静态资源,不会被wabpack构建。
└── test 测试文件目录(unit&e2e)
└── unit 单元测试
├── index.js 入口脚本
├── karma.conf.js karma配置文件
└── specs 单测case目录
└── Hello.spec.js
- Basic library: vue.js, vue-router, vuex, whatwg-fetch
- Compilation/packaging tools: webpack, babel, node-sass
- Unit testing tools: karma, mocha, sinon-chai
- Local server: express
The relationship between index.html, main.js and App.vue, here is the simplest way to test the relationship between the three, through the log observation method can know the approximate relationship:
index.html
<script type="text/javascript">
console.log("index.html")
</script>
main.js
import Vue from 'vue'
import App from './App'
import router from './router'
Vue.config.productionTip = false
console.log('main.js')
//#app 这个ID是index.html中div的
new Vue({
el: '#app',
//注册路由,让整个应用拥有路由功能
router,
//在声明注册App.vue组件
components: { App },
template: '<App/>'
})
View app
//vue生命周期created函数
created: () => {
console.log("App.vue")
}
The final log print:
- index.html: is the entrance to the entire project.
- main.js: It is a logical entrance, which is equivalent to a bridge, which is the link between index.html and App.vue.
- App.vue: The first component, the component entry.
https://www.cnblogs.com/Renyi-Fan/p/12484173.html
Template syntax
Interpolation
text
//这个msgText需要在data属性中定义
//在其他地方改变了msgText的值时,span标签也会跟着改变,这就是响应式
<span>{
{msgText}}</span>
data() {
return {
msgText: "今天的天气很好",
}
}
instruction
Instructions generally divided into two types, one is carrying vue with v-
the beginning, such as v-bind
, v-on
, v-html
etc., another is a custom instruction, defined in the subassembly props
related properties, custom commands and v-bind
instructions are referred to as Binding instructions
The role of the instruction: when the value of the expression changes, the collateral effects produced by it will act on the DOM responsively.
v-bind
The v-bind command is often used to update HTML attributes responsively, such as HTML attributes such as src, href, border, etc. The :
following is the name of the attribute that needs to be bound.
//注意img标签,通过v-bind来动态改变值,其中url不能是在`assets`中
<img v-bind:src="url">
<a v-bind:href="url">
In addition, the v-bind command can be abbreviated, omit the v-bind before the colon and write it directly as:
<img :src="url">
<a :href="url">
Custom binding instructions
Custom instructions are often used to transfer data from parent components to child components, and the name of the instruction must be declared in the props definition of the child component . For example, HelloWorld.vue child component is used in App.vue parent component:
HelloWorld subcomponent
<template>
<div class="hello">
<h1>{
{ title }}</h1>
<img v-bind:src="imgUrl" />
</div>
</template>
<script>
export default {
name: 'HelloWorld',
//在props声明属性名称
props: {
title: String,
imgUrl:String,
}
}
</script>
App.vue parent component
<template>
<div>
<!--3、使用组件 通过:引用子组件定义的属性名称 即指令-->
<HelloWorld :title="title" :imgUrl="url" />
</div>
</template>
<script>
//1、导入子组件,并设置注册组件的名称HelloWorld
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'app',
components: {
//2、注册导入的组件
HelloWorld
},
data() {
return {
title: "今天的天气很好",
url: "https://private.yinshua86.com/upload_tmp/56219-pexels-valeriia-miller-3685530.jpg?imageView2/2/w/260&attname=pexels-valeriia-miller-3685530.jpg"
}
}
}
</script>
If you use the data attribute variables, you must need to bring :
to bind referenced props instruction sub-assemblies, picture data attribute URL can not be a local static links, you must be a link, or will fail; if it is binding text attributes, You can :
remove it and initialize the static value directly, such astitle="今天天气真好"
v-on
V-on instructions are generally used for DOM monitoring, such as click, copy, change events, etc.
<!-- 完整语法 -->
<button v-on:click="doSomething">点击</button>
<!-- 缩写 -->
<button @click="doSomething">点击</button>
Then methods
define the declaration doSomething
method in the attribute
methods:{
doSomething(){
console.log('点击了')
}
}
data attribute
The data attribute must directly return a function that has declared the initial object, and this object cannot use external objects indirectly.
//正确用法,使用函数返回对象
data() {
return {
title: 'Hello'
}
}
//错误写法,会导致再次打开页面时,显示上次数据
data: {
title: 'Hello'
}
//错误写法,同样会导致多个组件实例对象数据相互影响
const obj = {
title: 'Hello'
}
data() {
return {
obj
}
}
Conditional rendering
Basically, if (…) else (…) conditional judgment statements are used in development, they are also supported in vue. There are two conditional instructions
- v-if和v-else if、v-else
- v-show
v-if和v-else if、v-else
<template>
<div>
<div v-if="score >= 80">成绩很优秀 {
{score}}</div>
<div v-else-if="score < 80 && score >= 60">成绩良好 {
{score}}</div>
<div v-else>成绩很差 {
{score}}</div>
<button v-on:click="doSomething"> 点击</button>
</div>
</template>
<script>
export default {
name: 'app',
data() {
return {
score:100,
}
},
methods:{
doSomething(){
console.log('点击了')
//取0 - 100随机整数
this.score=Math.ceil(Math.random()*100)
}
}
}
</script>
DOM elements using v-if instruction must be continuous, if they are divided and run, they will fail. There is also often increased by v-if instruction determines whether to display the hidden element DOM, v-if the conditions provided value true
will render the display, as false
will be hidden when the DOM element destruction.
//当score > 60时就会渲染显示,其他值都会销毁
<div v-if="score > 60">
<HelloWorld :title="title" :imgUrl="url" />
</div>
v-if can be set to the
template
root node element.
During the v-if switching process, the event listeners and sub-component elements in the conditional block will be destroyed and rebuilt. Each rebuild will be rendered once. Frequent switching will bring performance overhead.
v-show
v-show is an instruction to determine whether to display elements based on conditions, there is no else instruction
<div>
<div v-show="score >= 80">成绩很优秀 {
{score}}</div>
<div v-show="score < 80 && score >= 60">成绩良好 {
{score}}</div>
<HelloWorld :title="title" />
<div v-show="score > 60">
<HelloWorld :imgUrl="url" />
</div>
<div v-show="score < 60">成绩很差 {
{score}}</div>
<button v-on:click="doSomething"> 点击</button>
</div>
It can be seen from the example that the v-show instruction can be discontinuous in the DOM element, which is different from the use of v-if.
Regardless of the initial conditions of v-show, the element will only be initially rendered once, and it is simply switched based on CSS to control the display and hiding of the element.
The difference between v-if and v-show
- v-if has a higher switching overhead. If the conditions rarely change during runtime, it is better to use v-if.
- v-show has a higher initial rendering overhead. If you need to switch very frequently, v-show is better
List rendering
The list rendering is based on the v-for instruction, and the basic usage is as follows:
<template>
<div id="app">
<div v-for="(item,index) in lists" :key="index">
<p>{
{index}} - {
{item}}</p>
</div>
<div> ------------------------------------------------</div>
<div v-for="(item,index) in listsObj" :key="index">
<p>{
{index}} - {
{item.name}} - {
{item.age}} - {
{item.sex}}</p>
</div>
</div>
</template>
<script type="text/ecmascript-6">
export default {
name: 'App',
data(){
return{
lists:['张三','李四','王老五','王麻子'],
listsObj: [{
id: 0,
name: '张三',
age: 28,
sex: '男'
}, {
id: 1,
name: '李四',
age: 20,
sex: '男'
}]
}
},
created () {
console.log('App.vue')
}
}
</script>
The data rendered by the above list comes from an array, and the array rendering list is generally in (item,index) in lists
the way of.
- item: is the alias of the array element, you can name it arbitrarily, there is no special requirement
- index: the subscript of the array, optional
- lists: data sources, usually initialized declarations in the data attribute function
- key: The function of the key is to ensure that the positions of the array elements and the html elements are consistent, to ensure accurate and timely refresh when the data changes; the key is unique, if it is an array, use index, if the traversal is an object, it needs to be in each object element Add a unique id attribute. It is recommended to add the key to the v-for command .
When using v-for on the component, the key is necessary
operation result:
Iterate over objects
<div v-for="(name,value,index) in person" :key="index">
<p>{
{index}} - {
{name}} - {
{value}}</p>
</div>
data() {
return {
person: {
id: 0,
name: '张三',
age: 28,
sex: '男'
}
}
},
Traversing objects is generally a (name,value,index) in person
way, the parameters are as follows:
- name: the attribute name of the object, such as age, sex, etc.
- value: the attribute value corresponding to the attribute name
- index: the subscript corresponding to the attribute name
- person: object name
- key: Same as above
operation result:
v-model
The instructions described above are all one-way data binding, which can only be triggered in the js code to change the value of the data attribute object to refresh the html.
The v-model instruction is often used to implement two-way data binding on form input, textarea and select elements. The so-called two-way data binding means that the value changed in the html element interaction will be synchronized to the data attribute object in js, and the value that is triggered by js will also be refreshed on the html. This is two-way data binding.
<input placeholder="输入名字" v-model="user_name">
<button @click="randomGeneration">随机名字 - {
{user_name}}</button>
data() {
return {
user_name:'',
lists: ['张三', '李四', '王老五', '王麻子'],
},
methods:{
randomGeneration(){
let randomPos=Math.floor(Math.random()*this.lists.length)
this.user_name=this.lists[randomPos]
}
}
Slot
concept
In layman's terms, the slot is to add the content of the parent component to the child component. There is a set of rules and standards in the process of adding. Solve the following questions to correctly add the content of the parent component to the child component:
- Where should the content be inserted in the subcomponent – where the content is stored
- Where is the content written in the parent component is reasonable-the source of the content
- How the parent component and the child component interact with data
Where does the content need to be inserted in the subcomponent?
The slot instruction defines the storage location of the declared content in the subcomponent . as follows:
Child component Child.vue
<template>
<div>
<slot>父组件内容存放的位置</slot>
</div>
</template>
Where is it reasonable to write the content in the parent component?
Parent component App.vue
<template>
<div>
<Child><template>插槽测试内容编写区</template></Child>
</div>
</template>
<script type="text/ecmascript-6">
import Child from './components/Child.vue'
export default {
name: 'App',
components:{
Child,
},
}
<script>
Note: In the parent component to write the sub-component slot content area, you need to wrap it with the template element
After running, the content in the parent component will be 插槽测试内容编写区
replaced with the 父组件内容存放的位置
text in the child component . Final display
Named slot
The above example is the child component only has a single slot, if there are multiple slots, how the parent component is distinguished; in fact, this is very simple, is to set a name attribute for each slot in the child component to distinguish, the name attribute name is unique of. as follows
Child component Child.vue
<div>
<slot name="one"></slot>
<slot name="two"></slot>
</div>
Parent component App.vue
<Child ><template v-slot:one>内容来源1</template></Child>
<Child ><template v-slot:two>内容来源2</template></Child>
The template element in the parent component is v-slot
used to bind the slot attribute name of the child component, which can also be abbreviated as follows
<Child ><template slot="one">内容来源1</template></Child>
<Child ><template slot="two">内容来源2</template></Child>
It can be simply considered that the slot declared through the name attribute definition is called a named slot
Data interaction between parent and child components under the slot
The two major issues of the source and storage location of the slot content have been solved before, and only the last step is the data interaction.
The compilation scope of the parent component is not connected to the child component. Simply put, the parent component cannot access the data attribute content of the child component.
Under normal circumstances, when the parent component passes data to the child component, the declaration props
content will be defined in the child component . Similarly, we can define a pros instruction in the slot element of the child component to bind the data attribute content of the child component. as follows
Child component Child.vue
<template>
<div>
<div>
<!--persons是插槽的prop属性-->
<slot name="one" v-bind:persons="person"></slot>
<!--age是插槽的prop属性-->
<slot name="two" v-bind:age="maxAge"></slot>
</div>
</div>
</template>
<script>
export default {
name: "child",
data() {
return {
person:{
name:"张三"
},
maxAge:27
}
}
}
</script>
Note: The name attribute is equivalent to setting a unique attribute for each slot
Parent component App.vue
<Child >
<template v-slot:one="user">
<div>
内容来源1 访问子组件数据 persons {
{user.persons.name}}
</div>
</template>
</Child>
<Child >
<template v-slot:two="user">
内容来源2 访问子组件数据 age {
{user.age}}
</template>
</Child>
v-slot:one
Add an alias after the slot name attribute (this alias can be named arbitrarily), and then use the alias to call the prop attribute of the slot , so that you can access the data of the subcomponent.
- The name attribute name of the sub-component slot, compared to a custom binding instruction in the sub-component
- The name alias of the sub-component slot, which can be named arbitrarily
- The name of the prop attribute of the sub-component slot defines a public method relative to the sub-component slot, which can be called by the outside world.
operation result:
routing
The role of routing is the process of implementing a single Web page into a multi-view page
The official recommendation is to use the vue-router library , first package.json
rely on the routing plugin in the project :
"dependencies": {
"vue-router": "^3.0.1"
},
Route naming
In the Router example, set the name name for the route in the routes configuration. This name is the unique identifier of the route redirection, and which component can be redirected according to the name.
- path: The relative path of the route, if there
/
is only the root route, the corresponding component will be automatically rendered intorouter-view
the element - name: The name of the route, which can be redirected by name
- component: component name, first import the component and then declare
path routing path, after the colon
:
is used for routing jump transfer parameters
<!--路由跳转触发,router-link 最终会渲染成a标签-->
<router-link :to="{name:'user'}">前往用户中心</router-link>
<!--路由组件容器,目标组件所存放的位置,
如果在应用第一个组件(App.vue)声明了router-view,则会自动加载根路由组件显示;
其他情况都是用于渲染存放路由跳转的目标组件
-->
<router-view ></router-view>
Route jump
There are two ways to trigger a route jump, namely:
- Used in html
router-link
to render as a tag - Jump in the way of programming code in js, such as push and other apis.
router-link route jump
Router-link finally renders it to the a tag, and then router-link
wraps the trigger element with the tag, as follows:
<router-link :to="{name:'user'}">前往用户中心</router-link>
:to
Is a binding instruction for routing jumpname
Is the route name defined when naming
The above is a no-parameter routing jump, and the routing component passes parameters as follows:
<router-link :to="{name:'user',params:{userId:123}}">前往用户中心</router-link>
By params
declaring an object, it is used to initialize the parameters that need to be passed, such as userId
the attribute, which corresponds to the name after the colon in the routing path path:
Click to jump to the final path:
If there are multiple parameters to be passed, use /
segmentation at the registered named route , as follows:
path:'/user/:userId/:userName',
Corresponding to router-link trigger point
<router-link :to="{name:'user',params:{userId:123,userName:'ABS'}}">前往用户中心</router-link>
Programmatic routing jump
The this.$router.push
routing jump can be realized in vue , as follows:
<div @click="routePush">前往用户中心</div>
routePush() {
this.$router.push({
name: 'user', params: {
'userId': 987,
"userName": 'AAS'
}
})
}
Route access
Receive parameters in the target routing component, mounted
call the hook function of vue this.$route.params.
to get the parameters
mounted() {
this.userId= this.$route.params.userId
this.userName= this.$route.params.userName
}
to sum up
To be continued:
- Network request
- State management
reference
- https://www.jianshu.com/p/57f51bcdf1d4
- https://zhuanlan.zhihu.com/p/114502325
- https://router.vuejs.org/zh/guide/
- https://cn.vuejs.org/v2/guide/