欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Vue学习过程中的一些笔记

程序员文章站 2024-02-28 09:21:04
...

指令

  1. v-cloak: 解决插值表达式存在的“闪动”问题

  2. v-text: 填充纯文本,相比插值表达式更简洁,没有闪动问题

  3. v-html: 填充HTML片段,存在安全问题,本网站内部数据可以使用,需要使用第三方的数据时不要使用

  4. v-pre: 显示原始信息,跳过编译过程

  5. v-once: 显示的内容只编译一次,使用场景:如果显示的信息后续不需要再修改,可以使用v-once,这样可以提高性能

  6. v-model: 双向数据绑定

  7. v-on: 事件绑定

    如果事件绑定直接绑定函数名称,那么会默认传递事件对象作为事件函数的第一个参数;如果事件绑定函数调用,那么事件对象必须作为最后一个参数显式传递,并且事件对象的名称必须时$event

    事件修饰符:.stop阻止冒泡

    ​ .prevent阻止默认行为

    按键修饰符:keyup.enter回车键

    ​ keyup.delete删除键

    自定义按键修饰符:全局config.keyCodes对象 keyup.65 a键

    ​ Vue.config.keyCodes.aaa = 65------keyup.aaa

  8. v-bind:

    属性绑定 缩写 :

    样式绑定 :

    ​ class样式处理

    1. 对象绑定 :class="{active: isActive, error: isError}" //通过isActive的值来控制active样式是否有用

    2. 数组绑定 :class="[activeClass, errorClass]" //直接修改activeClass与errorClass对应的值来控制样式;eg: activeClass: ‘active’ this.activeClass = ‘’;//将值修改为空不显示样式

    3. 结合起来 .class="[activeClass, {error: isError}]"

      ​ .class=“arrClasses” arrClasses: [‘active’, ‘error’],//对数组进 行操作

      ​ .class=“objClasses” objClasses: {active: true, error: true}, this.objClasses.active = false;

    4. 默认的class会保留 <dive class="base" :class='objClasses'></div>

    ​ style样式处理

    1. 对象语法::style=’{border: borderStyle, width: widthStyle, height: heightStyle}’ borderStyle: ‘1px solid blue’,

      或者::style=‘objStyles’ objStyles: {border: ‘1px solid red’, width: ‘200px’} this.objStyles.width = ‘500px’

    2. 数组语法::style=’[objStyles, overideStyles]’

  9. 分支循环结构

    1. v-if v-else-if v-else

    2. v-show

    3. v-if与v-show区别

      v-if 控制元素是否渲染到页面;v-show 控制元素是否显示(已经渲染到了页面)

      v-if是控制DOM元素的,如果是需要频繁切换display就用v-show

    4. v-for遍历数组

      <li v-for='(item, index) in list' :key='index'>{{item + '---' + index}}</li>

      key的作用:帮助 Vue 区分不同的元素,从而提高性能 //:key=‘item.id’

    5. v-for遍历对象

      <div v-for="(value, key, index) in obj"></div>

    6. v-if和v-for结合使用

      <div v-if='value === 12' v-for='(v, k, i) in obj'></div>

vue常用特性

表单域修饰符

number:转换为数值 v-model.number=“age”

trim:去掉开始和结尾的空格

lazy:将input事件切换为change事件,v-model默认的是input事件,就是当表单内容发生改变的时候就触发,lazy是表单失去焦点之后才触发

自定义指令

全局指令

<input type="text" v-focus>
//自定义指令
Vue.directive('focus', {//focus:自定义的指令的名称
	inserted: function(el) {
		//el表示指令所绑定的元素
		el.focus();
	}
})

//带参数的自定义指令
Vue.directive('color', {
	inserted: function(el, binding) {
		el.style.background = binding.value.color;
	}
})

<input type="text" v-color='{color: "blue"}'>

局部指令

directives: {
	color: {
        inserted: function(el, binding) {
            el.style.background = binding.value.color;
        }
    }
}

计算属性

computed

模板中放入太多的逻辑会让模板过重且难以维护 使用计算属性可以让模板更加的简洁

computed比较适合对多个变量或者对象进行处理后返回一个结果值,也就是数多个变量中的某一个值发生了变化则我们监控的这个值也就会发生变化

