Vue基础学习网站链接
从入门到起飞1
Vue如何使用与vue常见问题
ES6小基础
箭头字符串
var name = "成哥";
var age = 18;
var str = `姓名:${name},年龄:${age}`;
//相当于
// str = "姓名:" + name + ",年龄:" + age;
console.log(str);
速写方法
var obj = {
name: "张三",
sayHello() {
console.log(this.name);
},
};
obj.sayHello();
速写属性
var name = "abc";
var age = 13;
var obj = {
name,
age,
};
console.log(obj);
基础
基础语句
<body>
<div id="app">
</div>
<script>
new Vue({
el: "#app", //app为前面div区块的id的值,通过"#"号绑定
//data区域定义属性的值
data: {
shuzhu: ""
},
//methods区域里面定义自己所写的函数
methods: {
//自定义了一个函数,名称为details
details: function() {
//调用该函数的时候,会返回下面的值
return;
}
},
//下面是过滤器
filters: {
//自定义过滤器的处理函数
capitalize: function(value) {
//返回处理后的字符串
return;
}
}
})
</script>
</body>
vue之修饰符
计算属性与方法的区别:
1.计算属性是基于他们的依赖进行缓存的
2.方法不存在缓存
侦听器
数据一旦发生变化就通知侦听器所绑定的方法
1.侦听器的应用场景:
验证用户名是否可用(用户名是否已经存在)(注册账号)
数据变化时执行异步或开销较大的操作
只要数据发生变化,方法就会马上变化
<div id="app">
<span>用户名:</span>
<input type="text" v-model.lazy='uname'>
</div>
<script>
/*
侦听器
1.采用侦听器侦听用户名的变化
2.调用后天接口进行验证
3.根据验证的结果调整提示信息
*/
new Vue({
el: '#app',
data: {
uname: '',
tip: ''
},
methods: {
checkName: function(uname) {
//调用接口,但是可以使用定时的任务的方式模拟接口调用
var that = this;
setTimeout(function() {
//模拟接口调用
if (uname == 'admin') {
that.tip = '用户名已经存在,请更换一个'
} else {
that.tip = '用户名可以使用'
}
}, 2000)
}
},
watch: {
uname: function(val) { //定义的名字要跟你要监听的量的名字一样,只要定义的发生变化,val就会发生变化
//val表示变化之后的值
//调用后台接口验证用户名的合法性
this.checkName(val);
//修改提示信息
this.tip = '正在验证...';
}
},
})
</script>
- 过滤器
过滤器的作用:
格式化数据,比如将字符串格式化为首字母大写,将日期格式化为指定的格式等 - 自定义过滤器
Vue.filter('过滤器名称',function(value){
//过滤器的业务逻辑
})
- 过滤器的使用
<div>{{msg|upper}}</div>
<div>{{msg|upper|lower}}</div>
<div v-bind:id="id|formatId"></div>
实例:输入后显示要求首字母大写
<div id="app">
<input type="text" v-model="msg">
<div>{{msg|upper}}</div>
</div>
<script>
new Vue({
el: '#app',
data: {
msg: ''
},
filters: {
upper: function(val) {
return val.charAt(0).toUpperCase() + val.slice(1);
}
}
})
</script>
- 带参数的过滤器
Vue.filter('format',function(value,arg1){
//value就是过滤器传过来的参数
})
过滤器的使用
<div>{{data|format('yyyy-MM-dd')}}</div>
- 修改响应式数据
Vue.set(vm.items,indexOfltem,newValue)
vm.$set(vm.items,indexOfltem,newValue)
1.参数一表示要处理的数组名称
2.参数二表示要处理的数组的索引
3.参数二表示要处理的数组的值
<div id="app">
<ul>
<li v-for='i in list'>{{i}}</li>
</ul>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
list: ['apple', 'orange', 'banana']
},
});
Vue.set(vm.list, 2, 'lemon')//在list中修改第三个数的值为lemon
</script>
组件
组件详解
注意事项:
组件配置对象和vue实例有以下几点差异:
如果使用驼峰式命名组件,那么在使用组件的时候,只能在字符串模板中用驼峰方式使用组件,但是如果在普通标签模板中,必须使用短横线的方式使用组件。
- 无el
- data必须是一个函数,该函数返回的对象作为数据
- 由于没有el配置,组件的模板必须定义在template中
注册组件
注册组件分为两种方式,一种是全局注册,一种是局部注册
- 全局注册
一旦全局注册了一个组件,整个应用中任何地方都可以使用该组件
全局注册的方式是:
// 参数1:组件名称,将来在模板中使用组件时,会使用该名称
// 参数2:组件配置对象
// 该代码运行后,即可在模板中使用组件
Vue.component('my-comp', myComp)
在模板中,可以使用组件了
<my-comp />
<!-- 或 -->
<my-comp></my-comp>
但在一些工程化的大型项目中,很多组件都不需要全局使用。
比如一个登录组件,只有在登录的相关页面中使用,如果全局注册,将导致构建工具无法优化打包
因此,除非组件特别通用,否则不建议使用全局注册
- 局部注册
局部注册就是哪里要用到组件,就在哪里注册
局部注册的方式是,在要使用组件的组件或实例中加入一个配置:
<div id="app">
<Count></Count>
</div>
<script>
var Count = {
template: '<h1>你好啊</h1>' //模板
}
new Vue({
el: "#app",
data: {},
components: { //注册组件
Count
}
})
</script>
// 这是另一个要使用my-comp的组件
var otherComp = {
components:{
// 属性名为组件名称,模板中将使用该名称
// 属性值为组件配置对象
"my-comp": myComp
},
template: `
<div>
<!-- 该组件的其他内容 -->
<my-comp></my-comp>
</div>
`;
}
import UserInfo from "./components/UserInfo.js";
var template = `<div id="app">
<UserInfo v-for="(item,i) in users" :key="i" :name="item.name" :age="item.age" />
</div>`;
export default {
template,//模板
components: {//注册组件
UserInfo,//组件
},
}
向组件传递数据
大部分组件要完成自身的功能,都需要一些额外的信息
比如一个头像组件,需要告诉它头像的地址,这就需要在使用组件时向组件传递数据
传递数据的方式有很多种,最常见的一种是使用组件属性 component props
首先在组件中申明可以接收哪些属性:
<template>
<div id="app">
<div style="width:1080px;margin:0px auto">
<!-- 我是父组件,传递消息给子组件,需要传递的消息在下面输入 -->
<!-- 父组件,可以在引用子组件的时候,通过属性绑定(v-bind:)的形式,把需要传递给子组件的数据,
以属性绑定的形式,传递到子组件内部,供子组件使用 -->
<!-- 绑定自定义属性banners,值等于data属性的banners值 -->
<Banner :banners="banners"/>
</div>
</div>
</template>
export default {
//注册组件,就可以在这个界面使用了
//结论:子组件中,默认无法访问到 父组件中的data上的数据 methods中的方法
components:{
Banner,
},
data() {
return {
banners:[
{url:banner1,link:"https://baidu.com"},
{url:banner2,link:"https://baidu.com"},
{url:banner3,link:"https://baidu.com"}
]
}
},
}
在使用组件时,向其传递属性:
<template>
<div class="banner-container">
<!-- 图片 -->
<ul class="images" style="width:300%">
<li v-for="(item,i) in banners" :key="i">
<!-- 用动态值的话无法引用 -->
<a :href="item.link"><img :src="item.url" alt=""></a>
</li>
</ul>
<!-- 小点 -->
<ul class="dots">
<li class="active"></li>
<li></li>
<li></li>
</ul>
</div>
</template>
<script>
//思考:哪些数据需要放到js中管理
//有哪些图片,每张图片的超链接地址(图片信息数组[{url:"xxx",link:"xxx"}]),当前显示的事第几章图片
export default {
//子组件想要使用传递过来的数据,必须按照传过来的属性,原样定义一个
//用props定义
//props中的数据,都是只读的,无法重新赋值,但是自身data的值是可读可写的
//注意,组件中的所有banners中的数据,都是通过父组件传递给子组件的
props:{//把父组件传递过来的banners属性,先在props数组中定义一下,这样,才能使用这个数据
//可以写成props:['banners']
banners:{
type: Array,//属性类型是数组
required:true,//必须要传递该属性
},
},
}
</script>
子组件向父组件传值
1.子组件通过自定义事件向父组件传递信息
<button v-on=:click='$emit("enlarge-text")'>扩大字体</button>
2.父组件监听子组件的事件
<menu-item v-on:enlarge-text='fontSize+=0.1'></menu-item>
非父子组件间传递
1.单独的事件中心管理组件间的通信
var eventHub=new Vue()
2.监听事件与销毁时间
eventHub.$on('add-todo',addTodo)
eventHuv.$off('add-todo')
3.触发事件
eventHub.$emit('add-todo',id)
组件插槽的作用
1.父组件向子组件传递内容
插槽位置:
Vue.component('alert-box',{
template:`
<div class="demo-alter-box">
<strong>Eroor!</strong>
<slot></slot>
</div>
`
})
插槽内容
<alert-box>传递过去的数据</alert-box>
工程结构
App.js
import UserInfo from "./components/UserInfo.js";
var template = `<div id="app">
<UserInfo v-for="(item,i) in users" :key="i" :name="item.name" :age="item.age" />
</div>`;
export default {
template,
components: {
UserInfo,
},
data() {
return {
users: [
{ name: "aa", age: 18 },
{ name: "bb", age: 68 },
{ name: "cc", age: 16 },
],
};
},
};
main.js
import Vue from "./lib/vue.js";
import App from "./App.js";
new Vue({
render: (h) => h(App),
}).$mount("#app");
组件UserInfo
var template = `<div>
<p>姓名:{{name}}</p>
<p>年龄:{{age}}</p>
</div>`;
export default {
props: ["name", "age"],
template,
};
Vue-cli基础
安装node.js及npm和cnpm
使用vue-cli提供的命令搭建工程:
vue create 工程名
注意:工程名只能出现英文、数字和短横线
第一个是默认的,第二个是手动的(选择手动的)
创建完后如何运行
找到所在文件夹
打开cmd
先 cd 文件名进入项目
npm run serve启动项目
如何编写代码
创建一个组件
<!--写入default.vue会自动出来一个模板-->
<!--写组件-->
<template>
<h1>轮播图</h1>
</template>
<!--写js代码-->
<script>
export default {
}
</script>
<!--写css代码-->
<style>
</style>
然后在App.vue中使用
<template>
<div id="app">
<Banner />
</div>
</template>
<script>
// 导入组件
import Banner from "./components/Banner"
export default {
//注册组件,就可以在这个界面使用了
components:{
Banner,
}
}
</script>
路由
路由的本质就是对应关系
在开发中,路由分为前端路由跟后端路由:
- 后端路由:
概念:根据不同的用户URL请求,返回不同的内容
本质:URL请求地址与服务器资源之间的对应关系
SPA
后端渲染(存在性能问题)
先安装第三方库
npm i vue-router
准备工作
在入口里面导入
import VueRouter from “vue-router”
//安装
Vue.use(VueRouter );
//创建路由对象
const router = new VueRouter({
//配置
routes
})
new Vue({
el: "#app",
router //配置路由到vue实例中
})
路由模式:
- hash:路径来自于地址栏中#后面的值,这种模式兼容性比较
- history:路径来自于真实的地址路径,旧浏览器不兼容
- abstract:路径来自于内存
配置实例
const router = new VueRouter({
routes,
//配置
mode: "history"
})
在导入路由组件的时候会把它们一起导入进去,
所以需要动态导入来提高他们的效率。
需要在同一个界面加载不同数据.用"/地址/:id"
{
path: '/bar/:id',//后面:id的意思是后面不管加什么,都加载这个界面
component: ()=>("路由地址"),//走到这就是动态导入
}
地址写成这样后他会在全局添加一个数据 this.$route
要写报错路径
{
path:"*",//匹配所有路径,然后连接报错页面
}
- 路由重定向
路由重定向指的是:用户在访问地址A的时候,强制用户跳转到地址C,从而展示特定的组件页面;
通过路由规则的redirect属性,指定一个新的路由地址,可以很方便地设置路由的重定向:
const router = new VueRouter({
routes:[
//其中,path 表示需要被重定向的原地址,redirect 表示将要被重定向的新地址
{path:'/',redirect:'/user'},
{path:'/user',component:User},
{path:'/register',component:Register}
]
})
- 嵌套路由用法:
1.点击父级路由链接显示模板内容,
2.模板内容中又有子级路由链接,
3.点击子级路由链接显示子级模板内容
- 第一步:父路由组件模板
父级路由链接,
父组件路由填充位
<div id="app">
<p>
<router-link to="/user">foo</router-link>
<router-link to="/register">bar</router-link>
</p>
<div>
<!-- 控制组件的显示位置 -->
<router-view></router-view>
</div>
</div>
- 第二步:子级路由模板
子级路由链接
子级路由填充位
const Register = {
template: `<div>
<h1>Register组件</h1>
<hr/>
<router-link to="/register/tab1">Tab1</router-link>
<router-link to="/register/tab2">Tab2</router-link>
<!-- 子路由填充位置 -->
<router-view/>
</div>`
}
- 第三步:嵌套路由配置
父级路由通过children属性配置子级路由
const router = new VueRouter({
routes: [{
path: '/user',
component: User
}, {
path: '/register',
component: Register,
//通过children属性,为/register添加路由规划
children: [{
path: '/register/tab1',
component: Tab1
}, {
path: '/register/tab2',
component: Tab2
}]
}]
})
- 动态匹配路由的基本用法:
<!-- 有如下3个路由链接 -->
<router-link to="/user/1">User1</router-link>
<router-link to="/user/2">User2</router-link>
<router-link to="/user/3">User3</router-link>
const router = new VueRouter({
routes:[
//动态路径参数,以冒号开头
{path:'/user/:id',component:User}
]
})
const User = {
//路由组件通过$route.params获取路由参数
template: '<div>User{{$route.params.id}}</div>'
}
- 路由组件传递参数
$route与对应路由形成高度耦合,不够灵活,所以可以使用props将组件和路由解耦 - 1.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>'//使用路由参数
}
- 2.props的值为对象类型
const router = new VueRouter({
routes: [
//如果props是一个对象,它会被按原样设置为组件属性
{
path: '/user/:id',
component: User,
props: {
uname:'list',
age:20
}
}
]
})
const User = {
props: ['uname','age'], //使用props接收路由参数
template: '<div>用户信息:{{uname+"---"+age}}</div>'//使用路由参数
}
- 3.props的值为函数类型
const router = new VueRouter({
routes: [
//如果props是一个函数,则这个函数接收route对象为自己的参数
{
path: '/user/:id',
component: User,
props:route=>({uanme:'cb',age:20,id:route.params.id})
}
]
})
- 命名路由的配置规则
<router-link :to="{name:'user',params:{id:123}}">User1</router-link>
const router = new VueRouter({
routes: [{
path: '/user/:id',
name: 'user',//通过name去router-link实现对应的跳转
component: User
}]
})
-
页面导航的两种方式:
-
声明式导航:通过点击链接实现导航的方式,叫做声明式导航
列如:普通网页中的< a>< /a>链接或vue中的< router-link>< /router-link> -
编程式导航:通过调用javaScript形式的API实现导航的方式,叫做编程式导航
例如:突破普通网页中的location.href -
编程式导航的基本用法
常用的编程式导航API如下:
this. r o u t e r . p u s h ( ′ h a s h 地 址 ′ ) ; / / 实 现 后 退 功 能 t h i s . router.push('hash地址'); //实现后退功能 this. router.push(′hash地址′);//实现后退功能this.router.go(-1)
const User = {
template:'<div><button @click="goRegister">跳转到注册界面</div>',
methods: {
goRegister:function(){
//用编程的方式控制路由跳转
this.$router.push('/register');
}
},
}
前后端交互
接口的调用方式和:
1.fetch
2.axios
Promise用法
function (data){
//data为状态数据
}
//例子
var pro = new Promise((resolve, reject) => {
console.log("任务进行中....");
setTimeout(() => {
resolve("over");
}, 3000);
});
pro.then((data) => {
console.log("成功", data);
}, (err) => {
console.log("失败", err);
});
Promise的链式调用
function delay(duration){
return new Promise(resolve=>{
setTimeout(()=>{
resolve();
}, duration)
})
}
/*
异步任务:
1. 等待1秒,输出1
2. 然后等待2秒,输出2
3. 然后等待3秒,输出3
*/
delay(1000).then(()=>{
console.log(1);
return delay(2000);
}).then(()=>{
console.log(2);
return delay(3000);
}).then(()=>{
console.log(3);
})
对象方法
Promise.all():
并发处理多个异步任务,所有任务都执行完成才能得到结果
Promise.race():
并发处理多个异步任务,只要有一个任务完成就能得到结果
Promise.all([p1,p2,p3]).then((resole)=>{
console.log(resole);
})
Promise.race([p1,p2,p3]).then((resole)=>{
console.log(resole);
})
axios概述
方法一:需要引入
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
方法二:
npm i axios进行安装
安装之后在要使用的页面组件中进行引入。
import axios from ‘axios’
axios的响应结果
data:实际响应回来的数据
headers:响应头信息
status:响应状态码
statusText:响应状态信息
axios的全局配置:
axios.defaults.timeout=3000;//超时时间
axios.defaults.baseURL='http:/localhost:3000/app';//默认地址
axios.defaults.headers['mytoken']='aqwerwqwsghgf';//设置请求头
axios拦截器:
1.请求拦截器:
在请求发出之前设置一些信息
//添加一个请求拦截器
axios.interceptors.request.use(function(config){
//在请求发出之前进行一些信息设置
return config;
},function(err){
//处理响应的错误信息
})
2.响应拦截器:
在获取数据之前对数据做一些加工处理
//添加一个响应拦截器
axios.interceptors.response.use(function(res){
//在这里对返回的数据进行处理
return res;
},function(err){
//处理响应的错误信息
})
小结:
axios的作用:发送异步请求获取数据,常见的方法:get、post;在发送的时候可以指定参数(地址、请求方式和请求头部信息);返回数据结构(data/status/statusText/headers/config)
axios方法及get、post方法使用
目标:使用axios方法获取数据并在页面中将数据遍历显示;切换改为get/post方法实现数据加载
小结:
可以使用axios获取对应服务器数据;如果不是同一个服务器的数据则可能会出现跨域请求;需要在相应额服务器上配置跨域。
一个简单是实例:
<div id="app">
<ul>
<li v-for="(user,i) in users" :key="i">
{{user}}--{{user.name}}--{{user.age}}
</li>
</ul>
</div>
<script>
var app = new Vue({
el: "#app",
data() {
return {
users: []
}
},
created() {
//初始化加载数据
axios({
url: "data.json", //到哪个地方去获取数据就填哪个地址
method: "get" //get方法
}).then(res => {
console.log(res);
//将数据赋值到vue实例中的数据属性userrs;
//不能使用this,在axios回调函数中表示窗口,不是vue实例
app.users = res.data; //其中数据属性是放在res的data属性中
}).catch(err => alert(err));
//加载成功会调用then方法(返回输入为res),加载失败会掉哟用catch方法(返回数据为err)
//第二种get写法
// axios.get("data.json").then().catch(err => alert(err))
},
})
</script>
写在Vue中的service中的话
//要加上async跟await
export async function getNews() {
var resp = await axios.get("xxxx.xxx")
}
async/await用法
1.async/await的基本用法:
async/await是ES7引入的新语法,可以更加方便的进行异步操作
async关键字用于函数上(async函数的返回值是Promise实例对象)
await关键字用于async函数当中(await可以得到异步的结果)
async function queryData(id){
const ret=await new Promise(function(resolve,reject){
setTimeout(() => {
resolve('nihao');
}, 1000);
})
return ret;
}
queryData.then(ret=>{
console.log(ret);
})
async/await处理多个异步请求
async function queryData(id){
const info=await axios.get('/async1');
const ret=await axios.get('async2?info='+info.data);
return ret;
}
queryData.then(ret=>{
console.log(ret);
})
处理共享数据(vuex)
vuex简介
介绍
注意:并非所有数据都需要让vuex管理,通常vuex只管理那些需要被组件共享的数据
在实际的开发中,一些逻辑特别复杂的数据,尽管不共享,也可能提取到vuex中进行管理
1.安装vuex
在页面中引入vuex库 npm i vuex
该库提供了一个构造函数Vuex.Store,通过该构造函数,即可创建一个数据仓库
创建方法跟router差不多
安装vue devtools
这是一个chrome浏览器插件,用于调试vue、vue-router、vuex应用
import vuex from "vuex"
//安装vuex
Vue.use(Vuex);
var store = new Vuex.Store({
// 仓库数据配置
})
new Vue({
// 其他配置
store
})
vuex的核心概念
-
数据的改动:
必须要提交commit一个mutation
在vuex中,提交mutation是数据变化的唯一原因
在mutation中不能出现副作用操作
什么是副作用操作:
1. 改动或使用外部的数据
2. ajax
3. 其他异步行为 -
处理副作用
触发dispatch一个action
store变化逻辑
- 直接通过
mutation
改动仓库数据
- 通过
actioin
改动仓库数据
关系图