饭碗级别技术
应用非常广泛 github
生态好(插件,ui库)
https://cn.vuejs.org/
渐进式JavaScript 框架
作者:尤雨溪
angular 谷歌 2013 指令系统
react facebook 2014 diff算法
vue 尤雨溪
兼容 ie9+
安装
引入
开发版本
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
生产版本
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
使用
代码:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Documenttitle>
<script src="./js/vue.js">script>
head>
<body>
<div id="app">
{
{msg}}
div>
body>
<script>
// console.log(Vue)
// 操作数据
// var app=new Vue({配置信息})
// 2:实例化一个vue对象
var app=new Vue({
el:"#app", //vue实例的作用范围标签
data:{
//数据层 作用域范围内使用到的数据都在这里定义
msg:"中公it"
}
})
// 操作dom元素
// var app=document.getElementById('app');
// var arr=[11,22,33,44];
// var str="中公成都校区"
// app.innerHTML=str;
script>
html>
错误集锦
[Vue warn]: Do not mount Vue to or - mount to normal elements instead.
//不能把vue挂载到html或者body
Vue is not defined
//vue.js文件没有引入
vue核心:数据驱动(数据改变,视图层跟着改变) 声明式渲染
插值表达式 Mustache语法 双花括号 { {}}
语法:
{
{
变量/表达式/函数名()}}
//注意:不能写if语句和for循环
- 代码
```html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Documenttitle>
<script src="./js/vue.js">script>
head>
<body>
<div id="app">
msg
{
{msg}}
{
{msg+'0511'}}
<hr/>
{
{num}}
{
{num+50}}
<hr/>
{
{flag}}
{
{flag?"中公it":"中公尤久业"}}
<hr/>
{
{arr}}
<hr/>
{
{obj.name}}{
{obj.age}}
<hr/>
{
{fn()}}
div>
body>
<script>
var app=new Vue({
el:"#app",
data:{
msg:"中公it",
flag:false,
num:25,
arr:["aaa","bbb","ccc"],
obj:{
name:"张三",
age:25
}
},
methods:{
//所有用到的方法都在这里定义
fn:function(){
alert("123")
},
fn1(){
console.log(123)
}
}
})
script>
html>
vue实例的配置信息
el 作用域范围标签
data 定义数据
methods 定义方法
什么是指令:以v-开头 v-xx,给标签添加的一些新属性【指令就是标签的属性】
使用:
<标签名 v-指令名="变量/表达式">标签名>
提供了哪些指令
v-html
用来进行数据绑定
v-html和{ {}} 的区别: 如果还没渲染 v-html不会显示任何内容,{ {}}会显示{ {msg}};
v-html会解析字符串html,插值表达式不会解析;
v-text
v-html和v-text的区别
v-html会解析字符串html,v-text不会解析;
v-bind
实现属性绑定
百度
简写
百度
```
- 代码
<html lang="en">
<head>
<meta charset="UTF-8">
<title>常用指令title>
<script src="./js/vue.js">script>
head>
<body>
<div id="app">
<p>{
{msg}}p>
<p v-html="msg">p>
<hr/>
<p>{
{htmlstr}}p>
<p v-html="htmlstr">p>
<hr/>
<p v-text="msg">p>
<p v-text="htmlstr">p>
<hr/>
<a v-bind:href="url">百度a>
<img v-bind:src="imgurl"/>
<img :src="imgurl"/>
<p :title="'p标记'">这是一个p标记p>
{
{'p标记'}}
div>
body>
<script>
var app=new Vue({
el:"#app",
data:{
msg:"中公it",
htmlstr:"百度",
url:"http://www.baidu.com",
imgurl:"https://upload.jianshu.io/admin_banners/web_images/4995/af694827b911ab360fe44d5252422109849c5760.jpg?imageMogr2/auto-orient/strip|imageView2/1/w/1250/h/540"
}
})
script>
html>
动态样式绑定
class
代码
<html lang="en">
<head>
<meta charset="UTF-8">
<title>常用指令title>
<script src="./js/vue.js">script>
<style>
.col{
width: 100px;
height: 100px;
background-color: rebeccapurple;
}
.bg{
border: 2px solid red;
}
style>
head>
<body>
<div id="app">
<div class="col bg">div>
<div :class="classN">div>
<div :class="classobj">div>
<div :class="{
'col':false}">div>
<div :class="{
'col':msg=='中公'}">123div>
<div :class="[1==1?'col':'col bg']">456div>
<div :class="'col '+classN">789div>
div>
body>
<script>
var app=new Vue({
el:"#app",
data:{
classN:"bg",
classobj:{
'col':true,
'bg':true
},
msg:"中公it",
htmlstr:"<a href='#'>百度a>",
url:"http://www.baidu.com",
imgurl:"https://upload.jianshu.io/admin_banners/web_images/4995/af694827b911ab360fe44d5252422109849c5760.jpg?imageMogr2/auto-orient/strip|imageView2/1/w/1250/h/540"
}
})
style
动态绑定style的值是一个对象
如果属性名有"-" 需要加引号,若不想加引号要改成驼峰命名法 比如 font-size 改写成fontSize
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Documenttitle>
<script src="./js/vue.js">script>
head>
<body>
<div id="app">
<div style="width:100px;height:100px;background-color:red">div>
<div :style="{
width:'100px',height:'100px','background-color':'pink'}">div>
<div :style="{
width:size,height:'100px',backgroundColor:'pink'}">div>
<div :style="styleobj">div>
<div :style="[stylea,styleb]">各位帅哥美女们div>
{
{msg}}
div>
body>
<script>
var app=new Vue({
el:"#app",
data:{
size:"100px",
msg:"123",
styleobj:{
width:'100px',
height:'100px',
'background-color':'pink'
},
stylea:{
border:"5px solid red",
fontSize:'330px'
},
styleb:{
color:'blue'
}
}
})
script>
html>
v-if
作用:节点的插入和删除
注意:v-if和v-else-if还有v-else的标签要紧邻,否则报错
<标签 v-if="变量/表达式">内容标签>
//值为true插入节点,值为false删除节点、
<标签 v-if="变量/表达式">内容标签>
<标签 v-else>内容标签>
<div v-if="变量/表达式">登录 注册div>
<div v-else-if="变量/表达式">xxx欢迎你div>
<div v-else-if="变量/表达式">xxx欢迎你div>
<div v-else>xxx欢迎你div>
v-show
作用:元素的显示和隐藏(通过样式display控制显示隐藏)
什么时候使用v-if 什么时候使用v-show
频繁的切换元素 使用v-show,只有一两次切换元素使用v-if
使用
<标签 v-show="变量/表达式">内容标签>
v-if和v-show的区别
代码
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Documenttitle>
<script src="./js/vue.js">script>
head>
<body>
<div id="app">
<div v-if="flag">登录 注册div>
<div v-if="!flag">xxx欢迎你div>
<div v-if="flag">登录 注册div>
<div v-else>xxx欢迎你div>
<div v-if="score>=90&&score<=100">
<p>优秀p>
div>
<div v-else-if="score<90&&score>70">良好div>
<div v-else>合格div>
<div>
<span v-show="msg=='国际'">国际span>
<span v-show="msg=='国内'">国内span>
div>
div>
body>
<script>
var app=new Vue({
el:"#app",
data:{
flag:true,
score:89,
msg:"国际"
}
})
script>
html>
v-for
作用:用于对数组或对象进行遍历显示
使用
<标签 v-for="值 in 数组/对象">标签>
<标签 v-for="(值,键) in 数组/对象">标签>
多层嵌套
代码
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Documenttitle>
<script src="./js/vue.js">script>
head>
<body>
<div id="app">
<ul>
<li v-for="(item,index) in arr">
{
{index+1}}----{
{item}}
li>
ul>
<hr/>
<ul>
<li v-for="(val,key) in obj">
{
{key}}--- {
{val}}
li>
ul>
<hr/>
<ul>
<li v-for="item in userarr">
{
{item.name}}-{
{item.age}}-{
{item.sex}}
<ol>
<li v-for="val in item.scorearr">
{
{val.scorename}}-{
{val.scorenum}}
li>
ol>
li>
ul>
div>
body>
<script>
var app=new Vue({
el:"#app",
data:{
arr:["aaa","bbb","ccc","ddd"],
obj:{
name:"小小",
age:21,
sex:"男"
},
userarr:[
{
name:"张三",age:24,sex:"男",
scorearr:[
{
scorename:"china",scorenum:96},
{
scorename:"english",scorenum:12},
{
scorename:"math",scorenum:120}
]
},
{
name:"李四",age:23,sex:"男",
scorearr:[
{
scorename:"china",scorenum:96},
{
scorename:"english",scorenum:12},
{
scorename:"math",scorenum:120}
]},
{
name:"狗蛋",age:25,sex:"男",
scorearr:[
{
scorename:"china",scorenum:96},
{
scorename:"english",scorenum:12},
{
scorename:"math",scorenum:120}
]},
{
name:"翠花",age:21,sex:"女",
scorearr:[
{
scorename:"china",scorenum:96},
{
scorename:"english",scorenum:12},
{
scorename:"math",scorenum:120}
]}
]
}
})
script>
html>
v-for的key值
https://cn.vuejs.org/v2/guide/list.html#%E7%BB%B4%E6%8A%A4%E7%8A%B6%E6%80%81>
”就地复用“问题 加key值, key唯一标识
当 Vue 正在更新使用 v-for
渲染的元素列表时,它默认使用“就地更新”的策略
代码:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Documenttitle>
<script src="./js/vue.js">script>
head>
<body>
<div id="app">
<div v-if="flag">
姓名: <input type="text" key="a1" />
div>
<div v-else>
年龄: <input type="text" key="a2" />
div>
<ul>
<li v-for="(item,index) in arr" :key="item.id">
<input type="checkbox" /> {
{item.name}} {
{index}}
li>
ul>
div>
body>
<script>
var app=new Vue({
el:"#app",
data:{
flag:true,
arr:[
{
id:1,name:"香蕉"},
{
id:2,name:"苹果"},
{
id:3,name:"西瓜"},
{
id:4,name:"梨"}
]
}
})
script>
html>
基础的事件绑定
使用
<标签 v-on:click="函数()">标签>
简写
<标签 @click="函数()">标签>
代码
事件传参
使用
<标签 v-on:click="函数(实参)">标签>
new Vue({
el:"#app",
data:{
},
methods:{
事件函数(形参){
}
}
})
this的使用
this指向的是vue实例
事件对象
使用
new Vue({
el:"#app",
data:{
},
methods:{
事件函数(形参){
//没有传入实参,那么这个形参就是事件对象
}
}
})
<标签 @事件名="事件函数">标签> //不需要传入实参
传实参还要有事件对象
使用
new Vue({
el:"#app",
data:{
},
methods:{
事件函数(形参,事件对象形参){
}
}
})
<标签 @事件名="事件函数(实参,$event)">标签> //形参和实参位置要一一对应
代码
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Documenttitle>
<script src="./js/vue.js">script>
<style>
.box{
width: 200px;
height: 200px;
background-color: pink;
}
style>
head>
<body>
<div id="app">
<button v-on:click="fn()">点我button>
<button v-on:click="fn">点我button>
<button @click="fn()">点我button>
<ul>
<li v-for="(item,index) in arr" :key="index">
{
{item}} <button @click="del(index)"> 删除button>
li>
ul>
<div class="box" @mousemove="move">div>
<a href="http://www.baidu.com" @click="run('成都',$event)">百度a>
div>
body>
<script>
var app=new Vue({
el:"#app",
data:{
msg:"中公it",
arr:["香蕉","葡萄","苹果"]
},
methods:{
fn(){
alert("好好")
},
del(ind){
//删除
// alert(ind)
// this指向的是vue实例
console.log(this.msg)
},
move(event){
//移动事件
// 如果函数没有传入实参,methods里面的事件函数定义的形参就是事件对象
console.log(event.offsetX)
},
run(city,event){
//阻止默认行为
event.preventDefault();
alert(1111,city)
}
}
})
// var box=document.querySelector(".box");
// box.οnmοusemοve=function(event){
// console.log(event.offsetX)
// }
// var a=document.querySelector("a")
// a.οnclick=function(event){
// // 阻止元素的默认行为
// event.preventDefault()
// alert(1111);
// }
script>
html>
架构思想:MVVM
数据双向绑定:数据层改变,视图层跟着改变; 视图层改变,数据层跟着改变;
什么是修饰符: 修饰我们事件和v-model的符号,简化我们的一些操作
使用
<标签 @事件名.修饰符="事件函数">标签名>
事件修饰符
https://cn.vuejs.org/v2/guide/events.html
.stop 阻止事件冒泡
.prevent 阻止默认行为
.self 只当在 event.target 是当前元素自身时触发处理函数
.once 一次性事件绑定
键盘修饰符 (键盘事件) .enter .up .down .left .right
代码
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Documenttitle>
<script src="./js/vue.js">script>
<style>
.box{
width: 300px;
height: 300px;
background-color: pink;
}
.small{
width: 150px;
height: 150px;
background-color: red;
}
style>
head>
<body>
<div id="app">
<input type="text" @keydown.enter="down"/>
<a href="http://www.baidu.com" @click.prevent="fn">百度a>
<button @click.once="pay">确认支付button>
<div class="box" @click="fn1">
<div class="small" @click.stop="fn2">div>
div>
<div class="box" @click.self="fn1">
<div class="small" @click="fn2">div>
div>
<div class="box" @click="fn1">
<a href="http://www.baidu.com" @click.stop.prevent="fn">百度a>
div>
div>
body>
<script>
var app=new Vue({
el:"#app",
data:{
},
methods:{
fn(){
alert(1111);
},
pay(){
alert("支付完成")
},
fn1(){
alert("大盒子box")
},
fn2(){
alert("小盒子small")
},
down(){
console.log("enter");
}
}
})
script>
html>
.lazy 不会实时数据绑定,在changge事件中进行数据绑定
.number 将输入的内容数据类型转换为数值
.trim 过滤首尾空白字符
代码
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Documenttitle>
<script src="./js/vue.js">script>
head>
<body>
<div id="app">
<input type="text" v-model.lazy="username" />
{
{username}}
年龄:<input type="text" v-model.number="age"/>
<input type="text" v-model.trim="str"/>
div>
body>
<script>
var app=new Vue({
el:"#app",
data:{
username:"",
age:0,
str:""
}
})
script>
html>
1:说说你对this的理解,如何改变this指向
this表示当前对象,this的指向是根据调用的上下文来决定的,默认指向window对象。
一、全局环境:
全局环境就是在里面,这里的this始终指向的是window对象。
二、局部环境:
1)在全局作用域下直接调用函数,this指向window。
2)对象函数调用,哪个对象调用就指向哪个对象。
3)使用 new 实例化对象,在构造函数中的this指向实例化对象。
4)使用call或apply改变this的指向。
生命周期:一个vue实例生命的周期,也就是vue实例从开始到结束的过程,从创建到销毁的过程;
生命周期阶段
创建阶段
挂载阶段
beforeMount 挂载之前
注意:在这个函数里,页面没有真正渲染,只是有了虚拟dom(js对象)
mounted 挂载之后
作用: 把虚拟dom真正的渲染到页面上,页面上有了真实dom
从这里开始可以使用$refs获取dom节点
初始化一些插件相关的配置,也可以发送数据请求
更新阶段
销毁阶段
代码
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Documenttitle>
<script src="./js/vue.js">script>
head>
<body>
<div id="app">
{
{msg}}
<button @click="fn">点击button>
div>
body>
<script>
var app=new Vue({
el:"#app",
data:{
msg:"中公it"
},
methods:{
fn(){
console.log(123)
}
},
//创建阶段
beforeCreate(){
//这里不能操作data里面的数据,因为data没有被初始化
console.log(this.msg);
console.log("创建之前");
console.log(document.querySelector("#app"));
},
created(){
// 一般在这里发送数据请求,开启定时器
console.log(this.msg);
console.log("创建之后");
console.log(document.querySelector("#app"));
},
//挂载阶段
beforeMount(){
console.log("挂载之前");
console.log(document.querySelector("#app"));
},
mounted(){
console.log("挂载之后");
console.log(document.querySelector("#app"));
},
//更新阶段
beforeUpdate(){
// 做一些判断 是否需要更新
console.log("更新之前");
console.log(document.querySelector("#app"));
},
updated(){
console.log("更新之后");
console.log(document.querySelector("#app"));
},
//销毁阶段
beforeDestroy(){
// 销毁之前做一些保存
console.log("销毁前");
},
destroyed(){
// 释放定时器相关的内容
// 销毁之后,事件绑定都不存在了
console.log("销毁后");
}
})
setTimeout(()=>{
app.$destroy(); //销毁vue实例
},10000)
script>
html>
作用 :来监听data里面数据的变化,一旦数据变化了就会自动执行相关的函数
分类:
使用
var app=new Vue({
el:"#app",
data:{
a:2,
b:0
},
watch:{
//监听器
data中的变量(新值,旧值){
//浅监听
//变量的值发生变化,就会执行这里的代码
},
data中变量:{
deep:true, //深监听 【监听引用类型】
handler(新值){
//代码块
}
}
}
})
代码
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Documenttitle>
<script src="./js/vue.js">script>
head>
<body>
<div id="app">
<input type="text" v-model.number="a"/>
+
<input type="text" v-model.number="b"/>
=
<input type="text" v-model="c"/>
<hr/>
<p>姓名:{
{user.name}}p>
<p>年龄:{
{user.age}} <button @click="ageadd">年龄增长button>p>
div>
body>
<script>
var app=new Vue({
el:"#app",
data:{
a:0,
b:0,
c:0,
user:{
name:"小小",
age:25
}
},
methods:{
ageadd(){
this.user.age++;
}
},
watch:{
a(newv,oldv){
// console.log(123)
// console.log(newv) //变化之后的值
// console.log(oldv) //变化之前的值
this.c=newv+this.b
},
b(newv,oldv){
this.c=newv+this.a
},
user:{
//深度监听
deep:true,
handler(newv){
console.log(1);
console.log(newv)
}
}
}
})
script>
html>
含义:计算 动词 属性 名词
使用
var app=new Vue({
el:"#app",
data:{
}, //定义默认数据的地方
computed:{
//通过计算得到属性
属性名:function(){
//值一定是一个函数,而且这个函数一定要有返回值
return 值;
}
}
}
})
{
{属性名}}
注意:
面试题:watch和computed的区别?
watch: 监听data和computed中数据的变化;可以进行异步操作;
computed: 定义属性(该属性通过计算得到);不能进行一步操作;通过return 返回处理的数据;
computed的get和set
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Documenttitle>
<script src="./js/vue.js">script>
head>
<body>
<div id="app">
<input type="text" v-model.number="a"/>
+
<input type="text" v-model.number="b"/>
=
<input type="text" v-model="c"/>
{
{c}}
div>
body>
<script>
var app=new Vue({
el:"#app",
data:{
a:0,
b:0
// ,c:0
},
computed:{
// c(){
// // 页面第一次加载时,该函数会(第一次)默认执行,给属性赋初始值
// //依赖属性变化的时候,该函数会再次执行
// console.log("computed")
// return this.a+this.b //this同样是vue实例
// }
c:{
get(){
//c被获取时执行这里(直接读取c的值不会执行)
console.log("get");
return this.a+this.b;
},
set(v){
//c被设置时执行这里 v就是设置的值
console.log("set",v);
}
}
}
})
script>
html>
1:Method “allcheck” has already been defined as a data property.
data中的变量名和methods中的方法名冲突了
语法
Vue.component('组件名',{
组件配置对象})
使用(调用)组件
<组件名>组件名>
注意:
代码
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Documenttitle>
<script src="./js/vue.js">script>
<style>
ul{
padding: 0;
margin: 0;
list-style: none;
width: 500px;
display: flex;
height: 50px;
border: 1px solid;
}
li{
width: 99px;
height: 50px;
border-right: 1px solid;
line-height: 50px;
text-align: center;
}
.active{
background-color: yellow;
color:red;
}
style>
head>
<body>
<div id="app">
<mycom>mycom>
<hr/>
<mycom>mycom>
div>
<h3>---------分割线-------h3>
<div id="main">
<mycom>mycom>
div>
body>
<script>
Vue.component("mycom",{
// template指定组件的模板
template: ""
})
// 全局注册组件需要放在vue实例化之前,所有的vue实例都可以使用
var app=new Vue({
el:"#app",
data:{
}
})
var main=new Vue({
el:"#main",
data:{
}
})
script>
html>
语法
var app=new Vue({
el:"#app",
data:{
},
components:{
组件名:{
配置对象},
组件名:{
配置对象}
}
})
使用
<组件名>组件名>
注意
代码
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Documenttitle>
<script src="./js/vue.js">script>
<style>
ul{
padding: 0;
margin: 0;
list-style: none;
width: 500px;
display: flex;
height: 50px;
border: 1px solid;
}
li{
width: 99px;
height: 50px;
border-right: 1px solid;
line-height: 50px;
text-align: center;
}
.active{
background-color: yellow;
color:red;
}
style>
head>
<body>
<div id="app">
<mycon>mycon>
div>
<h3>---------分割线-------h3>
<div id="main">
div>
body>
<script>
var app=new Vue({
el:"#app",
data:{
},
components:{
// 组件名:{配置对象}
// 局部组件只能在当前所在的实例去使用
mycon:{
template:`
我是局部组件
`
}
}
})
var main=new Vue({
el:"#main",
data:{
}
})
script>
html>
代码
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Documenttitle>
<script src="./js/vue.js">script>
<style>
ul{
padding: 0;
margin: 0;
list-style: none;
width: 500px;
display: flex;
height: 50px;
border: 1px solid;
}
li{
width: 99px;
height: 50px;
border-right: 1px solid;
line-height: 50px;
text-align: center;
}
.active{
background-color: yellow;
color:red;
}
style>
head>
<body>
<div id="app">
<mycon>mycon>
<mybb>mybb>
div>
<template id="aa">
<div>
<div>
<h3>我是局部组件h3>
div>
<div>789div>
div>
template>
<template id="bb">
<div>123div>
template>
body>
<script>
var app=new Vue({
el:"#app",
data:{
},
components:{
// 组件名:{配置对象}
// 局部组件只能在当前所在的实例去使用
mycon:{
template:"#aa"
},
mybb:{
template:"#bb"
}
}
})
script>
html>
1:Component template should contain exactly one root element. If you are using v-if on multiple elements, use v-else-if to chain them instead.
组件模板有且只有一个根元素
2:Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the “name” option.
不知道元素 你确定注册了这个组件了吗?
代码
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Documenttitle>
<script src="./js/vue.js">script>
<style>
ul{
padding: 0;
margin: 0;
list-style: none;
width: 500px;
display: flex;
height: 50px;
border: 1px solid;
}
li{
width: 99px;
height: 50px;
border-right: 1px solid;
line-height: 50px;
text-align: center;
}
.active{
background-color: yellow;
color:red;
}
style>
head>
<body>
<div id="app">
<mycon>mycon>
<hr/>
<mybb>mybb>
body>
<script>
Vue.component("mycd",{
template:"00000"
})
var app=new Vue({
el:"#app",
data:{
},
components:{
// 组件名:{配置对象}
// 局部组件只能在当前所在的实例去使用
mycon:{
template:`
mycon
`,
components:{
aa:{
template:`
aaa
`
}
}
},
mybb:{
template:`
mybb
`
}
}
})
script>
html>
The “data” option should be a function that returns a per-instance value in component definitions.
data选项应该是一个函数
组件中的data是一个函数,返回一个对象
template是指定模板的
其他配置选项和vue实例一模一样的
代码
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Documenttitle>
<script src="./js/vue.js">script>
<style>
ul{
padding: 0;
margin: 0;
list-style: none;
width: 500px;
display: flex;
height: 50px;
border: 1px solid;
}
li{
width: 99px;
height: 50px;
border-right: 1px solid;
line-height: 50px;
text-align: center;
}
.active{
background-color: yellow;
color:red;
}
style>
head>
<body>
<div id="app">
<mycon>mycon>
<hr/>
<mybb>mybb>
div>
body>
<script>
Vue.component("mycd",{
template:`
mycd全局组件
{
{msg}}
`,
data:function(){
return {
msg:"成都"
}
},
methods:{
fn(){
this.msg="nihao"
}
}
})
var app=new Vue({
el:"#app",
data:{
},
components:{
// 组件名:{配置对象}
// 局部组件只能在当前所在的实例去使用
mycon:{
template:`
mycon
`,
components:{
aa:{
template:`
aaa
`
}
}
},
mybb:{
template:`
mybb
`
}
}
})
script>
html>
确保电脑安装了node环境,输入以下命令检测是否安装了node
node -v //显示版本号说明安装了node 如果提示node不是内部命令,那就就去安装node
node的安装地址:https://nodejs.org/en/download/
npm install vue-cli -g //全局安装脚手架工具
如果电脑上安装了cnpm淘宝镜像,可以使用cnpm 安装
cnpm install vue-cli -g
如果没有淘宝镜像先安装淘宝镜像
npm install cnpm -g --registry=http://registry.npm.taobao.org
z执行完了 执行 cnpm/npm install vue-cli -g 该命令 安装脚手架工具
vue -V //显示版本号说明安装成功
2.9.6
找到需要存储项目的目录
在该目录下执行命令
vue init webpack 项目名(英文)
启动项目
npm run dev
or
npm start
1-1、组件
1-2、组件定义
局部注册
全局注册
Vue.component("组件名",{
template:`有且只能有一个根元素`,
data(){
return {
}
}
})
1-3、组件命名规范
1-4、组件嵌套
1-5、组件的配置项
1-6、vue-cli脚手架
命令行出现:
canot found module ‘user-home’
找不到模块
发给别人一个vue项目
删除项目目录下的node_modules包
压缩项目文件夹,将文件夹发给别人即可
如何运行别人发给你的vue项目
定义组件
在components目录下新建xxx.vue文件
在xxx.vue文件下写入代码
这个是myhead组件
使用组件
引入,注入,调用
// 组件模板
<template>
<div>
我的第一个vue项目
<!-- 3:调用 -->
<Myhead></Myhead>
</div>
</template>
// js
<script>
// 1:引入
import Myhead from './components/Myhead'
export default {
components:{
//2:注入
Myhead
}
}
</script>
1:父组件调用子组件,给子组件自定义属性
//父组件
<子组件 属性1="值" 属性2="值">子组件>
<子组件 :属性="变量">子组件>
2:子组件通过props接收父组件传来的自定义属性
<script>
export default {
props:['属性1','属性2']
}
</script>
3:子组件视图上直接使用该自定义属性
{
{属性1}}
代码
父组件
// 组件模板
<template>
<div>
<Myhead :mycon="num" :mycom="flag" :dataarr="arr[0]">Myhead>
<Myhead :dataarr="arr[1]">Myhead>
<Myhead :dataarr="arr[2]">Myhead>
<hr/>
<Myhead v-for="(item,index) in arr" :key="index" :dataarr="item">Myhead>
div>
template>
// js
<script>
import Myhead from './components/Myhead'
export default {
data(){
return {
flag:true,
num:25,
arr:[
{
title:"学院动态",
list:[
'中国上市企业市值500强出炉 中公教育位居',
'中国上市企业市值500强出炉 中公教育位居',
'中国上市企业市值500强出炉 中公教育位居'
]
},
{
title:"学员活动",
list:[
'中国上市企业市值500强出炉 中公教育位居1',
'中国上市企业市值500强出炉 中公教育位居1',
'中国上市企业市值500强出炉 中公教育位居1'
]
},
{
title:"常见问题",
list:[
'中国上市企业市值500强出炉 中公教育位居2',
'中国上市企业市值500强出炉 中公教育位居3',
'中国上市企业市值500强出炉 中公教育位居4'
]
}
]
}
},
components:{
Myhead
}
}
script>
// css
<style>
style>
子组件
<template>
<div>
<div class="list">
{
{mycon}} ----{
{mycom}}
<h3>{
{dataarr.title}}h3>
<ul>
<li v-for="(item,index) in dataarr.list" :key="index">
{
{item}}
li>
ul>
div>
div>
template>
<script>
export default {
props:['mycon','mycom','dataarr'], //2:通过props接收父组件传来的数据
data(){
return {
arr:[
"中国上市企业市值500强出炉 中公教育位居",
"中国上市企业市值500强出炉 中公教育位居",
"中国上市企业市值500强出炉 中公教育位居"
]
}
}
}
script>
<style>
style>
为了使组件内部使用数据的可靠性,我们对外部传递进来的数据进行校验
如何实现校验
//方式1
props:['属性1','属性2']
//方式2 (String,Number,Boolean,Array,Object Date Function Symbol)
props:{
属性1:类型 , //只有类型检测
属性2:[类型1,类型2]
}
//方式3
props:{
属性1:{
type:类型 ,
default:默认值,
required:true/false,
validator:function(val){
//validator函数一定要有返回值,返回true表示验证通过,false验证不通过 控制台有警告
}
}
}
代码
<template>
<div>
<div class="list">
{
{mycon}} ----{
{mycom}}
<h3>{
{dataarr.title}}h3>
<ul>
<li v-for="(item,index) in dataarr.list" :key="index">
{
{item}}
li>
ul>
div>
div>
template>
<script>
export default {
// props:['mycon','mycom','dataarr'], //2:通过props接收父组件传来的数据
// props验证,为了使组件内部使用数据的可靠性,我们对外部传递进来的数据进行校验
props:{
// mycon:String , //类型验证
mycon:{
type:String,
default:"hellworld" //默认值
},
// mycom:[String,Number],
mycom:{
type:String,
required:false, //是否必须传入 true必须 false可以不传入
validator:function(val){
// 验证函数
// validator函数一定要有返回值,返回true表示验证通过,false验证不通过 控制台有警告
if(val.length<5){
return true;
}else{
return false;
}
}
},
dataarr:{
type:Object //类型校验
}
},
data(){
return {
arr:[
"中国上市企业市值500强出炉 中公教育位居",
"中国上市企业市值500强出炉 中公教育位居",
"中国上市企业市值500强出炉 中公教育位居"
]
}
}
}
script>
<style>
style>
代码
父组件
<template>
<div>
{
{num}} <button @click="fn">修改numbutton>
<hr/>
<Myfoot :n="num">Myfoot>
div>
template>
<script>
import Myfoot from './components/Myfoot'
export default {
data(){
return {
num:25
}
},
components:{
Myfoot
},
methods:{
fn(){
console.log(this.num)
this.num++
}
}
}
script>
// css
<style>
style>
子组件
<template>
<div>
{
{n}}--{
{m}}
div>
template>
<script>
export default {
props:['n'],
data(){
return {
m:6
}
}
}
script>
1:父组件调用子组件时,给子组件自定义事件
//父组件
2:在父组件中的methods中定义自定义事件对应的函数
//父组件
methods:{
函数名(){}
}
3:在子组件中通过this.$emit(‘事件名’,参数)触发自定义事件
//子组件
this.$emit('事件名',参数)
代码
父组件
<template>
<div>
{
{m}}
<hr/>
<Child @abc="fn">Child>
div>
template>
<script>
import Child from './components/Child'
export default {
data(){
return {
m:""
}
},
components:{
Child
},
methods:{
fn(val){
//2:父组件中定义自定义事件对应的函数fn
console.log("wo 被触发了")
// val就是触发abc事件传递过来的参数
this.m=val;
}
}
}
script>
子组件
<template>
<div>
{
{msg}}
<button @click="change">触发abcbutton>
div>
template>
<script>
export default {
data(){
return {
msg:"子组件==成都"
}
},
created(){
// 3:触发自定义事件的
// this.$emit('事件名',参数)
// console.log(this)
// this.$emit('abc',this.msg)
},
methods:{
change(){
this.$emit('abc',this.msg)
}
}
}
script>
中央事件总线:eventbus
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6D9S7l4D-1611110597372)(F:\Web\vue\day05\参考\day05\非父子组件传值.png)]
需求:非父子组件A和B,从A组件向B组件传值
1:main.js中定义一个公共区域 (新的vue实例)
// 1:创建公共区域(新的vue实例)
var eventbus=new Vue();
// 2:公共区域挂载到Vue的原型上面(每一个vue实例都可以访问它原型上的成员)
Vue.prototype.$bus=eventbus;
2:在B组件中给公共区域自定义事件
<template>
<div>
{
{m}}
div>
template>
<script>
export default {
data(){
return {
m:"123"
}
},
created(){
// // console.log(this,111)
// var that=this;
// // 公共区域自定义事件--接收值
// this.$bus.$on('abc',function(v){
// console.log("我被触发了",v)
// console.log(this)
// that.m=v
// })
//--------------
// console.log(this,111)
// 公共区域自定义事件--接收值
this.$bus.$on('abc',(v)=>{
console.log("我被触发了",v)
console.log(this)
this.m=v
})
}
}
script>
3:在A组件中触发公共区域的自定义事件
<template>
<div>
<button @click="fn">传值button>
div>
template>
<script>
export default {
data(){
return {
msga:"a向b传值"
}
},
methods:{
fn(){
// 触发公共区域的自定义事件传值
this.$bus.$emit('abc',this.msga)
}
}
}
script>
父向子
子向父
非父子
ref 被用来给元素或子组件注册引用信息
获取到的是dom元素
可以获取或使用组件的所有数据和方法
利用v-for和ref获取一组数组
注意:
1:ref需要在dom渲染完成后才会有,使用的时候确保dom已经渲染完成,比如
mounted钩子函数中可以使用
2:ref如果是循环出来的,ref的值是一个数组,要拿到单个的ref只需要循环就可以了
代码
<template>
<div>
<h2 ref="myh2">中公成都校区在施工h2>
<input type="text" ref="myinput" />
<button @click="fn">获取h2button>
<ul>
<li ref="list" v-for="(item,index) in arr" :key="index">
{
{item}}
li>
ul>
<button @click="fn1">获取li元素button>
<Myref ref="myref">Myref>
<button @click="fn2">获取子组件button>
div>
template>
<script>
import Myref from './components/Myref'
export default {
data(){
return {
arr:['aaa','bbb','cccc']
}
},
methods:{
fn(){
// 所有的ref的注册信息都会注册到组件的$refs对象上
console.log(this.$refs)
console.log(this.$refs.myh2.innerHTML)
},
fn1(){
// ref注册到循环渲染的元素上,得到的是一个数组[li,li,li]
console.log(this.$refs.list[0].innerHTML)
},
fn2(){
console.log(this.$refs.myref.msg)
this.$refs.myref.msg="hello 晋老师"
}
},
components:{
Myref
}
}
script>
在index.html中,通过script标签直接引入外部链接
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>myvuetitle>
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js">script>
head>
<body>
<div id="app">div>
body>
html>
安装
cnpm install jquery -D
import $ from 'jquery'
//main.js
import $ from 'jquery'
Vue.prototype.$=$
//在每一个组件中使用
this.$("#box").hide()
插槽用于将所携带的内容,插入到指定的某个位置
父组件向子组件传html标签
使用
子组件
成都中公
我是成都学员-程序员
父组件
//msg数据在父组件中定义
{
{msg}}
代码
父组件
<template>
<div>
<Mychild>
<ul>
<li v-for="(item,index) in arr" :key="index">{
{item}}li>
ul>
Mychild>
<hr/>
<Mychild>
<p>{
{msg}}p>
Mychild>
div>
template>
<script>
import Mychild from './components/Mychild'
export default {
data(){
return {
msg:"我是p标签123",
arr:['aaa','bbb','ccc']
}
},
methods:{
},
components:{
Mychild
}
}
script>
子组件
成都中公
我是成都学员-程序员
}
# 4-2、具名插槽
- 代码
- 父组件
```html
我是cen要的内容
我是子组件的内容
```
- 子组件
```html
成都中公
我是成都学员-程序员
默认值
```
# 4-3、作用域插槽(难)
> 子组件做循环(循环的结构从父组件传来)或者某一部分他的dom结构应该由外部传递进来的时候,使用作用域插槽
>
> 使用作用域插槽,子组件会向父组件的作用域里传递数据,父组件使用插槽,要包含在template中
- 语法
v-bind:自定义prop名=“数据” //子组件中传值
{ {props.prop名}}
- 代码
父组件
```html
{
{props.msg}}---{
{props.tit}}
子组件
<template>
<div>
<slot name="one" :msg="msg" :tit="name">slot>
<slot name="two">slot>
div>
template>
<script>
export default {
data(){
return {
arr:[
'香蕉','苹果','西瓜'
],
msg:"nihao",
name:"张三"
}
}
}
script>
ol ul table他们的内部存放的标签是有约束的
代码
父组件
<template>
<div>
<table>
<tr is="Mytd">
tr>
table>
div>
template>
<script>
import Mychild from './components/Mychild'
import Mytd from './components/Mytd'
export default {
data(){
return {
}
},
methods:{
},
components:{
Mychild,
Mytd
}
}
script>
子组件
123
使用is属性渲染组件的内容
代码
<template>
<div>
<ul>
<li @click="fn('Catgory')">分类li>
<li @click="fn('Cart')">购物车li>
<li @click="fn('Mine')">我的li>
ul>
<div :is="com">
div>
div>
template>
<script>
import Catgory from './components/Catgory'
import Cart from './components/Cart'
import Mine from './components/Mine'
export default {
data(){
return {
com:'Catgory'
}
},
methods:{
fn(val){
this.com=val;
}
},
components:{
Catgory,
Cart,
Mine
}
}
script>
ref dom元素和子组件 this.$refs
vue中jquery的使用
外部链接 index.html script
npm
局部 import $ from ‘jquery’
全局
import $ from ‘jquery’
Vue.prototype. = = =
插槽 slot
is属性
SPA:single page application单页面应用,只有一个页面,不断切换内部展示的内容
路由:根据不同的url地址,映射不同的组件内容
1:安装vue-router
npm/cnpm i vue-router --save
2:配置路由 —main.js
import Vue from 'vue'
import App from './App.vue'
// 1:引入vue-router
import VueRouter from 'vue-router'
// 引入组件
import Index from './components/Index'
import Mya from './components/Mya'
// 2:给vue安装路由插件,让每一个组件中都可以使用router-link和router-view组件
Vue.use(VueRouter);
// /:3: 路由配置---路由映射关系
var routes=[
{
path:'/',
component:Index
},
{
path:'/mya',
component:Mya
}
]
// 4:实例化路由对象
var router=new VueRouter({routes:routes})
Vue.config.productionTip = false
new Vue({
el: '#app',
// 5:把路由对象注入到根实例中
// 在每一个组件中都可以使用this.$router和this.$route
router:router,
components: { App },
template: ' '
})
3:在组件中使用router-link 和router-view组件
关于我们
渲染成 关于我们
路由出口 网址上访问 /about router-view的位置上映射该路由对应的组件
1:src目录下新建router/index.js,index.js中写入如下代码
import Vue from 'vue'
// 1:引入vue-router
import VueRouter from 'vue-router'
// 2:给vue安装路由插件,让每一个组件中都可以使用router-link和router-view组件
Vue.use(VueRouter);
// 引入组件
import Index from '../components/Index'
import Mya from '../components/Mya'
import Myb from '../components/Myb'
// /:3: 路由配置---路由映射关系
var routes=[
{
path:'/',
component:Index
},
{
path:'/mya',
component:Mya
},
{
path:'/myb',
component:Myb
}
]
// 4:实例化路由对象
var router=new VueRouter({routes:routes})
// 导出router,vuerouter实例
export default router;
2:在main.js中导入router
// 把路由实例导入
import router from './router'
new Vue({
el: '#app',
// 5:把路由对象注入到根实例中
// 在每一个组件中都可以使用this.$router和this.$route
// router:router,
router,
components: { App },
template: ' '
})
3:组件中使用router-link和router-view组件即可
// /:3: 路由配置---路由映射关系
var routes=[
{
path:'/',
component:Index
},
{
path:'*', //*是所有的,上面没有匹配到就都渲染这里
// redirect:'/' //redirect重定向
// 还可以映射到到一个组件中404
component:Notfound
}
]
需要时再加载
//上面不需要再引入组件
var routes=[
{
path:'/',
component:()=>import('../components/Index')
},
{
path:'/mya',
component:()=>import('../components/Mya')
},
{
path:'/myb',
component:()=>import('../components/Myb')
},
{
path:'*', //*是所有的,上面没有匹配到就都渲染这里
// redirect:'/' //redirect重定向
// 还可以映射到到一个组件中404
component:()=>import('../components/Notfound')
}
]
声明式导航:html中的router-link组件实现页面跳转
编程式导航:通过js代码实现页面跳转
向history中添加记录
this.$router.push('/mya')
this.$router.push({path:'/mya'})
this.$router.push({path:'prodetail',query:{id:1}}) //只能是query数据
this.$router.push({name:'detail',params:{newsid:2}}) //对应params数据
不会向history中添加记录
this.$router.replace('/mya')
历史记录的前进及后退
this.$router.go(-1) //后退
this.$router.go(1) //前进
代码
index.vue
<template>
<div>
index
<button @click="fn">
跳转到mya
button>
div>
template>
<script>
export default {
methods:{
fn(){
// 跳转到mya
// 会添加到history中,router-link也会添加
console.log(this.$router)
// this.$router.push('/mya')
this.$router.push({
path:'/mya'})
// 不会添加到history中
// this.$router.replace('/myb')
}
}
}
script>
mya.vue
http://www.abc.com/newsdetial/102
newsdetial:表示新闻详情路由
102 表示新闻id
那么怎么配置这样的路由呢?
路由规则页面
var routes=[
{
path:'/detail/:newsid', // 匹配detail/5
component:()=>import('../components/Detail')
}
]
从某组件中跳转到Detail组件中
Detail.vue组件中获取动态参数
this.$route.params.newsid
代码
index.vue
index
-
{
{item.title}}
Detail.vue
detail
{
{obj.title}}
路由中传递 参数除了刚才的params外,还可以使用query数据
http://www.xx.com/p?id=8
路由规则页面
var routes=[
{
path:'/prodetail', // 匹配 prodetail
component:()=>import('../components/Prodetail')
}
]
从某组件中跳转到Prodetail组件中
Prodetail.vue组件中获取路由参数
this.$route.query.id
代码
index.vue
-
{
{item.title}}
Prodetail.vue
prodetail
面试题
r o u t e r 和 router和 router和route的区别?
route这里存储的是属性,比如route.query、route.params
router这里存储的是方法,比如router.push()、router.replace()、router.go(-1)
路由配置
var routes=[
{
path:'/myb',
component:()=>import('../components/Myb'),
children:[
{
path:'/myb/aa',
component:()=>import('../components/Myaa'),
},
{
path:'/myb/bb',
component:()=>import('../components/Mybb'),
}
]
},
]
Myb组件中
给谁设置二级路由,就在他的组件里写router-link和router-view
aa
bb
hash模式 # 默认模式
history模式
var router=new VueRouter(
{routes,
mode:'history'
}
)
路由规则
var routes=[
{
path:'/mya',
name:'minea', //命名路由
component:()=>import('../components/Mya')
}
]
路由跳转
//1种
xxxxxx
//2种
Mya
//3种
this.$router.push({name:'detail',params:{newsid:2}})
一个组件里有多个router-view时,我们要给router-view定义name属性
router-view添加name ,Myb组件
aa
bb
路由规则
var routes=[
{
path:'/myb',
component:()=>import('../components/Myb'),
children:[
{
path:'/myb/aa',
// component:()=>import('../components/Myaa'),
components:{
default:()=>import('../components/Myaa'),
a:()=>import('../components/Login'),
b:()=>import('../components/Mya')
}
},
{
path:'/myb/bb',
component:()=>import('../components/Mybb'),
}
]
}
]
https://router.vuejs.org/zh/guide/advanced/navigation-guards.html#组件内的守卫
vue-router
提供的导航守卫主要用来通过跳转或取消的方式守卫导航
守卫的所有的路由—进入每一个路由之前执行
to:即将要进入的目标 路由对象
from:当前导航正要离开的路由
next 一定要调用该方法来 resolve 这个钩子 进入导航
next()
next(false)
next('/login')
main.js中实现(还可以把该全局守卫放到router/index.js文件中)
import router from './router'
router.beforeEach((to, from, next) => {
//商城项目进入购物车页面要先进行判断 ,登录成功next()登录不成功next('/login')
//
console.log(to)
// console.log(to.path,to.name);
if(to.path=='/mine'){
next('/login')
}else{
next()
}
// next()
})
你可以在路由配置上直接定义 beforeEnter
守卫:
写在那个路由上,守卫的就是那个路由
var routes=[
{
path:'/mine',
component:()=>import('../components/view/Mine'),
beforeEnter(to,from,next){
// console.log(to)
next();
}
}
]
beforeRouteEnter
beforeRouteUpdate
(2.2 新增)beforeRouteLeave
解决的复杂组件之间的数据通信问题
vuex是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间的数据共享,它采用集中式存储管理应用的所有组件的状态,
1:安装vuex的依赖包
cnpm install vuex --save
2:导入vuex包(src目录下新建store目录,store目录下新建index.js文件)
3:创建store对象
//index.js
import Vue from 'vue'
//1: 导入vuex包
import Vuex from 'vuex'
Vue.use(Vuex)
// 2创建store对象
export default new Vuex.Store({
})
将store对象挂载到vue实例中
import store from './store'
new Vue({
el: '#app',
store,
components: { App },
template: ' '
})
state提供唯一的公共数据源,所有共享的数据都要统一放到Store的state中进行存储
export default new Vuex.Store({
//store数据源,提供唯一公共数据
state:{
count:20
}
})
组件访问state中数据的第一种方式
this.$store.state.全局数据名称
//代码
count的值是{
{$store.state.count}}
组件访问state中数据的第二种方式
// 1:从vuex中按需导入mapState函数
import {mapState} from 'vuex'
computed:{
// 2将全局数据,映射为当前组件的计算属性
...mapState(['count'])
}
//代码
{
{count}}
mutation用于变更store中的数据
定义mutation
export default new Vuex.Store({
state:{
count:20
},
mutations:{ //定义mutation 变更store中的数据
add(state){
//变更状态
state.count++;
}
}
})
组件中触发mutation中的方法(第一种)
//this.$store.commit('mutation中的方法')
this.$store.commit('add')
//代码
count的值是{
{$store.state.count}}
组件中触发mutation中的方法(第二种)
// 1:从vuex中按需导入mapMutations函数
import {mapMutations} from 'vuex'
//2:将指定的mutations函数,映射为当前组件的methods函数
methods:{
//将指定的mutations函数,映射为当前组件的methods函数
...mapMutations(['add'])
}
//代码
{
{count}}
触发mutations时传递参数
定义传参的mutation
export default new Vuex.Store({
state:{
count:20
},
mutations:{ //变更store中的数据 step形参
addN(state,step){
state.count +=step
}
}
})
组件中调用并传参(第一种)
//传递多个值用对象传递
this.$store.commit('addN',实参)
//代码
count的值是{
{$store.state.count}}
组件中调用并传参(第二种)
//代码
{
{count}}
action用于处理异步任务,和逻辑操作
如果通过异步操作或者执行逻辑操作变更数据,必须通过action,而不能使用mutation,但是在action中还是通过触发mutation的方式间接变更数据
定义action
const store=new Vuex.Store({
state:{},
mutations:{},
actions:{
addAsync(context){
setTimeout(()=>{
//在actions中,不能直接修改state中的数据
//必须通过context.commit()触发某个mutation才行
context.commit('add')
},1000)
}
}
})
//代码
import Vue from 'vue'
//1: 导入vuex包
import Vuex from 'vuex'
Vue.use(Vuex)
// 2创建store对象
export default new Vuex.Store({
//store数据源,提供唯一公共数据
state:{
count:20
},
mutations:{ //变更store中的数据
// 只有mutation中定义的函数,才有权利修改state中的数据
add(state){
state.count++;
// 不要在mutations函数中执行异步操作
// setTimeout(()=>{
// state.count++;
// },1000)
},
addN(state,step){
state.count +=step
}
} ,
actions:{
addAsync(context){
setTimeout(()=>{
//在actions中,不能直接修改state中的数据
//必须通过context.commit()触发某个mutation才行
context.commit('add')
},1000)
}
}
})
组件中访问action中的函数(第一种)
this.$store.dispatch('函数名')
//代码
count的值是{
{$store.state.count}}
组件中访问action中的函数(第二种)
// 1:从vuex中按需导入mapActions函数
import {mapState,mapMutations,mapActions} from 'vuex'
//将指定的actions函数,映射为当前组件的methods函数
methods:{
...mapActions(['addAsync'])
}
//代码
{
{count}}
触发action异步任务时携带参数
定义action
const store=new Vuex.Store({
state:{},
mutations:{},
addNAsync(context,step){
setTimeout(()=>{
//在actions中,不能直接修改state中的数据
//必须通过context.commit()触发某个mutation才行
context.commit('addN',step)
},1000)
}
})
//代码
import Vue from 'vue'
//1: 导入vuex包
import Vuex from 'vuex'
Vue.use(Vuex)
// 2创建store对象
export default new Vuex.Store({
//store数据源,提供唯一公共数据
state:{
count:20
},
mutations:{ //变更store中的数据
// 只有mutation中定义的函数,才有权利修改state中的数据
add(state){
state.count++;
// 不要在mutations函数中执行异步操作
// setTimeout(()=>{
// state.count++;
// },1000)
},
addN(state,step){
state.count +=step
}
} ,
actions:{
addAsync(context){
setTimeout(()=>{
//在actions中,不能直接修改state中的数据
//必须通过context.commit()触发某个mutation才行
context.commit('add')
},1000)
},
addNAsync(context,step){
setTimeout(()=>{
//在actions中,不能直接修改state中的数据
//必须通过context.commit()触发某个mutation才行
context.commit('addN',step)
},1000)
}
}
})
组件中访问action中的函数(第一种)
count的值是{
{$store.state.count}}
组件中访问action中的函数(第2种)
{
{count}}
getter用于对store中的数据进行加工处理形成新的数据,类似于vue中的计算属性
store中数据发生变化,getter的数据也会跟着变化
定义getter
export default new Vuex.Store({
getters:{
getcount:state=>{
return '当前最新的数量是【'+ state.count +'】';
}
}
})
使用getters的第一种方式
this.$store.getters.名称
代码
count的值是{
{$store.state.count}}
{
{$store.getters.getcount}}
使用getters的第二种方式
import {mapGetters} from 'vuex'
computed:{
...mapGetters(['名称'])
}
代码
{
{count}}---{
{getcount}}
安装
cnpm install axios -S
引入
//每个组件里单独引入
import axios from axios
get方法
语法:
axios.get(请求地址,配置对象).then(res=>{
}).catch(err=>{
})
//不传参数
axios.get('url')
.then(res=>{
})
.catch(err=>{
})
//传参数 第一种
axios.get('url?id=5&name=张三')
.then(res=>{
})
.catch(err=>{
})
//传参数 第二种
axios.get('url',
{
params:{
参数1:值,
参数2:值
}
})
.then(res=>{
})
.catch(err=>{
})
代码
<template>
<div>
<li v-for="item in arr" :key="item.id">{
{item.title}}li>
div>
template>
<script>
import axios from 'axios'
export default {
data(){
return {
arr:[]
}
},
created(){
// console.log(axios);
// axios.get('http://localhost:4000/arr')
// .then(res=>{
// console.log(res.data);
// })
// axios.get('http://localhost:4000/arr?id=2')
// .then(res=>{
// console.log(res.data);
// })
axios.get('http://localhost:4000/arr',{
params:{
id:2
}
})
.then(res=>{
console.log(res.data);
this.arr=res.data;
})
}
}
script>
post方法
语法:
axios.post(url[,数据[,配置项]])
axios.post('/user')
.then((res) =>{
console.log(response);
})
.catch((error)=> {
console.log(error);
});
axios.post('/user', {
参数1: 值,
参数2: 值
})
.then((res) =>{
console.log(response);
})
.catch((error)=> {
console.log(error);
});
代码
<template>
<div>
<li v-for="item in arr" :key="item.id">{
{item.title}}li>
<button @click="get">get请求button>
<button @click="post">post请求button>
div>
template>
<script>
import axios from 'axios'
export default {
data(){
return {
arr:[],
tit:"成都it"
}
},
methods:{
get(){
//get请求
// console.log(axios);
// 不传参数
// axios.get('http://localhost:4000/arr')
// .then(res=>{
// console.log(res.data);
// })
// 传参 第一种
// axios.get('http://localhost:4000/arr?id=2')
// .then(res=>{
// console.log(res.data);
// })
// 传参 第二种
axios.get('http://localhost:4000/arr',{
params:{
id:2
}
})
.then(res=>{
console.log(res.data);
this.arr=res.data;
})
},
post(){
//post请求
// axios.post(url[,数据[,配置项]])
// axios.post('http://localhost:4000/arr')
// .then(res=>{
// console.log(res.data);
// })
// .catch(err=>{
// console.log(err);
// })
axios.post('http://localhost:4000/arr',{
title:this.tit
})
.then(res=>{
console.log(res.data);
})
.catch(err=>{
console.log(err);
})
}
}
}
script>
all方法
可以实现发送多次请求,请求成功之后再做处理
在项目开发中,一个页面的数据需要请求多个接口地址,那我们就执行多并发请求
语法
// 执行多并发请求
// axios.all([函数1(),函数2(),函数3()]) 一个函数返回一个结果,多个函数返回多个结果
// axios.spread((结果1,结果2,结果3)=>{}) 去获取每个函数返回的结果
// 语法:
axios.all([函数1(),函数2(),函数3()])
.then(
axios.spread((结果1,结果2,结果3)=>{
})
)
代码
- {
{item.title}}
可以通过向 axios
传递相关配置来创建请求
axios({配置对象})
axios({
url:"地址",
method: 'post', //请求方式
data: { //传递的参数
参数1: 值,
参数2: 值
}
})
.then(res=>{ //res是axios返回的请求对象 res.data才是后端返回的数据
})
.catch(err=>{
console.log(err)
})
create方法不是用来请求数据的,而是用来创建一个axios实例对象,定义一些初始化配置
语法
let $axios=axios.create({配置对象})
let $axios=axios.create({
baseURL:'http://xxxx.com/aaa',
timeout:3000 //请求时长
})
$axios.get('/getuser',{
params:{
参数1:值
}
})
.then(res=>{})
.catch(err=>{})
拦截器 :发送请求之前做一些事情,返回数据之前做一些事情
使用
// 请求拦截器 修改请求头 【在请求头上加token】
$axios.interceptors.request.use(function (config) {
console.log(55555)
// 请求发送之前做一些事情
return config; //一定要return config 请求无法发送
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
// 响应拦截器 返回数据的校验 状态是否正确 信息的提取
$axios.interceptors.response.use(function (response) {
// 对响应数据做点什么
return response;
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error);
});
1:src目录下面新建http目录,目录下新建index.js文件
import axios from 'axios'
//初始化配置
const $axios=axios.create({
baseURL:'http://localhost:4000',
timeout:3000
})
// 请求拦截器 修改请求头 【在请求头上加token】
$axios.interceptors.request.use(function (config) {
// 请求发送之前做一些事情
return config; //一定要return config 请求无法发送
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
// 响应拦截器 返回数据的校验 状态是否正确 信息的提取
$axios.interceptors.response.use(function (response) {
// 对响应数据做点什么
return response;
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error);
});
export default $axios;
2:main.js文件中引入
import $axios from './http'
Vue.prototype.$axios=$axios
3:每一个组件中使用
this.$axios.get(url).then(res=>{})
this.$axios.post(url).then(res=>{})
//this.$axios没有all方法 要使用all方法需要 axios.all
安装
npm install json-server -g
新建一个文件夹myjson,在该文件夹下面新建data.json文件
{
"arr":[
{
"id":1,
"title":"111111111"
},
{
"id":2,
"title":"222222"
},
{
"id":3,
"title":"33333333"
}
],
"user":[
{
"id":1,
"name":"张三"
}
]
}
执行命令行
json-server -w data.json -p 4000
跨域问题:因为浏览器的同源策略,不能访问其他网站的资源
同源策略:协议相同,域名相同,端口号相同
解决方法:
vue里面如何解决跨域问题—webpack配置跨域代理 —生产环境不存在
config文件下面的index.js 中找 proxyTable
proxyTable: { // 【设置代理!!!】
'/api': { //使用"/地址名"来代替"请求网址"
target: 'http://localhost:3000/', //源地址
changeOrigin: true, //改变源
pathRewrite: { // 路径重写
'^/api': '' // 当请求的路径开头有 /地址名 的时候就替换成请求网址
}
}
组件中请求要修改链接
axios.get('/api/xxx/yyy').then(res=>{})
1:找个地方不是vue项目目录中 ,解压umall-api.zip
2:解压之后,umall-api目录中打开命令窗口 cnpm install
3:打开Navcat软件,新建数据库 shop_db ,然后把shop_db有数据.sql导入到数据库中
4:打开项目目录下的config/global.js文件,修改
exports.dbConfig = {
host: 'localhost', //数据库地址
user: 'root',//数据库用户名
password: '你的密码',//数据库用户密码
port: 3306,
database: 'shop_db' // 数据库名字
}
启动项目
npm start
网址上打开http://localhost:8080/出现空白
var routes=[
{
path:'/',
component:()=>import('../components/Home'),
redirect:'/index', //添加这一句 重定向
children:[]
}
]
Access to XMLHttpRequest at ‘http://localhost:3000/api/getcate’ from origin ‘http://localhost:8080’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
出现跨域问题
轻量、可靠的移动端 Vue 组件库
安装
cnpm i vant -S
引入 main.js
import Vant from 'vant';
import 'vant/lib/index.css';
Vue.use(Vant);
使用
http目录下新建api.js文件
// 存放所有的接口地址
export default {
baseUrl:'http://localhost:3000', //接口网址
cateUrl:'/api/getcate', //获取分类信息(首页)
bannerUrl:'/api/getbanner', //获取轮播图信息(首页)
seckillUrl:'/api/getseckill', //获取限时秒杀信息(首页)
indexgoodUrl: '/api/getindexgoods' //获取商品信息(首页)
}
main.js中引入,让每一个组件都可以直接使用
imprt $api from './http/api'
Vue.prototype.$api=$api
在组件中使用
this.$api.名称
1:已经登录成功
2:登录成功用户信息保存到本地
login.vue
methods:{
login(){
this.$axios.post(this.$api.loginUrl,{
phone:this.phone,
password:this.password
})
.then(res=>{
if(res.data.code===200){
// 登录成功,登录信息存储在本地的localStorage
// localStorage中只能存储字符串 永久存储 除非手动删除 userInfo自定义的
localStorage.setItem('userInfo',JSON.stringify(res.data.list))
this.$router.push('/mine');
}else{
Toast.fail(res.data.msg);
}
this.phone="";
this.password="";
})
}
:3:在购物车和我的路由添加自定义meta字段,来记录页面是否需要身份验证
var routes=[
{
path:'/cart',
// 元信息 记录进入该页面是否需要身份验证
meta:{reqiresAuth:true},
component:()=>import('../components/view/Cart'),
},
{
path:'/mine',
meta:{reqiresAuth:true},
component:()=>import('../components/view/Mine')
}
]
4:路由拦截
// 全局守卫--守卫的是所有的路由--进入每一个路由之前执行
router.beforeEach((to, from, next) => {
// 设置路由拦截
// $route.matched 一个数组,包含当前路由的所有嵌套路径片段的路由记录
// to.matched数组中包含$route对象的检查元信息
// arr.some()判断该数组是否有元信息,返回布尔值
// 判断哪些路由有元信息
if(to.matched.some(record=>record.meta.reqiresAuth)){
//需要登录身份验证的执行这里
// 判断是否登录
if(localStorage.getItem("userInfo")){
next()
}else{
next('/login')
}
}else{
// 不需要登录身份验证的执行这里
next()
}
})
5:设置请求拦截和响应拦截
import axios from 'axios'
import router from '../router'
import {Toast} from 'Vant'
// 创建了axios的实例--初始化配置---每次请求都会先执行这里
// 每次请求会把baseURL放到请求的url的前面-前提是使用$axios请求,axios请求不会执行这个文件
const $axios=axios.create({
baseURL:'/api', ///api此处的api是跨域里的替换的地址
timeout:3000
})
// 请求拦截器 修改请求头 【在请求头上加token】
$axios.interceptors.request.use(function (config) {
// console.log(config,"config")
// 请求发送之前做一些事情
var userInfo=JSON.parse(localStorage.getItem('userInfo'))
// 修改请求头,添加token
// 每一个请求都会加token
config.headers.Authorization=userInfo?userInfo.token:"";
return config; //一定要return config 请求无法发送
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
// 响应拦截器 返回数据的校验 状态是否正确 信息的提取
$axios.interceptors.response.use(function (response) {
// 对响应数据做点什么
// token过期我们拦截,跳转到登录页面
if(response.data.code==403){
Toast.fail(response.data.msg)
// router.push('/login')
}
return response;
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error);
});
export default $axios;
请求数据
export default {
data(){
return {
cartlist:[]
}
},
created(){
var uid=JSON.parse(localStorage.getItem('userInfo')).uid
this.$axios.get(this.$api.cartlistUrl+"?uid="+uid)
.then(res=>{
// console.log(res);
this.cartlist=res.data.list.map(item=>{
item.checked=false;
return item;
})
})
}
}
页面展示
-
欧莱雅面霜
规格:50g
¥123.00
-
+
删除
什么是token:
Token是在客户端频繁向服务端请求数据,服务端频繁的去数据库查询用户名和密码并进行对比,判断用户名和密码是否正确,并作出相应的提示,这时就有了token
token的定义
token是服务端生成的一串字符串,来作为客户端进行请求的一个令牌,当第一次登陆后服务端生成一个token然后将token返回给客户端,以后客户端只需要带着这个token去请求数据就可以了,不需要再次带上用户名和密码
使用token的目的
减轻服务器的压力,减少了频繁的查询数据库
工作原理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UD3K0kML-1611110597377)(F:\Web\vue\day09\参考\day09./token.png)]
1:准备详情页
2:配置详情页的路由
3:首页 实现产品跳转
-
{
{item.goodsname}}
¥
{
{item.price.toFixed(2)}}
已售800件
立即抢购
4:详情页中接收数据并展示
export default {
data(){
return {
proobj:null,
num:1
}
},
created(){
// 1获取url网址上的id值
let id=this.$route.params.id;
// console.log(id);
// 2 根据id去服务端请求数据
this.$axios.get(this.$api.goodsinfoUrl,{
params:{
id
}
})
.then(res=>{
console.log(res.data.list[0]);
if(res.data.code==200){
if(res.data.list.length>0){
this.proobj=res.data.list[0];
}
}
})
}
}
5:加入购物车
1:添加点击事件
2:实现添加到数据库的功能
methods:{
addcart(){
// 1获取需要传递的数据
const data={
uid:JSON.parse(localStorage.getItem('userInfo')).uid , //当前登录用户的uid
goodsid:this.$route.params.id,
num:this.num
}
// console.log(data)
// 2通过请求加入到数据库
this.$axios.post(this.$api.cartaddUrl,data)
.then(res=>{
if(res.data.code==200){
Toast.success('加入购物车成功');
}
})
}
}
饿了么提供的基于 Vue 2.0 的桌面端组件库(mintui移动端)
安装
npm i element-ui -S
引入main.js
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)
使用
登录页
首页
管理员列表
添加
启用
禁用
编辑
删除
1:下载
cnpm install wangeditor --save
2:组件中使用
import E from 'wangeditor'
data(){
return {
editor:null
}
}
mounted(){
this.editor = new E("#desc");
this.editor.create();
}
//添加内容
this.editor.txt.html(this.info.description);
//获取内容
this.editor.txt.html();
1:设置路由
2:实现下面的代码
首页
{
{item.title}}
{
{val.title}}
首页
菜单列表
菜单{
{tip}}
顶级分类
{
{tip}}
首页
商品分类列表
商品分类{
{ tip }}
请选择
{
{ item.catename }}
请选择
{
{ item.catename }}
请选择
{
{ item.specsname }}
请选择
{
{ item }}
添加
添加
vua 项目中执行命令:
npm run build
根目录下面生成一个dist目录
把dist目录交给后端,但是这一次我们把dist目录复制到接口目录下,打开app.js文件
app.use(express.static('dist'))
浏览器打开http://localhost:3000/login就可以访问项目了
npm uninstall vue-cli -g
安装
npm install @vue/cli -g
查看版本
vue -V
or
vue --version
vue create 项目名
启动项目
yarn serve
在vue的项目根目录下新建vue.config.js文件(一定是vue.config.js)
module.exports={
devServer:{
proxy:{
'/api': { //使用"/地址名"来代替"请求网址"
target: 'http://localhost:3000/', //源地址
changeOrigin: true, //改变源
pathRewrite: { // 路径重写
'^/api': '' // 当请求的路径开头有 /地址名 的时候就替换成请求网址
}
}
}
}
}
文本格式化—内容显示
局部定义
new Vue({
filters:{ //局部定义过滤器 val
名字:function(val){
return val+"111"
}
},
showprice(val,zk){
if(!val){
return;
}
return val*zk/10;
}
})
//定义过滤器可以传其他参数
使用过滤器
{
{ price | 过滤器的名字 }} //price 作为过滤器的第一个参数
{
{ price | 过滤器的名字(第二个参数) }}
全局定义
main.js中定义
// Vue.filter(过滤器的名字,()=>{
// })
Vue.filter('isTrue',function(val){
if(val==1){
return true
}else{
return false;
}
})
组件中使用
{
{ price | 过滤器的名字 }} //price 作为过滤器的第一个参数
filters的封装
1:src目录下新建filters/index.js文件
const isNullOrEmpty=function(val){
if(val==null || val=="" ||typeof(val)==undefined){
return "hello"
}else{
return "nihao"
}
}
const isTrue=function(val){
if(val==1){
return true
}else{
return false;
}
}
export {
isTrue,
isNullOrEmpty
}
2:main.js文件中导入
import * as filters from './filters'
//Object.keys把有键值对的对象转换为数组
Object.keys(filters).forEach(key=>{
console.log(key)
Vue.filter(key,filters[key])
})
3:组件中直接使用过滤器
{
{name | isNullOrEmpty}}
vue create 项目名称 //初始化项目
//1:选择手动配置还是默认配置
default 默认配置
Manually select features 手动配置
//2:我们选择手动配置
?Please pick a preset:Manually select features
?CHeck the features needed for your project
(*)Babel
( )TypeScript
( )Progressive Web App ( PWA) Support
(*)Router
(*)Vuex
(*)CSS Pre-processors
(*)Linter / Formatter
( )Unit Testing
( )E2E Testing
//3:选择vue的版本
Choose a version of Vue.js that you want to start the project with
启动项目
npm run serve
or
yarn serve
https://stylus.bootcss.com/
富于表现力、动态的、健壮的 CSS预处理器
1:下载
cnpm install stylus -dev--save
cnpm install stylus-loader -dev--save
2:使用
3:语法
.box
width 100px
height 100px
background red
// 变量
fontSize=30px
$bgColor=pink
body
font-size fontSize
background-color $bgColor
// 函数
fonts(){
border:2px solid
font-weight bold
width 100px
height 100px
}
.small
fonts()
border 2px solid
background blue
// 选择器
// textarea
// input
// color blue
// background-color red
textarea
input
color blue
&:hover
color red
// 插值
vendor(prop,args)
-webkit-{prop} args
-moz-{prop} args
{prop} args
border-radius()
vendor('border-radius',arguments)
border-shadow()
vendor('border-shadow',arguments)
.small
border-radius 10px
世界上最成熟、最稳定、最强大的专业级CSS扩展语言!
下载
cnpm install node-sass --save-dev
cnpm install sass-loader --save-dev
使用
语法
// .box{
// width: 200px;
// height:200px;
// background: pink;
// >a{
// text-decoration: none;
// }
// }
.box{
width: 200px;
height:200px;
background: pink;
a{
text-decoration: none;
span{
}
}
&:hover{
background: red;
}
}
https://cn.vuejs.org/v2/guide/transitions.html
vue中动画的使用场景:
transition组件
transition组件有个name属性,name属性就是动画名称,name值是自定义
在进入/离开的过渡中,会有 6 个 class 切换。
【从隐藏到显示】
动画名-enter 进入前
动画名-enter-active 进入中
动画名-enter-to 进入后
【从显示到隐藏】
动画名-leave 离开前
动画名-leave-active 离开中
动画名-leave-to 离开后
https://cdn.jsdelivr.net/npm/[email protected] 浏览器打开下载animate.css
https://animate.style/#documentation 查找有哪些动画
//引入animate.css
// main.js中引入 ---每一个组件都可以使用
// 单独的组件中引入
transtion 只能有0个或1个子节点
transtion-group可以有0个或多个子节点
-
{
{item}}
1)Typescript不是新的语言,是JavaScript语言的超集
2)Typescript是由微软开发的开源编程语言,增加了非常有用的编译时类型检查特性*,最终被编译成JavaScript来执行
2)增加了代码的可读性和可维护性,开发大型项目
3)如果不显示定义类型,能够自动做出类型推论
4)Typescript拥有活跃的社区
缺点:增加学习成本 增加了设定类型的开发时间
ts的学习,学习的是语法,好多的语法,es5,es6…已经学过了
ts文件可以直接引入的
<script src="index.ts" ></script>
环境安装
ts的很多语法浏览器是不支持,安装环境,将ts进行编译,编译成浏览器可以执行的js
安装·
npm install -g typescript
检测是否安装成功
tsc -v //可以查看到版本说明安装成功
编译文件
tsc xxx.ts //同级目录下生成一个同名的js文件
tsc --outDir ./js xxx.ts //把ts文件编译到指定的目录
自动编译 tsconfig.json
ts --init //生成tsconfig.json配置文件
“outDir”:‘出口文件名’ 出口文件设置
“rootDir”:“入口文件名” 入口文件设置
修改tsconfig.json,配合tsc -w 实时热更新
ts类型是非常严格的,定义了什么类型就必须是什么类型
let b=10; //正确 规定b是数值类型
b="123" //Type '"123"' is not assignable to type 'number'.2 b="123"
语法:
let 变量名:数据类型; //声明变量并指定数据类型,给变量赋值必须是指定的该数据类型
let 变量名:数据类型= 值;
代码:
let num:number;
num=58;
// num="str" 错误的
let n:number=45;
console.log(n)
在typescript中给我们提供了以下数据类型
/**
* 字符串
*/
let str:string;
str="123"
let str1:string="78";
/**
* number 数值
*/
let n:number;
n=12;
let n2:number=23;
console.log(n2)
/**
* 布尔 boolean
*/
let bool:boolean;
bool=true;
null和undefined
/*
null和undefined是所有类型的子类型
undefined表示未定义的值
null代表空 一个对象被人为的定义为空对象
*/
let tmp:undefined;
tmp=undefined;
// let tmp1:number=undefined; //错误的
let tmp2:null=null;
// tmp2={} 报错
数组类型(array)
/**
*数组
const arr=[1,"25",true]
const arr1=new Array()
*/
// ts中有两种方式定义数组 ---数组中每一个数据的元素类型指定什么类型就只能是什么类型
// 1--在元素类型后面加上[]--
const arr:string[]=["1","5"];
// arr[0]="45";
// arr[1]='true';
// console.log(arr)
// 2---使用数组泛型 Array<元素类型>
const arr1:Array<number>=[25,36];
let arr2:Array<boolean>;
arr2=[true,false]
any类型
/**
* any任意类型 可以是任何数据类型
*/
let a:any;
a=5;
a="123";
a=true;
const arr5:any[]=[45,"bugai",true];
const arr6:Array<any>=[45,"123"]
console.log(arr5,arr6)
元组类型(tuple)
/**
* 元组类型 表示一个已知元素数量和类型的数组,各元素的类型不必相同
*
* 语法:const 变量名:[类型1,类型2,类型3]=[14,"1ew",true]
* 注意:前面有几个类型 后面就只能有几个值
* 每一对类型和值必须一一对应
*/
// let arr7:[string,boolean,number,string]=[];//错误[]没有值,数量不统一
let arr7:[string,boolean,number,string]=["hello",true,25,"58"];
枚举类型(enum)
/**
* 枚举类型
* 我们的值只会出现在一定范围中
* 性别: 男 女 保密
* 状态: 成功 失败
* 请求方式 : get,post,delete...
*
* 语法:
* enum 枚举名 {标记名1,标记名2,标记名3}
* 默认 0 1 2
* enum 枚举名 {标记名1=值,标记名2=值,标记名3=值}
*
* 使用
* let 变量:枚举名=枚举名.标记名
*
*/
enum Sex {
man,women}
let s:Sex=Sex.women
console.log(s)
enum Status {
success=200,err=400}
let result:Status=Status.success
console.log(result)
void类型
/**
*
* void 没有任何类型 主要指的是函数没有返回值
*/
function fn():void{
console.log(1)
}
fn()
never类型
/**
* never 类型 异常
*/
function fn2(): never {
throw new Error()
}
类型断言
/**
* 类型断言:告诉编译器你比它更了解这个类型,并且它不应该发出错误,就是告诉不要去
* 对这个值进行类型检查
*
*/
function fn3(x:any):any{
if(typeof x==='string'){
// return (x).length
return (x as string).length
}
}
/****为函数定义类型
* 1:参数类型定义
* 2:返回值类型定义
* 第一种:
* function 函数名(参数:数据类型):返回值数据类型{
* return 值; //值的类型必须和返回值的数据类型一致
* }
* 第二种:
* let 函数名=function(参数:数据类型):返回值数据类型{
*
* }
* void 函数没有返回值
*/
function show(num:number):void{
console.log(num)
}
show(24)
function show1(x:string,y:string):string{
return x+y;
}
console.log(show1("中公","优就业"))
let show2=function (x:number,y:string):void{
console.log(x+y)
}
show2(14,"it")
let show3=function():string{
return "web前端"
}
console.log(show3())
/**可选参数
* js中参数是可选的 不传时候值为undefined
* ts 可选参数使用 ? 定义
* 注意:ts中没有配置可选参数,你不传值 就会报错
*/
function get(x:string,y?:number):string{
return x+y;
}
console.log(get("中公",520))
console.log(get("中公"))
/******默认参数 末尾的参数才能设置默认参数 */
function getd(x:number,y:number=25):number{
return x+y;
}
console.log(getd(12,23))
console.log(getd(12))
/****剩余参数
*
* 你想同时操作多个参数,或者你并不知道会有多少参数传递进来
*/
function get1(...data:any[]){
console.log(data)
}
// get1(1,2,3,true)
// get1(1)
// 剩余参数要放在尾部
function get2(x:number,...data:any[]){
console.log(data)
}
get2(25,"123","aaa","bbb")
装饰器是对类,函数,属性的一种装饰,可以针对其添加一些额外的行为
通俗点理解就是在原有代码的外层包装了一层处理器
装饰器其实就是一个函数
启用装饰器特性,需要在tsconfig.json
里启用experimentalDecorators
编译器选项
"experimentalDecorators": true,
装饰器就是在调用某个方法,某个属性,某个类,某个参数之前执行一段函数,
定义装饰器
function 装饰器名(target){
} //不能传参数
function 装饰器名(参数:类型){
return function(target){
}
}
function 装饰器名(target){
}
@装饰器名
class 类名{
} //该类被实例化的时候装饰器函数就会被调用
代码
function add(target:any){
console.log(target,"target")
target.prototype.num=12;
}
@add //后面不能加任何符号
class Stu{
constructor(){
console.log("构造函数")
}
}
let s1=new Stu()
console.log(s1)
可以传参的装饰器
function add(num:number){
return function(target:any){
//return 的函数才是真正的装饰器
console.log(target,"target")
}
}
@add(15) //后面不能加任何符号
class Stu{
constructor(){
console.log("构造函数")
}
}
let s1=new Stu()
console.log(s1)
function 装饰器名(类的原型对象,方法名,方法属性描述){
}
class 类名{
@装饰器名
方法名(){
}
}
function add(target:any,name:any,desc:any){
console.log(target,"target")
console.log(name,"方法名")
console.log(desc,"属性描述")
}
class Stu{
@add //后面不能加任何符号
run(){
console.log("nihao")
}
}
let s1=new Stu()
console.log(s1)
function 装饰器名(类的原型对象,属性名){
}
class 类名{
@装饰器名
public 属性名
}
function add(target:any,propertyKey:any){
console.log(target,"target")
console.log(propertyKey)
}
class Stu{
@add //后面不能加任何符号
public name:string;
constructor(n:string){
this.name=n;
}
}
let s1=new Stu("zhans")
console.log(s1)
function required(target:any, propertyKey: string, parameterIndex: number){
console.log(target) //类的原型对象
console.log(propertyKey) //方法名
console.log(parameterIndex) //参数的索引位置
}
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet(@required name: string) {
return "Hello " + name + ", " + this.greeting;
}
}
npm uninstall vue-cli -g
安装
npm install @vue/cli -g
查看版本
vue -V
or
vue --version
vue create 项目名
启动项目
yarn serve
vue-property-decorator 是vue社区提出的一个对vue使用class类方式开发的一个重要包
<template>
<div>
about
</div>
</template>
<script lang="ts">
// lang="ts"表示使用ts语法
// 引入类装饰器
import {
Component ,Vue} from 'vue-property-decorator'
@Component({
})
// 使用class方式创建类
export default class About extends Vue{
}
</script>
<style lang="stylus">
</style>
<template>
<div id="app">
<!-- 3---调用组件 -->
<About></About>
</div>
</template>
<script lang="ts">
import {
Component ,Vue} from 'vue-property-decorator'
// 1--引入组件
import About from './components/About.vue'
// 2---使用引入的组件
@Component({
components:{
About
}
})
export default class App extends Vue{
}
</script>
<style lang="stylus">
</style>
<template>
<div>
about
{
{
str}}
<li v-for="(item,index) in arr" :key="index">
{
{
item}}
</li>
</div>
</template>
<script lang="ts">
// lang="ts"表示使用ts语法
// 引入类装饰器
import {
Component ,Vue} from 'vue-property-decorator'
@Component({
})
// 使用class方式创建类
export default class About extends Vue{
str:string="中公it优就业" //没有data 直接定义
private arr:any[]=["aaa","Bbb","cccc"];
}
</script>
<script lang="ts">
// lang="ts"表示使用ts语法
// 引入类装饰器
import {
Component ,Vue} from 'vue-property-decorator'
@Component({
})
// 使用class方式创建类
export default class About extends Vue{
str:string="中公it优就业" //没有data 直接定义
private arr:any[]=["aaa","Bbb","cccc"];
created(){
console.log("生命周期created")
}
mounted(){
console.log("mounted")
}
}
</script>
<template>
<div>
<li v-for="(item,index) in arr" :key="index">
{
{
item}} <button @click="del(index)">删除</button>
</li>
<button @click="changestr">修改str</button>
</div>
</template>
<script lang="ts">
// lang="ts"表示使用ts语法
// 引入类装饰器
import {
Component ,Vue} from 'vue-property-decorator'
@Component({
})
// 使用class方式创建类
export default class About extends Vue{
str:string="中公it优就业" //没有data 直接定义
private arr:any[]=["aaa","Bbb","cccc"];
changestr(){
//修改str
this.str="北京中公教育科技有限公司"
}
del(index){
this.arr.splice(index,1)
}
}
</script>
<template>
<div>
about
{
{
str}}
<li v-for="(item,index) in arr" :key="index">
{
{
item}} <button @click="del(index)">删除</button>
</li>
{
{
mystr}}
<button @click="changestr">修改str</button>
</div>
</template>
<script lang="ts">
// lang="ts"表示使用ts语法
// 引入类装饰器
import {
Component ,Vue} from 'vue-property-decorator'
@Component({
})
// 使用class方式创建类
export default class About extends Vue{
str:string="中公it优就业" //没有data 直接定义
private arr:any[]=["aaa","Bbb","cccc"];
created(){
console.log("生命周期created")
}
mounted(){
console.log("mounted")
}
changestr(){
//修改str
this.str="北京中公教育科技有限公司"
}
del(index){
this.arr.splice(index,1)
}
get mystr(){
return "我的公司是"+this.str
}
}
</script>
// 监听
// 浅监听 @Watch('监听的变量')
@Watch('str')
changefn(newval:string,oldval:string){
console.log("新值是"+newval,"旧值是"+oldval)
}
// 深度监听
// @Watch(监听的变量,{immediate:true,deep:true})
@Watch('arr',{
immediate:true,deep:true})
changearr(newval:any){
console.log("新值为",newval)
}
父组件
<template>
<div id="app">
<!-- 3---调用组件 -->
<About :message="message"></About>
</div>
</template>
<script lang="ts">
import {
Component ,Vue} from 'vue-property-decorator'
// 1--引入组件
import About from './components/About.vue'
// 2---使用引入的组件
@Component({
components:{
About
}
})
export default class App extends Vue{
message:string="欢迎来到中公教育"
num:number=25;
}
</script>
子组件
<template>
<div>
{
{
message}}
</div>
</template>
<script lang="ts">
// lang="ts"表示使用ts语法
// 引入类装饰器
import {
Component ,Vue, Watch,Prop} from 'vue-property-decorator'
@Component({
})
// 使用class方式创建类
export default class About extends Vue{
// @Prop 属性装饰器
// @Prop(String) readonly message:string |undefined
// 1:传入message属性,只读,是string类型,可以传入可以不传入
// @Prop([String,Number]) readonly message?:string |number
// 2: 传入message属性,只读 可以是number或string ?表示不传入 !表示必须传入
@Prop({
type:String, //多个就写[Number,String]
default:"hellow",
required:true,
validator:function(val){
return val.length>3;
}
})
private message:string|undefined
}
</script>
<style lang="stylus">
</style>
@Emit装饰器
父组件
<template>
<div id="app">
{
{
message}}
<!-- 3---调用组件 -->
<About @to-parent-fn="changefn"></About>
</div>
</template>
<script lang="ts">
import {
Component ,Vue} from 'vue-property-decorator'
// 1--引入组件
import About from './components/About.vue'
// 2---使用引入的组件
@Component({
components:{
About
}
})
export default class App extends Vue{
message:string="欢迎来到中公教育"
num:number=25;
changefn(val:string){
this.message=val
}
}
</script>
<style lang="stylus">
</style>
子组件
<template>
<div>
<!-- 直接调用@Emit -->
<!-- <button @click="toParentFn">传值1</button> -->
<button @click="go">传值1</button>
</div>
</template>
<script lang="ts">
// lang="ts"表示使用ts语法
// 引入类装饰器
import {
Component ,Vue, Watch,Emit} from 'vue-property-decorator'
@Component({
})
// 使用class方式创建类
export default class About extends Vue{
private msg="我是中公讲师"
// 1---不传入事件名,表示下面紧贴的函数就是自定义事件
// @Emit()
// toParentFn(){
// return this.msg; //return 的值就是传递给父组件的值
// }
// 2 传入事件名,事件名就是该自定义事件
// @Emit('to-parent-fn')
// toParentFn(){
// return this.msg+"2222"
// }
// 3--跟方法1 相同 只不过间接调用
@Emit()
toParentFn(){
return this.msg+"33333"
}
go(){
this.toParentFn()
}
}
</script>
<style lang="stylus">
</style>
手动在根目录下创建vue.config.js文件
module.exports={
devServer:{
proxy:{
'/api':{
target:'http://xxx.com',
ws:true,
changeOrigin:true
}
}
}
}
重新启动项目
‘n’ was also declared here.
n被使用过了
https://www.nuxtjs.cn/
整个网站先在服务器中运行,然后返回一个完整的html字符串,将这个字符串当成响应内容输出给浏览器
ssr 解决的就是搜索引擎记录页面信息的问题
有利于搜索引擎抓取我们的页面
build之后,会静态化page页面,所以访问速度快
Nuxt.js是基于vue的服务器端的渲染框架
Vue.js本身没有附带SSR,但是有很好的库可以很容易地将SSR添加到我们的Web应用程序中。最受欢迎的两个库是vue-server-renderer和Nuxt.js。
1:安装依赖
新建一个文件夹,安装Vue与SSR依赖包vue-server-renderer
mkdir ssr-test //新建空文件夹
cd ssr-test //进入目录
npm init //初始化,生成 package.json
npm install vue vue-server-renderer express --save// 安装
创建启动文件
在当前目录下创建一个app.js文件,并编写如下内容:
const Vue = require('vue')
const server = require('express')()
const fs = require('fs')
//读取模板---index.html
const renderer = require('vue-server-renderer').createRenderer({
template: fs.readFileSync('./index.html', 'utf-8')
})
// 此参数是vue 生成Dom之外位置的数据 如vue生成的dom一般位于body中的某个元素容器中,
//此数据可在header标签等位置渲染,是renderer.renderToString()的第二个参数,
//第一个参数是vue实例,第三个参数是一个回调函数。
const context = {
title: 'Vue-ssr-demo',
meta: `
`
}
server.get('*', (req, res) => {
//创建vue实例 主要用于替换index.html中body注释地方的内容,
//和index.html中 的地方是对应的
const app = new Vue({
data: {
url: req.url,
data: ['这是一个ssr示例'],
title: '学习vue-ssr服务端渲染'
},
//template 中的文本最外层一定要有容器包裹, 和vue的组件中是一样的,
//只能有一个父级元素,万万不能忘了!
template: `
{
{title}}
{
{item}}
`
})
//将 Vue 实例渲染为字符串 (其他的API自己看用法是一样的)
renderer.renderToString(app, context, (err, html) => {
if (err) {
res.status(500).end('err:' + err)
return
}
//将模板发送给浏览器
res.end(html)
})
})
server.listen(8080)
引入模板
在app.js的平级目录处创建一个index.html,空内容
启动项目
在命令行中进入项目目录,执行如下命令启动项目:
node app.js
然后在浏览器中打开http://localhost:8080
安装create-nuxt-app工具
cnpm install -g create-nuxt-app
使用create-nuxt-app创建nuxtjs项目
create-nuxt-app myapp-nuxt
创建nuxt项目的过程中,会问我们选择哪种渲染方式,一定要要选择Universal(通用的,普遍的)
spa 是单页面应用,这种模式下,文件不会ssr渲染
nuxt项目创建完毕后,先进入到项目中,然后运行
cd myapp-nuxt
npm run dev
在浏览器中运行 http://localhost:3000
package.json
"config": {
"nuxt": {
"host": "0.0.0.0",
"port": "3333"
}
},
"script":{
}
重新启动项目
nuxtjs没有所谓的index.html入口页,这个index.html实际是由nuxt.config.js编译而成的
引入公共的css文件
nuxt.config.js
css: [
'assets/css/resert.css'
],
在 static 目录下,建立 js/rem.js 文件。
static 目录是存放独立的文件的。
我们应该使用 script 标签引入 rem.js 文件,但 nuxtjs 中没有 html 页面,需要写在 nuxt.config.js 中。
在 nuxt.config.js 文件中:
head: {
script:[
{ src: '/js/rem.js', async: true, defer: true }
]
}
1:主入口文件layouts/default.vue类似于我们vue中的App.vue
components 目录下新建全局公用的组件库,该目录下新建Head.vue和Foot.vue
Head.vue
head
Foot.vue
-
首页
-
分类
-
购物车
-
我的
pages下面创建路由组件
index.vue是路由 ‘/’ 对应的组件, ’路由 ‘/mine’ 对应的组件是在pages下新建mine/index.vue
然后就可以实现路由跳转了
下载
cnpm i axios -S
引入
import axios from 'axios'
使用
ayncData方法会在组件每次加载之前被调用,它可以在服务端或路由更新之前被调用
<script>
import axios from 'axios'
export default {
data(){
return {
}
},
async asyncData(){
let {
data} = await axios.get('http://jsonplaceholder.typicode.com/posts')
// console.log("data",data)
return {
arr:data}; //这个return会把结果和data属性值自动合并,视图层直接调用即可
}
}
</script>
如果不喜欢es6的async/awai,那么也可以使用回调函数
asyncData({
params },callback){
axios.get('http://jsonplaceholder.typicode.com/posts')
.then(res=>{
callback(null,{
arr:res.data
})
})
}
注意:在视图层可以直接使用return 返回来的数据
{
{
arr}}
项目都开发完毕之后,我们需要将开发环境下的碎片化的文件做合并,这个过程叫做打包(发布)
如果 mode: ‘universal’ 模式
需要到package.json 文件中添加 “generate”: “nuxt generate”,
npm run generate
运行之后就会生成dist目录
如果 mode: ‘spa’ 模式
npm run build
将上一步的dist文件夹放入网站服务器下
后端服务可以是nodejs
新建文件夹 www
dist
app.js
app.js
//cnpm install express
const express =require('express');
const app=express()
app.use(express.static('dist'))
app.listen(8888)
用户打开浏览器 访问该项目了 http://localhost:8888