计算属性与方法的区别:

  1. 计算属性是基于他的依赖的数据进行缓存的
  2. 方法不存在缓存

侦听器

数据变化时执行异步或者开销比较大的操作

watch

监听属性的变化

当需要监听一个对象的改变时,普通的watch方法无法监听到对象内部属性的改变,只有data中的数据才能够监听到变化,此时就需要deep属性对对象进行深度监听

案例:验证用户名是否可用

过滤器

格式化数据,比如将字符串格式化为首字母大写,将日期格式化为指定的格式等

// upper 为全局过滤器
Vue.filter('upper', function(val) {
	return val.charAt(0).toUpperCase() + val.slice(1);
});
Vue.filter('lower', function(val) {
	return val.charAt(0).toLowerCase() + val.slice(1);
});

<div>{{msg | upper}}</div>
//可以级联使用

//局部过滤器
filter: {
	upper: function(val) {
        return val.charAt(0).toUpperCase() + val.slice(1);
	}
}

带参数的过滤器

Vue.filter('format', function(value, arg){
	if(arg == 'yyyy-MM-dd'){
		var ret = '';
		ret += value.getFUllYear() + '-' + (value.getMonth() + 1) + '-' + value.getDate();
		return ret;
	}
})

<div>{{data | format('yyyy-MM-dd')}}</div>

声明周期

生命周期钩子函数

(-----------创建----------)

beforeCreate

created

beforeMount

mounted el被新创建的vm.$el替换,并挂载到实例上去之后调用该钩子。 数据已 经真实渲染到页面上,在这个钩子函数里面我们可以使用一些第三方的 插件

(----------更新---------)

beforeUpdate

updated

(------------销毁----------)

beforeDestory

destoryed

===============

mounted: function() {

​ //该生命周期钩子函数被触发的时候模板已经可以使用,一般此时可以用于获取后台数据,然后把数据填充到模板

}

综合案例

数组变更方法(修改原有数据)(响应式的)

push() pop() shift() unshift() splice() sort() reverse()

替换数组(生成新的数组,不会影响本来的数据)(不是响应式的)

filter() contcat() slice()

用索引号修改数组不是响应式的

修改响应式数据

Vue.set(vm.list, indexOfItem, newValue)

vm.$set(vm.list, indexOfItem, newValue)

(参数1表示要处理的数组名或者对象名,2表示要处理的索引号或者对象的属性,3表示要修改的值)

组件化开发

全局组件注册

Vue.component('button-counter', {
	data: function() {	//data必须是一个函数
		return {
			count: 0
		}
	}
	//组件模板内容必须是单个根元素,组件模板内容可以是模板字符串
	template: '<button von:click="handle"> 点击了{{count}}</button>
	methods: {
		handle: function(){this.count++}
	}
})
<div id="app">
	<button-counter></button-counter>
</div>

如果使用驼峰式命名组件,那么在使用组件的时候,只能在字符串模板中用驼峰的方式使用组件,但是在普通的标签模板中,必须使用短横线的方式使用组件,首字母要变小写

局部组件注册

<hello-world></hello-world>//局部组件只能在其父组件中使用

var HelloWorld = {
	data: function() {
		return {
			msg: 'HelloWorld'
		}
	},
	template: '<div>{{msg}}</div>'
}

components:{
	'hello-world': HelloWorld,
}

组件间数据交互

父组件向子组件传值

子组件内部通过props接受传递过来的值

Vue.component(‘menu-item', {
    props: ['title', 'content', 'menuTitle'],
    template: '<div>{{ title }}</div>'
})

父组件通过属性将值传递给子组件

<menu-item title=" 来自父组件的数据 "></menu item>
<menu-item :title="ptitle" :content="pcontent" :menu-title='ptitle'></menu item>

var vm = new Vue({
	el: '#app',
	data: {
		ptitle: '父组件的值',
		pcontent: '还是父组件的值'
	}
})

props属性名规则

  1. 在props中使用驼峰形式,模板中需要使用短横线的形式
  2. 字符串形式的模板中没有这个限制

props传递数据原则:单项数据流

子组件向父组件传值

子组件用$emit()触发事件

