vue-A tutorial written for yourself

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!


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

Insert picture description here

├── 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:

Insert picture description here

  • 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-htmletc., another is a custom instruction, defined in the subassembly propsrelated properties, custom commands and v-bindinstructions 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.

Insert picture description here

//注意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 methodsdefine the declaration doSomethingmethod 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 truewill render the display, as falsewill 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 templateroot 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 liststhe 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:

Insert picture description here

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 personway, 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:

Insert picture description here

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:

  1. Where should the content be inserted in the subcomponent – ​​where the content is stored
  2. Where is the content written in the parent component is reasonable-the source of the content
  3. 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

Insert picture description here

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-slotused 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 propscontent 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:oneAdd 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.

Insert picture description here

  1. The name attribute name of the sub-component slot, compared to a custom binding instruction in the sub-component
  2. The name alias of the sub-component slot, which can be named arbitrarily
  3. 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:

Insert picture description here

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.jsonrely 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.

Insert picture description here

  1. path: The relative path of the route, if there /is only the root route, the corresponding component will be automatically rendered into router-viewthe element
  2. name: The name of the route, which can be redirected by name
  3. 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-linkto 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-linkwraps the trigger element with the tag, as follows:

  <router-link :to="{name:'user'}">前往用户中心</router-link>
  • :to Is a binding instruction for routing jump
  • nameIs 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 paramsdeclaring an object, it is used to initialize the parameters that need to be passed, such as userIdthe attribute, which corresponds to the name after the colon in the routing path path:

Click to jump to the final path:

Insert picture description here

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.pushrouting 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, mountedcall 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/

Guess you like

Origin blog.csdn.net/hzw2017/article/details/115029283