文章目录
只是一个普通的vue项目,html引入vue.js
一、
v-bind 指令
class样式此处省略
<div id="app">
<label for="r1">修改颜色</label>
<input type="checkbox" v-model="use" id="r1">
<br><br>
<div v-bind:class="{'class1': use}"> 通过绑定的use参数来让样式是否显示样式
</div>
</div>
new Vue({
el: '#app',
data:{
use: false
}
});
----------------------------------
v-bind是对标签的属性进行绑定的,使用v-bind时,可以进行简写,
如:
<a v-bind:href="url"></a>
<!-- 缩写 -->
<a :href="url"></a>
----------------------------------
<div id="app">
{{5+5}}<br>
{{ ok ? 'YES' : 'NO' }}<br> 判断是否为true, 字符串空为false,数字类型0为false
{{ message.split('').reverse().join('') }} 字符反转
<div v-bind:id="'list-' + id">菜鸟教程</div> 设置id名称为list-1 ,字符串和vm值得拼接
</div>
data: {
ok: "88",
message: 'RUNOOB',
id : 1
}
v-html 指令
<div id="app">
<div v-html="message"></div>
</div>
data: {
message: '<h1>菜鸟教程</h1>'
}
这样将标签都给引入了
v-model指令
也叫双向数据绑定
<div id="app">
<p>{{ message }}</p>
<input v-model="message">
</div>
new Vue({ el: '#app', data: { message: 'Runoob!' } })
用来在 input、select、textarea、checkbox、radio 等表单控件元素上
也就是说,表单输入的值与data里的属性值是双向更新的,谁变了,另外一个就跟着变
v-model 默认传的是 value,不是 checked。
v-on 指令
用于监听 DOM 事件
<p>{{ message }}</p>
<button v-on:click="reverseMessage">反转字符串</button> //点击事件
new Vue({
el: '#app',
data: { message: 'Runoob!'},
methods: {
reverseMessage: function () {
this.message = this.message.split('').reverse().join('')
}
}
})
//split('')会把数据拆分为一个字符串数组, join('') 是重组的意思
点击事件也可以简写
<a v-on:click="doSomething"></a>
<!-- 缩写 -->
<a @click="doSomething"></a>
过滤器
情况一
<div id="app"> {{ message | capitalize }} </div> 使用管道符分隔
new Vue({
el: '#app',
data: {
message: 'runoob'
},
filters: {
capitalize: function (value) { 将messaage传入
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1) 返回将字符大写
}
}
})
情况二
过滤器也可以串连起来
{{ message | filterA | filterB }} 两个过滤器
先经过filterA,然后再经过filterB
过滤器也可以传参数
{{ message,message2 | capitalize('aa') }} 此时是两个参数,再加上过滤器一个参数
那么过滤器上应该这么写:
filters: {
capitalize: function (value,value2,value3) {....} 三个参数
//按照顺序的,value1,value2是要过滤的值,value3是过滤器携带的
}
条件指令
v-if指令
<div id="app">
<p v-if="seen">现在你看到我了</p> 通过指令if来判断是否显示
<template v-if="ok">
<h1>菜鸟教程</h1>
<p>学的不仅是技术,更是梦想!</p>
<p>哈哈哈,打字辛苦啊!!!</p>
</template>
</div>
new Vue({
el: '#app',
data: {
seen: true,
ok: true
}
})
v-else 指令
条件分支
<div v-if="Math.random() > 0.5">
Sorry
</div>
<div v-else>
Not sorry
</div>
v-else-if指令
<div v-if="type === 'A'"> A </div>
<div v-else-if="type === 'B'"> B </div>
<div v-else-if="type === 'C'"> C </div>
<div v-else> Not A/B/C </div>
new Vue({ el: '#app', data: { type: 'C' } })
v-show指令
<h1 v-show="ok">Hello!</h1>
v-if 与 v-show 的区别
在切换 v-if 块时,Vue.js 有一个局部编译/卸载过程,因为 v-if 之中的模板也可能
包括数据绑定或子组件。
v-if是真实的条件渲染,因为它会确保条件块在切换当中合适地销毁与重建条件块内的
事件监听器和子组件。
v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——在条件第一次变为真时才开始
局部编译(编译会被缓存起来)。
v-show 简单得多——元素始终被编译并保留,只是简单地基于 CSS 切换。
v-if 有更高的切换消耗而 v-show 有更高的初始渲染消耗。
因此,如果需要频繁切换 v-show 较好,如果在运行时条件不大可能改变 v-if 较好
v-for指令
<ol> <li v-for="site in sites"> {{ site.name }} </li> </ol> 迭代的是数组
data: { sites: [ { name: 'Runoob' }, { name: 'Google' }, { name: 'Taobao' } ] }
---------------------------------------
通过一个对象的属性来迭代数据,取值
<ul> <li v-for="value in object"> {{ value }} </li> </ul> 注意,这是一个对象,
data: {
object: {
name: '菜鸟教程',
url: 'http://www.runoob.com',
slogan: '学的不仅是技术,更是梦想!'
}
}
注意,这里迭代出来的是数据里面属性的值,然而value不是固定的,可以是其他的名称
----------------------------------------
通过一个对象的属性来迭代数据,取值,取key
<div id="app"> <ul>
<li v-for="(value, key) in object"> {{ key }} : {{ value }} </li> </ul>
</div>
data: {
object: {
name: '菜鸟教程',
url: 'http://www.runoob.com',
slogan: '学的不仅是技术,更是梦想!'
}
}
注意:key和value也不是固定的名字随意取的,但是,注意他们的位置
针对于当对象遍历的时候,
接收的只有一个参数时,那么就是值;
两个参数的话,那么右边的是对象的属性名称,左边的是值;
当有三个参数时,最右边是索引下标,中间对象属性名称,左边是值。
该指令还有排序的作用
<div v-for="item in items" :key="item.id"> {{ item.text }}</div>
遍历该集合,然后取对象的id进行排序,默认是升序
计算属性(computed)
computed用来监控自己定义的变量,该变量不在data里面声明,直接在computed里面定义,
然后就可以在页面上进行双向数据绑定展示出结果或者用作其他处理.
computed比较适合对多个变量或者对象进行处理后返回一个结果值,也就是数多个变量中的某一个值发生了变化则我们监控的这个值也就会发生变化
例:
<div id="app"> <p>原始字符串: {{ message }}</p> <p>计算后反转字符串: {{ reversedMessage }}</p> </div>
var vm = new Vue({
el: '#app',
data: { message: 'Runoob!' },
computed: { // 计算属性的 getter
reversedMessage: function () { 声明了一个计算属性 reversedMessage 。 函数默认是getter,没有setter
提供的函数将用作属性 vm.reversedMessage 的 getter
vm.reversedMessage 依赖于 vm.message,在 vm.message 发生改变时,vm.reversedMessage 也会更新。
return this.message.split('').reverse().join('') // this 指向 vm 实例
}
}
})
---------------------------------------
computed默认是getter方法,但也可以手动设置setter方法
例:
computed: {
site: {
// getter
get: function () {
return this.name + ' ' + this.url //getter用做取值 取值时 {{site}}默认调用getter方法
},
// setter
set: function (newValue) { //用于设置值调用的函数
var names = newValue.split(' ')
this.name = names[0]
this.url = names[names.length - 1]
}
}
}
外部调用,进行赋值时,会调用对应的setter方法
vm.site = '菜鸟教程 http://www.runoob.com'; 设置值,会自动调用setter方法,没有写方法,则无效
methods
methods: {
one: function(){
alert("one");
},
two(){
alert("two") ;
}
}
定义两个方法one和two
computed vs methods(简单比较)
区别
我们可以使用 methods 来替代 computed,
效果上两个都是一样的,但是 computed 是基于它的依赖缓存,
只有相关依赖发生改变时才会重新取值。
而使用 methods ,在重新渲染的时候,函数总会重新调用执行.
注意,发生改变的要是在vue对象的数据发生改变,才会重新取值。在vue对象外的改变了,不会重新取值
computed默认是getter方法,但也可以手动设置setter方法
样式控制
<div v-bind:class="[errorClass ,isActive ? activeClass : '']"></div>
new Vue({
el: '#app',
data: {
isActive: true,
activeClass: 'active', //active样式
errorClass: 'text-danger' //text-danger样式
}
})
---------------------------------
内联样式
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }">菜鸟教程</div>
new Vue({
el: '#app',
data: {
activeColor: 'green',
fontSize: 30
}
})
--------------------------------
<div v-bind:style="styleObject">菜鸟教程</div>
data: {
styleObject: {
color: 'green',
fontSize: '30px'
}
}
---------------------------------
使用数组将多个样式作用在同一个对象上
<div v-bind:style="[baseStyles, overridingStyles]">菜鸟教程</div>
data: {
baseStyles: {
color: 'green',
fontSize: '30px'
},
overridingStyles: {
'font-weight': 'bold'
}
}
动态调节
<div v-bind:style="{color: 'red', fontSize: fontSize + 'px'}">可以动态调节</div>
<div v-bind:style="objectStyle"> 不可以动态调节</div>
{{fontSize}}
<button @click="++fontSize">+</button>
<button @click="--fontSize">-</button>
data: {
fontSize: 20,
objectStyle: {
color: 'green',
fontSize: this.fontSize + 'px'
}
}
正确的使用方法是使用 computed。(使用 methods 返回无效)
也就是说,当样式没有写在vue对象的data里面,而是通过内联的方式的话,此时是可以动态改变样式的,
但是如果写在了vue的data里面的话,需要使用computed来进行返回样式,进行动态的修改
如:
computed: {
computedStyle: function(){
return {color: 'red' , fontSize: this.fontSize + 'px'}
}
}
还有一种方式,使用监听的方式
watch: {
size: function(){
this.objectStyle.fontSize = this.fontSize + 'px'
}
}
事件修饰符
通过由点 . 表示的指令后缀来调用修饰符
.stop - 阻止冒泡
.prevent - 阻止默认事件,比如 submit 加了这个,就不会提交了。
.capture - 阻止捕获 ,在传递的父子事件种,加了这个,无论先点哪个,都先执行这个。
.self - 只监听触发该元素的事件
.once - 只触发一次
.left - 左键事件
.right - 右键事件
.middle - 中间滚轮事件
<!-- 阻止单击事件冒泡 --><a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重载页面 --><form v-on:submit.prevent="onSubmit"></form>
<!-- 修饰符可以串联 --><a v-on:click.stop.prevent="doThat"></a>
<!-- 只有修饰符 --><form v-on:submit.prevent></form>
<!-- 添加事件侦听器时使用事件捕获模式 --><div v-on:click.capture="doThis">...</div>
<!-- 只当事件在该元素本身(而不是子元素)触发时触发回调 --><div v-on:click.self="doThat">...</div>
<!-- click 事件只能点击一次,2.1.4版本新增 --><a v-on:click.once="doThis"></a>
按键修饰符
<!-- 只有在 keyCode 是 13 时调用 vm.submit() --><input v-on:keyup.13="submit">
<input v-on:keyup.enter="submit">
表单
<p>单个复选框:</p>
<input type="radio" id="google" value="Google" v-model="checked "> v-model要相同
<input type="radio" id="google" value="baidu" v-model="checked ">
<label for="checkbox">{{ checked }}</label>
data: {
checked : false,
checkedNames: []
}
<p>多个复选框:</p> v-model要相同
<input type="checkbox" id="runoob" value="Runoob" v-model="checkedNames">
<label for="runoob">Runoob</label>
<input type="checkbox" id="google" value="Google" v-model="checked"Names>
<label for="google">Google</label>
<p>select 列表:</p>
<select v-model="selected" name="fruit">
<option value="">选择一个网站</option>
<option value="www.runoob.com">Runoob</option>
<option value="www.google.com">Google</option>
</select>
data: {
selected: ''
}
<select v-model="selected" name="fruit">
<option v-for="(option,items) in optionsList" :value='option.value'>{{option.key}}</option>
</select>
data: {
optionsList:[{
key:'选择',
value:'Select'
},{
key:'淘宝',
value:'taobao'
},{
key:'京东',
value:'jingd'
}]
}
修饰符
.lazy
<!-- 在 "change" 而不是 "input" 事件中更新 --><input v-model.lazy="msg" >
自动将用户的输入值转为 Number 类型 (如果转换结果 NaN 则返回原值)<input v-model.number="age" type="number">
如果要自动过滤用户输入的首尾空格 <input v-model.trim="msg">
@change
<input type="checkbox" id="checkbox" v-model="checked" @change="changeAllChecked()">
内容被改变则触发事件
侦听器
<button @click = "counter++" style = "font-size:25px;">点我</button>
var vm = new Vue(
{
el: '#app',
data: { counter: 1 }
});
vm.$watch('counter', function(nval, oval) { nval新的值,oval旧的值
alert('计数器值的变化 :' + oval + ' 变为 ' + nval + '!');
});
-----------------
.......
var vm = new Vue({
el: '#computed_props',
data: {
kilometers : 0,
meters:0
},
methods: {},
computed :{},
watch : { 监听kilometers
kilometers:function(val) { // vm的kilometers属性改变时调用,该属性被监控了
this.kilometers = val;
this.meters = this.kilometers * 1000
}, 写两个参数的话,那么前面那个就是旧值,后面的是新值
}
});
组件
全局组件
Vue.component(tagName, options) 注册一个全局组件语法格式
tagName 为组件名,options 为配置选项
调用组件: <tagName></tagName>
例如:
<div id="app"> <runoob></runoob> </div>
var Child = {
template: '<h1>自定义组件!</h1>'
}
Vue.component('runoob', Child ) //注册
new Vue({ el: '#app' }) // 创建根实例
局部组件
<div id="app"> <runoob></runoob> </div>
var Child = {
template: '<h1>自定义组件!</h1>'
}
局部组件:
new Vue({ // 创建根实例
el: '#app',
components: { 可以注册多个局部组件
'runoob': Child // <runoob> 将只在父模板可用
}
})
区别就在于是否在vue实例里面进行组件注册的,
组件
const one={
template: '<div> <h2>111</h2> <p>内容1</p> </div>'
};
const two={
template: '<div> <h2>111</h2> <p>内容2</p><on></on> </div>',
components: {
on: one //引用组件一,也就是组件一注册在了组件二里面
}
}
const Vm=new Vue({
el: "#app",
components: {
tw: two
}
})
const 定义遍历的修饰符
模板与组件分离
<script type="text/x-template" id="cpn">
<div>
<h2>标题 </h2>
<p>内容</p>
</div>
</script>
Vue.component('tw',{ template: '#cpn' }); 这里是使用的一个对象来创建组件的
注意,根实例是必不可少的,这里省略
方法二:
<template id='two'>
<div>
<h2> 标题2 </h2>
<p>内容2</p>
</div>
</template>
Vue.component('two',{ template: '#two' }); 这种方式也可以 ,使用template
局部的写法:components: { one : { template: '#one' } }
这两种方式:一种是使用script标签,一个是使用template标签
Prop
父组件向子组件传值
<div> <input v-model="parentMsg"> <br>
<child v-bind:message="parentMsg"></child> </div>
// 注册
Vue.component('child', { // 声明 props
props: ['message'], // 也可以在 vm 实例中像 "this.message" 使用
template: '<span>{{ message }}</span>' })
// 创建根实例
new Vue({ el: '#app', data: { parentMsg: '父组件内容' } })
-----------------------------------
将数组放在自定义组件里遍历,props创建的属性todo与与数组遍历的单个对象绑定
<ol> <todo-item v-for="item in sites" v-bind:todo="item"></todo-item> </ol>
Vue.component('todo-item', { props: ['todo'], template: '<li>{{ todo.text }}</li>' })
new Vue({ el: '#app',
data: { sites: [ { text: 'Runoob' }, { text: 'Google' }, { text: 'Taobao' } ] } })
props: {
ff:{
type: String,
default: 'dddd'
},
gg:{
type: Object,
default: 'gggg'
}
}
子组件向父组件传值
<example1 v-on:incretment="incretmentTotal" value="点击"></example1>
var a=Vue.component('example1', {
props: ['value'],
template: '<button v-on:click="incrementHanlder">{{value}}</button>',
methods: {
incrementHanlder: function () {
this.$emit('incretment') //子组件通过 $emit 触发父组件的方法
// 当要传递参数时 :$emit("'incretment'",[arg1,arg2...])。
}
}
})
a组件通过设置一个点击事件,调用incrementHanlder方法,通过incretment属性,触发了父组件的incretmentTotal方法
var b=new Vue({
el: '#div_col',
data: {
total: 0
},
methods: {
incretmentTotal: function () {
this.total += 1
}
}
})
自定义指令
全局
<p>页面载入时,input 元素自动获取焦点:</p>
<input v-xx>
// 注册一个全局自定义指令 v-focus ,使用directive来注册
Vue.directive('xx', {
// 当绑定元素插入到 DOM 中。
inserted: function (el) {
// 聚焦元素
el.focus()
}
})
局部
使用 directives 选项来注册局部指令
new Vue({
el: '#app',
directives: {
// 注册一个局部的自定义指令 v-focus
focus: {
// 指令的定义
inserted: function (el) {
// 聚焦元素
el.focus()
}
}
}
})
Axios
GET
axios
.get('https://www.runoob.com/try/ajax/json_demo.json')
.then(response => (this.info = response))
.catch(function (error) { // 请求失败处理 console.log(error); });
get方式添加参数的话,可以直接拼接在请求路径上 get('/user?ID=12345')
或者使用
get('/user', { params: { ID: 12345 } }) 使用属性params
Post
axios .post('https://www.runoob.com/try/ajax/demo_axios_post.php').then(..)
axios.post('/user', { firstName: 'Fred', firstName lastName: 'Flintstone'}).then(..)...
all并发执行请求
function getUserAccount() { return axios.get('/user/12345'); }
function getUserPermissions() { return axios.get('/user/12345/permissions'); }
axios.all([getUserAccount(), getUserPermissions()])
.then(axios.spread(function (acct, perms) {
})
);
-------------
没有写请求方式,默认是get请求
axios.all([
axios({
url: 'https://www.runoob.com/try/ajax/json_demo.json'
}),
axios({
url: 'https://www.runoob.com/try/ajax/json_demo.json'
})]).then(data =>{
console.log(data);
})
请求方式(请求方法别名)
axios.request(config)
axios.get(url [,config])
axios.delete(url [,config])
axios.head(url [,config])
axios.post(url [,data [,config]])
axios.put(url [,data [,config]])
axios.patch(url [,data [,config]])
当使用这些指定了明确的请求方式的请求时,不需要指定url,method和data属性
不使用别名方式的请求
axios({
method: 'post',
url: '/user/12345',
data: {
firstName: 'Fred',
lastName: 'Flintstone'
}
});
axios的属性进行全局设置
我们的请求路径其实是可以拆分的,拆分为
baseURL: 'https://www.runoob.com/',
url: 'try/ajax/json_demo.json',
但这种写在一起的,属于局部的设置,没有意义,
--------------------
这是在vue实例外设置的
axios.defaults.baseURL='https://www.runoob.com/ ,在请求时,只要携带一小段不同的路径就可以了
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'; 配置请求头
axios.defaults.withCredentials=true;设置跨域,一般这个前端跨域是为了携带cookie,因为cookie在请求头里面
普通的携带cookie的话,前端是不需要进行这个设置的,
前端继续设置后,后端还进行设置
由于我使用的是springboot项目我使用的是拦截器
response.setHeader("Access-Control-Allow-Origin", "http://localhost:63342"); // 这里最好明确的写允许的域名
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
response.addHeader("Access-Control-Allow-Credentials","true"); 注意,一定要设置这个,否则报错
自定义配置创建axios的新实例
axios.create([config])
如: var instance = axios.create({
baseURL:'https://api.example.com'
});
这个例子,也只是将url的前缀设为默认值,后面我们需要使用的时候,就可以不需要写重复的url
使用:
test6: function(){
instance ({
url:'try/ajax/json_demo.json'
}).then(re =>{
console.log(re);
})
},
axios请求的响应
{
// `data` 由服务器提供的响应
data: {},
// `status` HTTP 状态码
status: 200,
// `statusText` 来自服务器响应的 HTTP 状态信息
statusText: "OK",
// `headers` 服务器响应的头
headers: {},
// `config` 是为请求提供的配置信息
config: {}}
拦截器
请求拦截:
axios.interceptors.request.use(function(config){
alert("发送前") ...处理逻辑
return config
},function(error){
alert("请求失败") ..处理逻辑
return Promise.reject(error)
});
axios在发出请求前,会先经过这个过滤器
响应拦截
axios.interceptors.response.use(function(config){
console.log(config) ...处理逻辑
alert("响应数据");
return config;
},function(error){
alert("响应数据失败"); ...处理逻辑
return Promise.reject(error);
});
请求错误
catch(function(error){
console.log(error.config)
console.log(error.response.status)
})
请求错误时,可以使用response来获取信息
请求正确时,直接通过回调函数的参数点属性获取响应信息
validateStatus 配置选项定义一个自定义 HTTP 状态码的错误范围
axios.get('https://www.runoob.com/try/ajax/json_demo.json',
{
validateStatus: function (status) {
return status < 100;
}
}).then(data >{
如果状态码满足范围,则会在这里进行回调处理,如果不在这个范围,这回报错,进入catch里面
}).catch(function(error){
返回的状态不在范围内,则会进入到这里
})
Vue.set
Vue.set 方法用于设置对象的属性,它可以解决 Vue 无法检测添加属性的限制
语法格式如下:
Vue.set( target, key, value )
target: 可以是对象或数组
key : 可以是字符串或数字
value: 可以是任何类型
不使用Vue.set时:
var test={name:"xiaoxiao",age: 18,sex: '女'}
var two=new Vue({
el: "#two",
data: {tests: test}
})
two.tests.address='赣州';
console.log(two)
这种方式给test对象添加属性,但是通过控制台的打印我们可以知道,是没有对应address的set和get方法的
换成
Vue.set(test,'address','南昌') ,上面是在tests上添加,这里是在test里面添加,就有get,set方法
Vue.delete
Vue.delete 用于删除动态添加的属性
语法格式: Vue.delete( target, key )
target: 可以是对象或数组
key : 可以是字符串或数字
在上面的示例情况下, Vue.delete(test,'sex') ,则可以动态的将test的sex属性删除,