$emit()第一个参数为自定义的事件名称,第二个参数为需要传递的数据

父组件用v-on监听子组件的事件,通过$event接受子组件传递过来的数据

非父子组件间传值

单独的事件中心管理组件间的通信

  • 兄弟之间传递数据需要借助于事件中心,通过事件中心传递数据
    • 提供事件中心 var hub = new Vue()
  • 传递数据方,通过一个事件触发hub.$emit(方法名,传递的数据)
  • 接收数据方,通过mounted(){} 钩子中 触发hub.$on()方法名
  • 销毁事件 通过hub.$off()方法名销毁之后无法进行传递数据
var hub = new Vue();//事件中心
//兄弟组件A
methods: {
	handle: function() {
		hub.$emit('b-event', 1);//触发监听的对方的事件
	}
},
mounted: function() {
	hub.$on('a-event', (val) => {//这个val是兄弟组件b传递过来的
		
	})
}
//兄弟组件B
methods: {
	handle: function() {
		hub.$emit('a-event', 2);//触发监听的对方的事件
	}
},
mounted: function() {
	hub.$on('b-event', (val) => {//这个val是兄弟组件a传递过来的
		
	})
}
methods: {
	handle: function() {
		hub.$off('a-event');//销毁事件
		hub.$off('b-event');
	}
}

组件插槽

<alert-box>Hello</alert-box>//这个Hello会显示在slot中

Vue.component('alert-box', {
template: `
    <div class="demo-alert box">
        <strong>Error!</strong>
        <slot></slot>
    </div>
    `
})

具名插槽

//使用1
<base-layout>
	<p slot="header">header</p>
	<p slot="footer">footer</p>
	<p>main</p>
</base-layout>
//使用2
<base-layout>
	<template slot="header">
		<p>heade1r</p>
		<p>header2</p>
	</template>
</base-layout>

//插槽定义
Vue.component('base-layout', {
	template: `
    <div class="container">
        <header>
            <slot name="header"></slot>
        </header>
        <main>
            <slot></slot>
        </main>
        <footer>
            <slot name="footer"></slot>
        </footer>
    </div>
    `
})

作用域插槽

应用场景: 父组件要获取到子组件的数据,并且要对子组件的内容进行加工处理

<a-list :list= "list">//向子组件传值list
    <template slot-scope="slotProps">//slot-scope可以获取到子组件中绑定的属性
	    <strong v-if="slotProps.info.id==3" class="current">{{slotProps.info.text}}</strong>
	    <span v-else>{{slotProps.info.text}}</span>
    </template>
</a-list>

//插槽定义
props: ['list'],//接受父组件传来的list
`
<ul>
    <li v-for= "item in list" v bind:key= "item.id" >
        <slot :info="item">
       		{{item.name}}
        </slot>
    </li>
</ul>
`

Vue前后端交互

接口调用方式:

  1. 原生ajax
  2. 基于jQuery的ajax
  3. fetch
  4. axios

URL地址格式:

  1. 传统形式的URL:schema://host:port/path?query#fragment

    ​ schema:协议,例如http, https, ftp

    ​ host:域名或者ip地址

    ​ port:端口,http默认端口80可以省略

    ​ path:路径

    ​ query:查询参数,如果uname=list&age=1

    ​ fragment:锚点,用于定位欸页面的某个位置

  2. Restful形式的URL

    ​ 与请求方式密切相关(GET,POST,PUT,DELETE)

Promise用法

常见异步效果:定时任务、Ajax、事件函数

多次异步调用的依赖分析:多次异步调用的结果顺序不确定,异步调用结果如果存在依赖需要嵌套

使用Promise:

  1. 可以避免多层异步调用嵌套问题(回调地狱)
  2. Promise对象提供了简洁的API,使得控制异步操作更加容易

基于Promise发送Ajax请求

then参数中的函数返回值

  1. 返回Promise对象:返回的该实例对象会调用下一个then
  2. 返回普通值:返回的普通值会直接传递给下一个then,通过then参数中函数的参数接受该值

常用的API

实例方法

​ p.then() 得到异步任务的正确结果

​ p.catch() 获取异常信息

​ p.finally() 成功与否都会执行(目前不是正式标准)

