Vue
官网https://cn.vuejs.org/
使用{{}}
j进行数据绑定
<p>{{变量}}p>
使用v-ones
可以指定元素只改变一次
<p v-ones>{{变量}}p>
如果返回的数据是一个带有html
格式的字符串,需要按照格式显示则需要v-html="变量"
<p v-html="code">p>
如过想要将返回的值放在属性上则需要v-bind:属性="变量"
,其中v-bind
可以省略,直接写:
<img v-bind:scr="logo" alt="">
<img :src="logo" alt="">
b-bind
来绑定<p :class="{title:true,'main-title':false}">我爱你:世界p>
<p :class="{title:true,'main-title':false}">我爱你:XXXp>
<p :style="[pStyle,fontW]">我爱你:oooop>
<script>
new Vue({
el: '#app',
data: {
username: "张锐",
pclass1: "title",
pclass2: "main-title",
strong: false,
pStyle:{
'color': "red",
"fontSize":"30px"
},
fontW:{
"fontWeight":"800"
}
}
})
script>
js
的表达式和函数
v-
,如果需要判断的代码有很多则可以使用使用template
标签来包裹,默认情况会重用相同的代码,如果想要不使用重用则可以在标签上加入key
属性,实例代码如下<div id="app">
<p v-if="weather=='sun'">去公园p>
<p v-else-if="weather=='rain'">去看电影p>
<p v-else>呆在家p>
<tamplate v-if="age<18">
<p>数学考了多少分p>
tamplate>
<tamplate v-else-if="age>18&&age<25">
<p>有没有女朋友p>
tamplate>
<tamplate v-else>
<p>工资多少啊p>
tamplate>
<template v-if="loginType=='username'" key='username'>
<label>用户名label>
<input type="text" name="username" placeholder="用户名">
template>
<template v-else="loginType=='email'">
<label>邮箱label>
<input type="text" name="email" placeholder="email">
template>
<button @click="changeLoginType">更换登陆类型button>
div>
<script>
new Vue({
el: '#app',
data: {
weather: "sun",
age:25,
loginType: "username"
},
methods:{
say(){
return "早上好"
},
changeLoginType(){
this.loginType = this.loginType=='username'?"email":"username"
}
}
})
script>
v-if
和v-show
的区别
v-if
只有在第一次为真时才会渲染,调整的标签的渲染v-show
在加载的时候就会全部加载上,只是display
属性为none
而已,在修改时只是会调整这个属性v-if
有更高的切换开销,而v-show
有更好的渲染开销,因此如果一个元素需要频繁的切换则一般使用v-show
较好,如果在运行时条件很少改变则使用v-if
比较好v-for
语句,可以只取元素,也可以将元素和索引都取出来,第一个参数为列表中的每一个元素,第二个参数为索引,使用 in
或of
的方式遍历 。v-for
的语句,可以只取元素,也可以将元素和键都取出来,第一个参数为元素第二个参数为键,使用 in
或of
的方式遍历 。
key
,以Vue
默认使用代码重用引发意想不到的bugv-for
则key
是必须的<div id="app">
<table>
<thead>
<tr>
<th>序号th>
<th>标题th>
<th>作者th>
tr>
thead>
<tbody>
<tr v-for="(book,index) in books" :key="book.title">
<td>{{ index }}td>
<td>{{ book.title }}td>
<td>{{ book.author }}td>
tr>
tbody>
table>
<div>
<p v-for="(value,key) in user">{{key}}->{{value}}p>
div>
div>
<script>
new Vue({
el: '#app',
data: {
books:[
{
"title": "三国演义",
"author": "罗贯中"
},
{
"title": "西游记",
"author": "吴承恩"
},
{
"title": "水浒传",
"author": "施耐庵"
},
{
"title": "红楼梦",
"author": "曹雪芹"
},
],
user:{
"name":"zr",
"age":"19"
}
}
})
script>
直接赋值更新。this.heros=[]
,模板会立即更新
通过函数更新。this.heros.push("xxx")
push、pop、shift、unshift、splice、sort
这些函数会直接触发更新<div id="app">
<ul>
<li v-for="hero in heros" :key="hero">{{hero}}li>
ul>
<button @click="update">直接更新button>
<button @click="fun_show_update">函数显示更新button>
<button @click="fun_update">函数不显示更新button>
<button @click="fun_concat">拼接button>
div>
<script>
new Vue({
el: '#app',
data: {
heros:["蜘蛛侠","美国队长"]
},
methods:{
update(){
this.heros=["绿巨人"]
},
fun_show_update(){
// 追加一个
// this.heros.push("绿巨人")
// 删除最后一个
// this.heros.pop()
// 删除第一个
// this.heros.shift()
// this.heros.unshift("绿巨人")
// 删除两个
// this.heros.splice(0,2)
// 在第一个位置插入一个元素
// this.heros.splice(0,0,"绿巨人")
// 将从0开始的两个元素替换为绿巨人
// this.heros.splice(0,2,"绿巨人")
},
fun_update(){
this.heros.slice(0,1)
// 不能触发更新的还有 filter 、 concat 、 slice
// 可以采用直接赋值来取消这种结果
},
fun_concat(){
this.heros = this.heros.concat(["蝙蝠侠","超人"])
}
}
})
script>
1、如果直接修改数组中的某个值不会触发视图更新,着用情况需要使用splice
或者Vue.set
方法来实现。
Vue.set(this.books,0,"钢铁是怎么练成的")
2、如果同台给对象添加属性,也不会触发视图更新,只能通过Vue.set
来进行添加。
Vue.set(this.user,"age",18)
v-on
来绑定事件,可以直接使用变量或者函数。@
符号来完成。<div id="app">
<p v-for="book in books" :key="book" @click="fun_click(book)">{{ book }}p>
div>
<script>
new Vue({
el:'#app',
data: {
books: ["水浒传","三国演义","红楼梦","西游记"]
},
methods:{
fun_click(value){
alert(value)
}
}
})
script>
传入js
的事件event
,使用固定写法$event
<div id="app">
<a href="http:www.baidu.com" @click="fun($event)">点击不跳转a>
div>
<script>
new Vue({
el:app,
data: {
},
methods:{
fun(event){
event.preventDefault()
alert("不跳转")
}
}
})
script>
阻止标签的默认行为,prevent
<a href="http:www.baidu.com" @click.prevent="">点击不跳转a>
常见修饰符,用于事件后的修饰
.stop
:event.stopPropagation
阻止事件冒泡.capture
:事件捕获.once
:这个事件只执行一次.self
:代表当前这个被点击的元素自己.passive
:在页面滚动的时候告诉浏览器不会阻止默认行为,从而让滚动更流畅js
中的冒泡机制
冒泡机制就是在嵌套的元素中内部元素触发的事件会冒泡到外面元素,也就是说外面元素会监听到内部元素的事件。阻止这种冒泡的方法可以在需要阻断的位置加入.stop
修饰符。
js
中的事件捕获机制
捕获的方式就是会先执行捕获,可以使用.capture
来进行捕获
计算属性都写在computed
中
计算属性默认情况中只有get
,没有set
,如果想要实现set
,那么就必须实现get
,放到计算属性的名字中
扩展:取到输入框中的值可以使用v-model:value
或者简写v-model
<div id="app">
<div>
<label>宽:label>
<input type="text" v-model="width">
div>
<div>
<label>高:label>
<input type="text" v-model="height">
div>
<div>
面积:{{ area }}
div>
<div>
<label>省:label>
<input type="text" v-model:value="province">
div>
<div>
<label>市:label>
<input type="text" v-model:value="city">
div>
<div>
<label>区:label>
<input type="text" v-model:value="district">
div>
<div>
<label>详细地址:label>
<input type="text" v-model="address">
div>
div>
<script>
new Vue({
el:'#app',
data: {
width:0,
height:0,
province:"",
city:"",
district:""
},
computed:{
// 默认只有get
area(){
return this.width*this.height
},
address:{
// 取值的时候会调用这个方法
get(){
let result = ""
if(this.province){
result += this.province + "省"
}
if(this.city){
result += this.city + "市"
}
if(this.district){
result += this.district + "区"
}
return result
},
set(value){
// xx省xx市xx区
let result = value.split(/省|市|区/)
if(result && result.length > 0){
this.province = result[0]
}
if(result && result.length > 1){
this.city = result[1]
}
if(result && result.length > 2){
this.district = result[1]
}
}
}
}
})
script>
watch
中,默认会传递两个参数,一个新的值,一个是旧的值<div id="app">
<div>
<input type="text" v-model="kw">
div>
<div>
<span>推荐的关键字span>
{{result}}
div>
div>
<script>
new Vue({
el:'#app',
data: {
kw:"",
result:""
},
watch:{
kw(newValue,oldVaule){
// 模拟加载
this.result = "正在加载中...."
setTimeout(()=>{
this.result = "推荐结果:" + newValue
},1000)
}
}
})
script>
v-model
来绑定属性获取输入值checkbox
需要注意v-model
的值必须是同一个,然后返回值为一个数组,数组中存放的是每一个选择框的value
radio
同一组单选按钮的v-model
也必须绑定同一个值,返回的是选中的按钮的value
的值select
需要将v-model
绑定到select
标签上,如果option
中没有value
属性,默认会区其中显示的值,如果指定了value
属性,则选中的value
值.lazy
会在输入框输入完成后才更新.number
会将输入的值转换为数值类型,如果字符串不能被转换为数字则不会修改值,而且会清掉输入框中的字符串.trim
会将输入的字符串首尾的空白字符串清理掉注册方式使用Vue.component("组件名",{data,template})
。
data
: 必须为一个函数,这个函数返回一个对象,用法和Vue
中的data
用法相同template
:用来表示这个组件的渲染后的具体代码<div>
<button-count>button-count>
div>
<script>
Vue.component("button-count",{
// template 为渲染内容
template:"",
// data 为数据,必须是函数,然后返回一个对象
data: function () {
return {count: 0}
}
})
script>
注意: 组件模板中必须只包含同一个 根标签
props
来表示属性,props
可以采用数组的方式,或者是对象的方式,采用对象的方式可以提供一些限制。
type
类型、required
是否必须、default
默认值<div id="app">
<article-list :articles="articles">article-list>
div>
<script>
Vue.component("article-list",{
// props:["articles"],
props:{
articles:{
type:Array,
required:true
}
},
// ``符号用于可以换行的字符
template: `
序号
标题
{{index+1}}
{{article.title}}
`
})
new Vue({
el:'#app',
data: {
articles:[
{
title:"《三国演义》"
},
{
title:"《水浒传》"
},
{
title:"《红楼梦》"
},
]
},
})
script>
methods
中定义这个事件应该执行的函数this.$emit('xxx',传参)
来执行函数(外部传过来的函数 比如叫xxx),这里需要注意这个xxx不要使用驼峰命名法,可以使用-
。@XXX='外部定义的函数'
<div id="app">
<blog-item v-for="blog in blogs" :blog="blog" @check-change="outChange">blog-item>
<h1>选中的博客:h1>
<div v-for="blog in select_blogs">
{{blog.title}}
div>
div>
<script>
Vue.component("blog-item",{
props: ["blog"],
template: `
{{blog.title}}
`,
methods: {
onClick(){
this.$emit("check-change",this.blog)
}
}
})
new Vue({
el:app,
data: {
blogs:[
{
"title": "这是一个测试",
"id": 1
},
{
"title": "这也是一个测试",
"id": 2
}
],
select_blogs:[]
},
methods: {
outChange(blog){
// 判断元素在数组中的位置,如果值为非负数,则是下标
let index = this.select_blogs.indexOf(blog)
if(index>=0){
this.select_blogs.splice(index,1)
}else{
this.select_blogs.push(blog)
}
}
}
})
script>
model
event
表示什么情况下触发v-model
的行为prop
表示传给v-model
的变量绑定到模板中的哪个变量上this.$emit(model.event,计算结果)
就可以了,注意这里面只需要返回计算结果而不需要改变值,Vue
会自动改变这个值同时改变模板外面的值<div id="app">
<Stepper v-model="goods_count">Stepper>
<span>{{goods_count}}span>
div>
<script>
Vue.component("Stepper",{
props: ["count"],
model:{
// model 的事件
event: "xxx",
// 绑定的值
prop: "count"
},
template: `
{{ count }}
`,
methods:{
// 这里面不需要修改this.count的值,只要把结果传出去就可以
sub(){
this.$emit("xxx",this.count-1)
},
add(){
this.$emit("xxx",this.count+1)
}
}
})
new Vue({
el:"#app",
data: {
goods_count: 0
}
})
script>
来占位,以后在标签内写入的内容(包括标签)就会在
的位置进行替换<div id="app">
<navigation-link url="www.baidu.com">百度navigation-link>
div>
<script>
Vue.component("navigation-link",{
props: ["url"],
template: `
`
})
script>
默认值
中添加默认值,也就是在使用模板但模板标签中无任何值的时候显示
属性表示名字default
指定名字,来加载不同的数据<div id="app">
<main>
<template v-slot="header">
<p>这是头部p>
template>
<template v-slot="body">
<p>这是主体p>
template>
<template v-slot="footer">
<p>这是尾部p>
template>
main>
div>
<script>
Vue.component("mian",{
props: ["url"],
template: `
`
})
script>
v-bind:
传参的方式传入v-slot:header="headerProps"
讲插槽里面的值得到存入headerProps
里v-slot="props"
来简写<div id="app">
<container>
<template v-slot:header="headerProps">
<p>{{ headerProps.navs }}p>
template>
<template v-slot:body>
<p>这是主体p>
template>
<template v-slot:footer="footerProps">
<p>{{footerProps.address}}p>
<p>{{footerProps.aboutus}}p>
template>
container>
div>
<script>
Vue.component("container",{
template: `
`,
data: function () {
return {
address: "公司地址",
aboutus: "关于我们",
navs: ["首页","新闻","课程"]
}
}
})
new Vue({
el:"#app",
data: {
username: "张锐"
}
})
script>
beforeCreate
:Vue
已经创建了,但是data
和methods
还没有创建好creadted
:data
和methods
已经创建好了beforeMount
:模板经过编译,还没有挂在到网页中mounted
:模板经过编译,并且已经挂在到网页中,创建阶段的事情都做好了beforeUpdate
:数据data
已经更新了,但是模板还未更新updated
:在data
中更新了,在模板中也更新了beforeDestory
:Vue
执行实例或者组件销毁之前执行的函数,在这个函数中Vue
或者组件中的所有属性都是可以使用的。destoryed
:Vue
实例或者组件被销毁以后执行的。此时Vue
实例上所有东西都会解绑,所有事件都会被移除,所有元素都会被销毁。使用:{{username|strip}}
的方式可以为属性username
添加过滤器,也可以为这样的标签属性添加过滤器
定义:都是定义一个函数,这个函数的第一个参数永远都是被过滤的变量
filters
,然后在filters
中添加过滤器。Vue.filter("过滤器名",函数)
的方式定义传参:如果使用过滤器的时候还需要传递额外的参数,那么可以在定义过滤器的时候,提供其他参数,在使用的时候与普通函数相同。
<body>
<div id="app">
{{username|strip("-")}}
div>
<script>
Vue.filter("strip",function (value, str) {
// 将空格替换为 str
return value.replace(" ",str)
})
new Vue({
el:"#app",
data: {
username: "张 锐"
}
})
script>
创建一个VueRouter
对象:new VueRouter()
。
在VueRouter
中,需要传递一个routes
参数。这个参数是一个数组类型,数组中存储的是对象,对象中最少有两个属性,一个是path
,代表url
,第二个是component
,代表数据更新的组件,示例代码如下:
let index = Vue.extend({template:"首页
>"})
let find = Vue.extend({template:"发现音乐
>"})
let friend = Vue.extend({template:"我的朋友
>"})
let router = new VueRouter({
routes: [
{path:"/",component:index},
{path:"/find",component:find},
{path:"/friend",component:friend},
]
})
将router
传给Vue
new Vue({
el:"#app",
router: router
})
将网页中之前的a
标签,替换成router-link
。然后指定参数to
表示需要跳转的路径。
<li><router-link to="friend">我的朋友</router-link></li>
使用router-view
指定网页中哪个地方需要被更新
extend
和component
之间的区别
extend
只是创建了一个组件,但是没有加载的Vue
中component
是创建了一个组件,并且起了一个名字,然后加载到Vue
中$route
和$router
的区别
$route
是表示当前访问的路由,其中参数有
fullpath
:完整路径name
:路由名字params
:参数query
:查询字符串参数,或者叫get
参数$router
表示全局的VueRouter
对象url
中定义一个参数,那么以后url
中就可以动态的传递这个参数。语法是:/about/:参数名
。this.$oute.params.参数名
拿到这个参数,或者在组件的模板中,可以直接使用$route.params.参数名
拿到。this.$route
和this.$router
使用动态路由的时候,如果只有请求参数的不同,则Vue
默认使用组件的复用,这虽然回加快渲染效率,但是由于组件一直存在,所以不会在调用生命周期函数,可能出现问题。
解决这个问题可以采用监听属性
let index = Vue.extend({template:"首页
"})
let about = Vue.extend({
template:"个人中心:{{$route.params.userid}}
",
mounted(){
console.log(this.$route.params.userid);
},
watch: {
"$route": function (to, from_) {
console.log(to);
console.log(from_);
}
}
})
let friend = Vue.extend({
template:"我的朋友
",
})
let router = new VueRouter({
routes: [
{path:"/",component:index},
{path:"/about/:userid",component:about},
{path:"/friend",component:friend},
]
})
new Vue({
el:"#app",
router: router
})
使用路由守卫
beforeRouteUpdate: function (to, from, next) {
console.log(to);
console.log(from);
next()
}
to
表示下一个路由from
表示当前路由next
是一个函数,也就是跳转函数*
来匹配未知的路由,可以将将这个路由映射到一个404的组件中this.$router.replace
来跳转到404的页面<div id="app">
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigationspan>
<span class="icon-bar">span>
<span class="icon-bar">span>
<span class="icon-bar">span>
button>
<a class="navbar-brand" href="#">网易云音乐a>
div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="active"><router-link to="/">首页router-link>li>
<li><router-link to="find">发现音乐router-link>li>
<li><router-link to="friend">我的朋友router-link>li>
ul>
div>
div>
nav>
<div class="container">
<router-view>router-view>
div>
div>
<script>
let index = Vue.extend({template:"首页
"})
let find = Vue.extend({template:"发现音乐
"})
let friend = Vue.extend({
template:"我的朋友{{$route.params.user_id}}
",
mounted(){
if(this.$route.params.user_id !== '123'){
this.$router.replace("/404")
}
},
watch:{
"$route": function (to, from) {
// 监听user_id改变
// 想服务端发送请求,验证是否存在
// 如果返回不存在需要跳转到404页面
}
}
})
let notfound = Vue.extend({
template:"404页面没有找到
",
})
let router = new VueRouter({
routes: [
{path:"/",component:index},
{path:"/find",component:find},
{path:"/friend/:user_id",component:friend},
{path:"/404",component:notfound},
{path:"*",component:notfound},
]
})
new Vue({
el:"#app",
router: router
})
script>
在大的路由下面有时候可能使用一些子路由来切换数据,那么这时候可以使用路由嵌套。
首先在定义路由的时候不需要放在routes
中,而是应该放在父路由的children
中。
在父路由的组件中,要记得添加路由出口
,示例代码如下。
<div id="app">
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigationspan>
<span class="icon-bar">span>
<span class="icon-bar">span>
<span class="icon-bar">span>
button>
<a class="navbar-brand" href="#">网易云音乐a>
div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="active"><router-link to="/">首页router-link>li>
<li><router-link to="find">发现音乐router-link>li>
ul>
div>
div>
nav>
<div class="container">
<router-view>router-view>
div>
div>
<script>
let index = Vue.extend({template:"首页
"})
let find = Vue.extend({
template:`
发现音乐
`
})
let user_ldh = Vue.extend({
template:`刘德华
`
})
let user_lm = Vue.extend({
template:`黎明
`
})
let user_gfc = Vue.extend({
template:`郭富城
`
})
let router = new VueRouter({
routes: [
{path:"/",component:index},
{
path:"/find",
component:find,
children: [
{path:"",component:user_ldh},
{path:"lm",component:user_lm},
{path:"gfc",component:user_gfc},
]
},
]
})
new Vue({
el:"#app",
router: router
})
script>
this.$router.push
:跳转到下一个url
,会把新转入的url
添加到浏览器的history
中。参数
path
和name
都可以,但是如果使用了path
,那么参数必须放到path
中,放到params
中无用this.$router.replace
:用法和push
一样,只是会替换当前页面,不会存在历史记录,也就是当点击前进或者后退的时候都没有这个页面。this.$router.go
:前进或者后退。
this.$router.go(1)
,前进一步this.$router.go(-2)
,后退两步
在定义路由的时候指定name
属性作为路由的名字,然后在使用路由的时候传递一个对象,这个对象中包含name
属性,使用方法和this.$router.push
中参数一样。
需要注意使用router-link
的时候要在to
前使用:
因为使用了变量。
个人中心
components
参数,然后把所有需要展示的组件都放到这个里面components
是一个对象,{name:组件}
映射。
来实现。default
,可以在components
中指定这个出口对应的组件。
redirect
来指定重定向的位置。alias
来指定url
的别名。起别名之后,也可以通过别名来访问这个路由。
beforeEach
全局导航守卫就是在VueRouter
上实现的。
这个是在路由发生变化了,但是页面还没有跳转时候执行的函数。
beforeEach(to,from,next)
to
:是上一个路由对象from
: 是下一个路由对象next
:表示下一步该怎么走
next()
:按照正常走next('/')
:中断之前的路由,重新走到 /
路由上,也可以传递{name:'/'}
这种指定名字的路由next(false)
:中断路由,什么也不做,不会导向任何一个路由。afterEach
afterEach(to,from)
to
:表示上一个路由from
:表示下一个路由
首页
我的账户
我的订单
登陆
是绑定到路由上的,在定义路由的时候需要指定beforeEnter
属性
首页
我的账户
我的订单
登陆
主键导航守卫是绑定到组件上的,有三个方法:
veforeRouteEnter
:是在组件之前调用
comfirm
之前调用this
来代表组件,因为组件还没创建next
中使用vm
来代表组件next(vm=>{ console.log(vm.username) })
beforeRouteYpdate
:这个是在进入组件之前调用,也就是当前路由改变,页面还没渲染的时候调用
this
beforeRouteLeave
:这个是在即将离开组件路由的时候执行的函数
this
beforeEach
守卫beforeRouteUpdate
守卫beforeEnter
beforeRouteEnter
beforeResolve
守卫(2.5+)afterEach
DOM
更新元素beforeRouteEnter
守卫传递next
的回调函数.Vue
中分成三个模块,template
、script
、style
。
template
:模板script
:js相关代码style
:样式相关代码import XXX from XXX
.vue
中的style
中的样式是全局可用的style
标签中加入scoped
属性后,使样式只能在当前标签可用
App.vue
作为主入口文件,因此一般全局的样式会写在这个中,比如清空浏览器默认样式等lang='scss'
可以用来写sass
语法使用包postcss-pxtorem
和lib-flexible
npm install postcss-pxtorem --save-dev
npm install lib-flex --save-dev
需要配置package.json
文件
"postcss": {
"plugins": {
"autoprefixer": {},
"postcss-pxtorem": {
"rootValue": 37.5,// 基数,也就是1rem = 多少px,一般为设计师给的数除以10
"propList": [ // 什么属性支持转换
"*"
],
"selectorBlackList": [ // 什么不用转换
"van-*"
]
}
}
},
引用组件需要安装包babel-plugin-import
,用于解析import
cnpm install babel-plugin-import --save
需要配置babel.config.js
文件
babel-plugin-vant
错误module.exports = {
presets: [
'@vue/app'
],
plugins : [
['import',{
libraryName: 'vant',
libraryDirectory: 'es',
style : true,
},'vant']
]
}
导入语法{ botton } from 'vant'