对象方法

​ Promise.all() 并发处理多个异步任务,所有任务都执行完成才能得到结果

​ Promise.rece() 并发处理多个异步任务,只要有一个任务完成就能得到结果

Promise.all([p1,p2,p3]).then(function(result){
       //all 中的参数[p1,p2,p3]和返回的结果一 一对应["HELLO TOM", "HELLO						JERRY", "HELLO SPIKE"]
       console.log(result) //["HELLO TOM", "HELLO JERRY", "HELLO SPIKE"]
})
Promise.race([p1,p2,p3]).then(function(result){
      // 由于p1执行较快,Promise的then()将获得结果'P1'。p2,p3仍在继续执行,但执行结果将			被丢弃。
      console.log(result) // "HELLO TOM"
})

fetch

更加简单的数据获取方式,功能更强大、更灵活、可以看作是xhr的升级版

  • Fetch API是新的ajax解决方案 Fetch会返回Promise
  • fetch不是ajax的进一步封装,而是原生js,没有使用XMLHttpRequest对象。
  • fetch(‘url’, options).then()

参数传递

//get delete请求传参
fetch('http://localhost:3000/books?id=123' {//或者 /books/123
   //get请求可以省略不写 默认的是GET 
    method: 'get'//method: 'delete'
})
.then(function(data){
      // text()方法属于fetchAPI的一部分,它返回一个Promise实例对象,用于获取后台返回的数据
      return data.text();
      //return data.json();
}).then(function(data){
      //在这个then里面能拿到最终的数据  
      console.log(data);
      var obj = JSON.parse(data);
      console.log(obj.uname)
})
//post请求传参
fetch('http://localhost:3000/books', {
    method: 'post',
    body: JSON.stringify({
        uname: '张三',
        pwd: '456'
	}),
    headers: {
        'Content-Type': 'application/json'
    }
})
.then(function(data) {
	return data.text();
}).then(function(data) {
	console.log(data)
});
//put请求
fetch('http://localhost:3000/books/123', {
    method: 'put',
    body: JSON.stringify({
        uname: '张三',
        pwd: '789'
    }),
    headers: {
    	'Content-Type': 'application/json'
    }
})
.then(function(data) {
	return data.text();
}).then(function(data) {
	console.log(data)
});

axios

  • 基于promise用于浏览器和node.js的http客户端
  • 支持浏览器和node.js
  • 支持promise
  • 能拦截请求和响应
  • 自动转换JSON数据
  • 能转换请求和响应数据

四种参数传递的方式

axios全局配置

//配置公共的请求头 
axios.defaults.baseURL = 'https://api.example.com';
//配置 超时时间
axios.defaults.timeout = 2500;
//配置公共的请求头
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
//配置公共的 post 的 Content-Type
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';

axios拦截器

请求拦截器

响应拦截器

//请求拦截器 
axios.interceptors.request.use(function(config) {
	console.log(config.url)
	//1 任何请求都会经过这一步   在发送请求之前做些什么   
	config.headers.mytoken = 'nihao';
	//2  这里一定要return   否则配置不成功  
	return config;
    }, function(err){
       //3对请求错误做点什么    
      console.log(err)
    })
// 响应拦截器 
axios.interceptors.response.use(function(res) {
      //1在接收响应做些什么  
      var data = res.data;
      return data;
    }, function(err){
      //2对响应错误做点什么  
      console.log(err)
    })

async-await用法

  • async作为一个关键字放到函数前面
    • 任何一个async函数都会隐式返回一个promise
  • await关键字只能在使用async定义的函数中使用
    • ​ await后面可以直接跟一个 Promise实例对象
    • ​ await函数不能单独使用

路由

后端路由

概念:根据不同的用户 URL 请求,返回不同的内容

本质:URL 请求地址与服务器资源之间的对应关系

后端路由根据不同的URL地址分发不同的资源

  1. 后端渲染(存在性能问题)如果用户和服务器之间有经常的提交表单的这类数据交互行为,后端路由就会造成页面的频繁刷新,造成体验非常差,于是后面有了ajax前端渲染

  2. Ajax前端渲染(用于前端页面的局部刷新,很大程度上提高了用户体验,前端渲染提高性能,但是不支持浏览器的前进后退操作,也就是说浏览器没有办法保存用户的浏览状态,所以前端又出现了spa)

  3. SPA(Single Page Application)单页面应用程序:整个网站只有一个页面,内容的变化通过Ajax局部更新实现、同时支持浏览器地址栏的前进和后退操作

  4. SPA实现原理之一:基于URL地址的hash(hash的变化会导致浏览器记录访问历史的变化、但是hash的变化不会触发新的URL请求)

  5. 在实现SPA过程中,最核心的技术点就是前端路由

前端路由

概念:根据不同的用户事件,显示不同的页面内容

本质:用户事件与事件处理函数之间的对应关系

前端路由负责事件监听,触发事件后,通过事件函数渲染不同内容

Vue Router

  1. 支持HTML5 历史模式或 hash 模式
  2. 支持嵌套路由
  3. 支持路由参数
  4. 支持编程式路由
  5. 支持命名路由

使用:

  1. 引入相关的库文件
  2. 添加路由链接 router-link
  3. 添加路由填充位 <router-view></router-view>
  4. 定义路由组件
  5. 配置路由规则并创建路由实例
  6. 把路由挂载到 Vue 根实例中

路由重定向

路由重定向指的是:用户在访问地址 A 的时候,强制用户跳转到地址 C ,从而展示特定的组件页面; 通过路由规则的 redirect 属性,指定一个新的路由地址,可以很方便地设置路由的重定向

嵌套路由

动态路由匹配

{path: 'user/:id', component: User}		//:id动态路由参数

路由组件中通过$route.params获取路由参数		//$route.params.id

路由传参

$route与对应路由形成高度耦合,不够灵活,所以可以使用props将组件和路由解耦

//props的值为布尔类型
const router = new VueRouter({
routes: [
    // 如果 props 被设置为 true,route.params 将会被设置为组件属性
    { path: '/user/:id', component: User, props: true }
]
})
const User = {
    props: ['id'], // 使用 props 接收路由参数
    template: '<div>用户ID:{{ id }}</div>' // 使用路由参数
}
//props的值为对象类型
const router = new VueRouter({ 
    routes: [ 
        // 如果 props 是一个对象,它会被按原样设置为组件属性 
        { path: '/user/:id', 
        component: User, 
        props: { uname: 'lisi', age: 12 }
        }
	]
}) 
const User = { 
	props: ['uname', 'age'], 
	template: '<div>用户信息:{{ uname + '---' + age}}</div>' 
}
//props值为函数类型
const router = new VueRouter({
    routes: [
    // 如果 props 是一个函数,则这个函数接收 route 对象为自己的形参
    { path: '/user/:id',
    component: User,
    props: route => ({ uname: 'zs', age: 20, id: route.params.id })}
    ]
})
const User = {
    props: ['uname', 'age', 'id'],
    template:<div>用户信息:{{ uname + '---' + age + '---' + id}}</div>'
}

命名路由

为了更加方便的表示路由的路径,可以给路由规则起一个别名,即为“命名路由”。

<router-link :to="{ name: 'user', params: { id: 123 }}">User</router-link>

const router = new VueRouter({
    routes: [
        {
        path: '/user/:id',
        name: 'user',
        component: User
        }
    ]
})

页面导航的两种方式

声明式导航:通过点击链接实现导航的方式,叫做声明式导航 例如:普通网页中的 <a></a> 链接 或 vue 中的 <router-link></router-link>

编程式导航:通过调用JavaScript形式的API实现导航的方式,叫做编程式导航 例如:普通网页中的 location.href

编程式导航

常用的编程式导航 API 如下:
this.$router.push('hash地址')//通过push可以跳转到指定页面
this.$router.go(n)//前进后退

router.push()方法的参数规则

// 字符串(路径名称) 
router.push('/home') 
// 对象 
router.push({ path: '/home' }) 
// 命名的路由(传递参数) 
router.push({ name: '/user', params: { userId: 123 }}) 
// 带查询参数,变成 /register?uname=lisi 
router.push({ path: '/register', query: { uname: 'lisi' }})
相关标签: 个人笔记 vue

上一篇: maven的target和source版本

下一篇: