解释:
注意:被挂载的div要放在vue的上面,否则vue管不到
方法一:直接在标签里实现
<div id="app">
<h2>当前计数: {{count}}h2>
<button v-on:click="count++">+button>
<button v-on:click="count--">-button>
div>
<script src="../js/vue.js">script>
<script>
const bpp=new Vue({
el: "#app",
data : {
count: 0,
movices: ['one','two','three']
}
})
script>
mustache语法(双大括号语法)
在div中加入v-cloak属性,可以让div在vue没解析之前不显示
v-cloak在vue解析完之后就会消失
动态绑定class:可以绑定是否将class属性添加到标签中
另一种比较简洁的写法
<!--当item为true时,button不起作用-->
<button :disable="item">按钮</button>
用于进行事件监听
<body>
<div id="app">
<h2>当前计数: {{count}}</h2>
<button v-on:click="add">+</button>
<button v-on:click="mid">-</button>
</div>
<script src="../js/vue.js"></script>
<script>
const bpp=new Vue({
el: "#app",
data : {
count: 0,
movices: ['one','two','three']
},
methods: {
add: function () {
console.log("add被执行");
this.count++
},
mid: function () {
console.log("mid被执行");
this.count--
}
}
})
</script>
</body>
<button @cick="add">+</button>
<button @cick="incr">-</button>
<body>
<div id="app">
<button @click="print('hello')">按钮</button>
</div>
<script src="../js/vue.js"></script>
<script>
const bpp=new Vue({
el: "#app",
data : {
count: 0,
movices: ['one','two','three']
},
methods: {
print(name){
console.log(name)
}
}
})
</script>
</body>
7.3.1)如果函数不是写在{{}}里面或者函数没有参数,则()可以省略
<button @click="print">按钮</button>
7.3.2)如果函数中有参数,但是没有传入参数的话,那么就将undefined传进去
<button @click="print()">按钮</button>
7.3.3)如果函数中有参数,但是没有写()那么将点击事件传进去
<button @click="print">按钮</button>
7.3.4)如果既要传递参数,又要获得event
<body>
<div id="app">
<button @click="print('hello',$event)">按钮</button>
</div>
<script src="../js/vue.js"></script>
<script>
const bpp=new Vue({
el: "#app",
data : {
count: 0,
movices: ['one','two','three']
},
methods: {
print(name,event){
console.log(name+'-----'+event)
}
}
})
</script>
</body>
.stop停止该按钮的作用
停止某个事件的作用,如果不加stop修饰的话,点击按钮那某divClick也会起作用,这不是想要的,所以可以加上stop就阻止了
.prevent阻止默认事件的发生
监听某个键帽的作用
当按下回车的时候,才让函数起作用
.once
让点击事件只起一次作用
<body>
<div id="app">
<h2 v-if="isShow">你好呀</h2>
<h2 v-show="isShow">你好呀</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el:"#app",
data:{
isShow:true
}
})
</script>
</body>
当isShow为false时,v-if是直接被清除了,
而v-show则是多了个style=“display:none”
遍历数组
<body>
<div id="app">
<ul>
<li v-for="item in movices">{{item}}</li>
</ul>
</div>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el:"#app",
data:{
movices:['喜羊羊与灰太狼','熊出没','海贼王']
}
})
</script>
</body>
遍历对象
<body>
<div id="app">
<ul>
<li v-for="(value,key) in info">{{value}}-{{key}}</li>
</ul>
</div>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el:"#app",
data:{
movices:['喜羊羊与灰太狼','熊出没','海贼王'],
info:{
name:"张三",
sex:"男",
age:180
}
}
})
</script>
</body>
v-for绑定和非绑定key的区别
<div id="app">
<ul>
<li v-for="item in movices" key="item">{{item}}</li>
</ul>
</div>
如果有绑定key,那么每个item都会和key一一对应,如果要进行添加或者删除操作时,就会像链表的添加删除一样快;
如果没有绑定key,那么要进行添加或者删除操作时,就会像数组的添加删除一样慢。
双向绑定:就是对属性值进行改变时,页面中展示的值跟着改变,对页面展示的值进行改变时,属性值也跟着改变
也就是:数据变化更新视图,视图变化更新数据
原理:v-model其实就是一个语法糖,它的背后本质上是包含两个操作:
1、v-bind绑定一个value属性
2、v-on指令给当前元素绑定input事件
绑定text类型:
<body>
<div id="app">
<input type="text" :value="message" @input="btnClick">
{{message}}
</div>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el:"#app",
data:{
message:"你好啊"
},
methods:{
btnClick(event){
this.message=event.target.value
}
}
})
</script>
</body>
v-model绑定radio类型:
<body>
<div id="app">
<input type="radio" v-model="sex" id="sex" value="男">男
<input type="radio" v-model="sex" id="sex" value="女">女<br/>
<h2>您选择的性别是:{{sex}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el:"#app",
data:{
message:"你好啊",
sex:''
}
})
</script>
</body>
绑定checkbox:
<body>
<div id="app">
<h1>单选框</h1>
<input type="checkbox" v-model="agree">同一协议<br/>
<h2>您的选择是{{agree}}</h2>
<button :disable="!agree">下一步</button>
<h1>多选框</h1>
<input type="checkbox" value="篮球" v-model="hobbies">篮球<br/>
<input type="checkbox" value="足球" v-model="hobbies">足球<br/>
<input type="checkbox" value="羽毛球" v-model="hobbies">羽毛球<br/>
<input type="checkbox" value="乒乓球" v-model="hobbies">乒乓球<br/>
<h2>您的选择是:{{hobbies}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el:"#app",
data:{
agree:false,
hobbies:[]
}
})
</script>
</body>
<body>
<div id="app">
<select v-model="fruit">
<option value="苹果">苹果</option>
<option value="香蕉">香蕉</option>
<option value="菠萝">菠萝</option>
<option value="橘子">橘子</option>
</select>
<h2>您的选择是:{{fruit}}</h2>
<select v-model="fruits" multiple>
<option value="苹果">苹果</option>
<option value="香蕉">香蕉</option>
<option value="菠萝">菠萝</option>
<option value="橘子">橘子</option>
</select>
<h2>您的选择是:{{fruits}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el:"#app",
data:{
fruit:"香蕉",
fruits:[]
}
})
</script>
</body>
值绑定:
就是动态地给value赋值,可以通过v-bind动态地给value绑定值
<body>
<div id="app">
<label v-for="item in books">
<input type="checkbox" :value="item" v-model="books">{{item}}<br/>
</label>
<h2>书籍有:{{books}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el:"#app",
data:{
books:['数据结构与算法','算法导论','编译原理','计算机网络','计算机组成原理']
}
})
</script>
</body>
.lazy
这个修饰符让v-model不用实时绑定,而是等到回车的时候才进行绑定
<input type="text" v-model.lazy="message">{{message}}
.number
这个修饰符让输入框中的值保持是数字,如果没有加这个修饰符那么即使让它的初始化是数字,输入多个数字时它会自动转为string类型
<input type="number" v-model.number="age">{{age}}--{{typeof age}}
.trim
这个修饰符用于去除左右两边的空格
<input type="text" v-model.trim="name">
计算属性的优点:计算属性是有缓存的
使用它时不需要加(),因为它是当做一个属性来使用的
计算属性本质上是长这样的
computed:{
fullName:{
setter:function () {
},
getter:function () {
}
}
}
但是,一般是不写setter方法的,所以只是这样的
computed:{
fullName:{
getter:function () {
}
}
}
为了简写,所以一般看到的都是这样的
computed:{
fullName:function () {
}
}
}
计算属性是有缓存的,如果要多次显示计算属性的内容,计算属性只会被调用一次,而methods是没有缓存的,显示多少次,methods就被调用多少次。
在JavaScript中,使用var定义的变量除了function其他都是没有作用域的(例如:if,for等)
以下这个例子
它内部是这样的
{
var i=0;
btns[i].addEventListener('click', function () {
console.log('第' + i + '个按钮被点击')
})
}
{
var i=1;
btns[i].addEventListener('click', function () {
console.log('第' + i + '个按钮被点击')
})
}
{
var i=2;
btns[i].addEventListener('click', function () {
console.log('第' + i + '个按钮被点击')
})
}
而var是没有作用域的,所以每次每个块中的i都被5重新赋值
不管点击哪个button,控制台都是打印5,因为for是没有作用域的,所以i会一直加到5,因此,不管点击哪个button都是打印5
就不会总是打印5了
而如果使用let的话,就是有作用域的,就不会出现上面的问题。
对于下面这段代码,它是加了闭包的
for (var i=0;i<5;i++){
(function (num) {
btns[i].addEventListener('click',function () {
console.log('第'+num+'个按钮被点击')
})
})(i)
}
每次执行的时候就在function里面创建了个i,而function是有作用域的,因此,当每次点击button时,打印的是function里面的值,和外面的i没有关系,所以可以打印正确
对于ES5中的字面量对象的书写形式
<script>
const name='hello'
const age=20
const height=1.80
const person={
name:name,
age:age,
heigth:height
}
console.log(person)
</script>
ES6中的书写形式
<script>
const name='hello'
const age=20
const height=1.80
const person={
name,
age,
height
}
console.log(person)
</script>
ES5的写法:
const demo={
run:function () {
}
}
ES6中的写法:
const demo={
run(){
}
}
响应式就是直接在控制台上对数组中的元素进行增删改查时,页面中的展示会跟着变化。
从最后一位添加元素,可以一次性添加多个值
push(…num)
从最后一位删除元素
从第一位删除元素
从第一位添加元素,可以一次性传入多个值unshift(…num)
splice的作用:
删除:
splice(start,删除的元素个数) ,表示从start开始,要删除多少个元素;
splice(start)表示删除start开始后面的元素
替换:
splice(start,end,替换的元素)表示从start开始删除end个元素,然后再插入替换元素,可以替换多个元素
排序
反转
可以对内容进行修饰
格式:{{原本的内容 | 过滤器}}
例子:想要对价格的显示进行一些修饰,在前面添加¥符号和让它有两位小数显示
filters:{
priceFilter(price){
return '¥'+price.toFixed(2)
}
}
对数组中的数据进行过滤,满足条件的则放到新数组中
const nums=[20,40,80,100,111,212,212]
//filter
const newNum1=nums.filter(function (n) {
return n<100
})
对数组中的数据进行处理后放到新数组里面
const nums=[20,40,80,100,111,212,212]
//2、map
const newNum2=newNum1.map(function (n) {
return n*2
})
对数组中的数据进行累加
const nums=[20,40,80,100,111,212,212]
//3、reduce
const newNum3=nums.reduce(function (previousValue,n) {
return previousValue+n
},0) //初始值是0
组件使用的步骤:
1)创建组件构造器
2)注册组件
3)使用组件
例子:
<body>
<div id="app">
<my-cpn></my-cpn>
</div>
<script src="../js/vue.js"></script>
<script>
//1、注册组件构造器
const conC=Vue.extend({
template: `
我是标题
我是内容,哈哈哈哈
我是内容,呵呵呵呵
`
})
//2、注册组件
Vue.component('my-cpn',conC)
const app=new Vue({
el:"#app",
data:{
}
})
</script>
</body>
它们的区别:
1、在于注册的方式
2、全局组件可以作用在被不同Vue实例挂载的dom里,而局部组件只能作用在注册这个组件的dom里
全局组件的注册方式:
Vue.component('my-cpn',conC)
局部组件的注册方式:
在vue实例中注册
const app=new Vue({
el:"#app",
data:{
cpn:conC
}
})
不再需要单独写template,而是将组件构造器里的东西写到注册里面
前面注册的时候模板都是写在注册里的,非常难看,我们可以通过标签将模板写在这里面
5.1)子组件不能直接访问Vue实例里面的数据
5.2)vue组件应该有自己保存数据的地方
5.2)组件中的data是function格式的
因为一个组件一般都是被使用多次的,而使用函数的话它是会返回一个对象的,然后不同函数返回的对象就是不一样的,就不会导致每个组件都是在操作同一个数据,避免了数据的错误。如果它是用对象的话,那么多个组件就是在操作同一个数据,造成数据的错误。
<body>
<div id="app">
<cpn></cpn>
<cpn></cpn>
</div>
<template id="cpn">
<div>
<h2>当前计数:{{counter}}</h2>
<button @click="increment">+</button>
<button @click="decrement">-</button>
</div>
</template>
<script src="../../js/vue.js"></script>
<script>
Vue.component('cpn',{
template:"#cpn",
data(){
return{
counter:0
}
},
methods:{
increment(){
this.counter++
},
decrement(){
this.counter--
}
}
})
const app=new Vue({
el:"#app"
})
</script>
</body>
如果组件中的data是驼峰标识的,那么dom中需要用 - 来表示,否则会出错。
要求:将父组件中的数据传递到子组件中,然后在子组件中对数据进行改变后,可以将改变后的数据传递到父组件中。同时,要求父组件中显示的数据是子组件的2倍。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>父子组件通信-双向绑定</title>
</head>
<body>
<div id="app">
<cpn :number1="num1"
:number2="num2"
@num1change="num1change"
@num2change="num2change"></cpn>
</div>
<template id="cpn">
<div>
<p>data:{{dnumber1}}</p>
<p>props:{{number1}}</p>
<input type="text" :value.number="dnumber1" @input="number1input" />
<p>data:{{dnumber2}}</p>
<p>props:{{number2}}</p>
<input type="text" :value.number="dnumber2" @input="number2input" />
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el:"#app",
data:{
num1:0,
num2:1
},
components:{
cpn:{
template:"#cpn",
props:{
number1:Number,
number2:Number
},
data(){
return{
dnumber1:this.number1,
dnumber2:this.number2
}
},
methods:{
number1input(event){
this.dnumber1=event.target.value;
this.$emit('num1change',this.dnumber1);
this.dnumber2=this.dnumber1*100;
this.$emit('num2change',this.dnumber2)
},
number2input(event){
this.dnumber2=event.target.value;
this.$emit('num2change',this.dnumber2);
this.dnumber1=this.dnumber2/100;
this.$emit('num1change',this.dnumber1)
}
}
}
},
methods:{
num1change(value){
this.num1=parseFloat(value)
},
num2change(value){
this.num2=parseFloat(value)
}
}
})
</script>
</body>
</html>
有两种方式:
10.1)通过 $ children(很少用,一般在获取所有子组件的时候才会使用)
10.2)通过 $ refs:
<body>
<div id="app">
<cpn></cpn>
<cpn ref="aaa"></cpn>
<button @click="btnClick">按钮</button>
</div>
<template id="cpn">
<div>我是子组件</div>
</template>
<script src="../../js/vue.js"></script>
<script>
const cpn={
template:"#cpn",
data(){
return {
name:"我是子组件中的name"
}
},
methods:{
showmessage(){
console.log('showmessage')
}
}
};
const app=new Vue({
el:"#app",
data:{
message:'你好啊'
},
methods:{
btnClick(){
//console.log(this.$children[0].name)
console.log(this.$refs.aaa.name)
}
},
components:{
cpn
}
})
</script>
</body>
vue中的插槽就是在组件的标签中加入
标签,然后如果需要在这里面加入新的内容就可以直接添加
具名插槽
如果没有对插槽指定具体的名称,那么所有的插槽都会替换
结果
加了名称,就会替换了那些加了名称的
一般在组件中有默认的显示数据的方式。如果父组件调用了子组件,但是父组件并不想要子组件显示数据的方式,而是想要按照自己的方式显示数据,但是在父组件中是不能直接访问子组件中的数据的。所以可以采用插槽的方式来处理。
模块化有两个核心:导出和导入
Commonjs的导出
module.exports={
flag:true,
test(a,b){
return a+b
},
demo(a,b){
return a*b
}
}
Commonjs的导入
//Commonjs的导入
let{test,demo,flag}=require('moduleA');
//等同于
let _mA=required('moduleA');
let test=_mA.test;
let demo=_mA.demo;
let flag=_mA.flag;
可以通过在标签中加入
type="module"
属性来标志这个一个模块,就不会出现模块间数据冲突的问题
一个模块只能有一个export default,使用这个东西之后在导入时就可以自定义名称
webpack是一个前端模块化打包工具
对于有些技术,浏览器是识别不了的,而通过webpack打包之后就可以转化为浏览器可以识别的东西
node和webpack和npm的关系:
webpack模块化打包;
webpack为了可以正常运行,必须依赖node环境;
node环境为了可以正常的执行化很多代码,必须其中包含各种依赖的包;
npm工具就是用来管理这些包的。
node安装完之后附带安装了npm
https://blog.csdn.net/qq_38232598/article/details/91346993
可以通过npm get registry
来获取npm源
npm install webpack@3.6.0 -g
–save-dev 是开发时依赖,项目打包后不需要继续使用
cd 对应目录
npm install webpack@3.6.0 --save-dev
一般创建两个文件夹dist和src,dist放的是打包后的代码,src放的是我们原始代码
进入src所在的目录,然后执行以下指令进行打包
webpack ./src/main.js ./dist/bundle.js
打包后生成的bundle.js代码就是最终使用的代码
注意:main.js会调用很多其他代码,这里不用管它,webpack会自动将它们打包
上一个例子中打包js需要写打包的入口和出口,比较麻烦,可以用一个配置文件来记录入口和出口,以后就不用在打包时写入口和出口了。
因为要使用到node中的一些包,所以需要用npm来加载这些包,每次使用npm前,建议都先执行npm init
然后就生成了这个文件
在package.json中可以对指令进行映射,然后执行npm run 映射的名称,如果在这里映射了webpack,那么使用映射后的指令默认优先使用本地安装的webpack,而不是全局的,而只要是使用webpack指令,那么使用的就是全局的。
我们除了对js文件进行打包之外,还需要对其他文件进行打包,所以需要将其他文件导入到mian.js中,但是打包其他文件需要一些加载器
https://webpack.docschina.org/loaders/css-loader/
注意:安装时指定以下版本,否则可能会出错
安装css-loader
npm install css-loader@2.0.2 --save-dev
安装style-loader
npm install style-loader@0.23.1 --save-dev
安装less-loader和less,其中less不是一个loader,而是为了将less解析为css
老规矩,指定具体版本
npm install less-loader@4.1.0 less@3.9.0 --save-dev
npm install url-loader@1.1.2 --save-dev
当图片小于limit时,图片会被编译成base64的格式
当图片的大于limit时,需要再下载file-loader
在使用webpack进行打包时,还是不能将ES6转为ES5,所以需要使用相应的loader对其进行转化。
安装babel-loader,babel-core和babel-preset-es2015(es2015也就是es6)
npm install babel-loader@7 babel-core babel-preset-es2015 --save-dev
在webpack.config.js中添加如下配置
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/, //排除掉那些不是我们自己写的代码
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
npm install vue@2.5.21 --save-dev
这是因为我们使用的是runtime-only版本的,它不允许有template,因为我们引入了vue实例,所以就有template,所以报错。
解决方法:在webpack.config.js中进行配置,让它可以找到compiler可以编译template
将App中的内容抽取之后写在一个js文件里
export default{
template: `
{{message}}
{{name}}
`,
data(){
return{
message:"我是message",
name:"我是name"
}
},
methods:{
btnClick(){
console.log(this.message,this.name)
}
}
};
将app.js文件内容放到App.vue里面(然后就不需要app.js了)
<template>
<div>
<h2>{{message}}</h2>
<button @click="btnClick">按钮</button>
<h2>{{name}}</h2>
</div>
</template>
<script>
export default {
name: "App" ,
data(){
return{
message:"我是message",
name:"我是name"
}
},
methods:{
btnClick(){
console.log(this.message,this.name)
}
}
}
</script>
<style scoped>
</style>
然后需要加载vue-loader
和vue-template-compiler
因为版本太大的vue-loader需要安装相应的vue-loader应该低一点
npm install vue-loader@13.0.0 vue-template-compiler@2.5.21 --save-dev
在webpack.config.js中进行相应的配置
执行结果
步骤一:通过npm安装需要使用的plugins(某些webpack已经内置的插件不需要安装)
步骤二:在webpack.config.js中的plugins中配置插件
例子:
这个是webpack自带的plugin,所以直接引入就行了,不需要安装
在webpack.config.js中进行配置
在bundle.js中就多了这个东西
在使用webpack打包后,html并不会打包进去,但是这个html确是我们需要使用的,所以就用到了htmlwebpackplugin插件
安装
npm install html-webpack-plugin@3.2.0 --save-dev
在webpage.config.js中进行相应的配置
问题:没有这个模板
解决:在new htmlwebpackplugin()添加一个模板
更改index.html
在webpack.config.js中导入template
然后就能生成我们想要的index.html了
安装uglifyjs-webpack-plugin
npm install uglifyjs-webpack-plugin@1.1.1 --save-dev
将配置文件分为公共、开发和运行配置文件
需要安装webpack-merge
npm install webpack-merge@4.1.5 --save-dev
base.config.js
const path = require('path'); //动态地获取路径
const webpack=require('webpack');
const htmlwebpackplugin=require('html-webpack-plugin');
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, '../dist'), //__dirname是一个全局变量,是node里面的东西
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.css$/i,
use: ["style-loader","css-loader"],
},
{
test: /\.less$/,
use: [{
loader: "style-loader", // creates style nodes from JS strings
}, {
loader: "css-loader" // translates CSS into CommonJS
}, {
loader: "less-loader", // compiles Less to CSS
}]
},
{
test: /\.(png|jpg|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 13000,
},
},
],
},
{
test: /\.(png|jpe?g|gif)$/i,
use: [
{
loader: 'file-loader',
},
],
},
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015'],
}
}
}
],
},
resolve:{
alias:{ //配置别名
'vue$': 'vue/dist/vue.esm.js' //让它可以去这个路径中找到compiler编译template
}
},
plugins:[
new webpack.BannerPlugin('最终版权归aaa所有!'),
new htmlwebpackplugin({
template:'index.html'
})
]
};
prod.config.js
const UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin')
const webpackMerge = require('webpack-merge')
const baseConfig = require('./base.config')
module.exports = webpackMerge(baseConfig, {
plugins: [
new UglifyjsWebpackPlugin()
]
})
CLI是什么意思:
脚手架的前提:node
安装脚手架vue cli,这里进行全局安装
cnpm install -g @vue/cli@3.2.1
查看版本
C:\Users\lenovo>vue --version
3.2.1
如果想要使用脚手架2,可以拉取脚手架2
npm install -g @vue/cli-init
Vue CLI2初始化项目
vue init webpack my-project
Vue CLI3初始化项目
vue create my-project
vue init webpack my-project
npm run dev
vue create vuecli3
npm run serve
使用runtime-compile和runtime-only执行后的mian.js的区别:
template->ast->render->vdom->ui
render->vdom->ui
区别:
1)runtime-only的性能更高
2)runtime-only的代码量更少
启动配置服务器(在哪个目录启动都可以)
vue ui
就打开了这个界面
导入一个项目,进入到管理页面
看vue真实的版本要去打包之后的文件中看,而不是看源码里面的,可以在以下两个文件中查看
是ES6中一种定义函数的方式
const sum=(num1,num2)=>{
return num1+num2;
}
console.log(sum(2,3));
如果只有一个参数,可以省略()
const power2=num=> {
num*num;
}
需要写{}
可以省略{}
const power2=num=> num*num
console.log(power2(3));
没有参数,且只有一行代码
const demo=()=>console.log("没有参数,且只有一行代码");
demo();
在箭头函数中,this是向外层作用域中,一层一层向外找,直到有this
const obj={
aaa(){
setTimeout(function () {
console.log(this);
},1000);
setTimeout(()=>console.log(this),1000);
}
};
obj.aaa();
const obj={
aaa(){
setTimeout(function () {
setTimeout(function () {
console.log(this);
});
setTimeout(()=>{
console.log(this);
});
});
setTimeout(()=>{
setTimeout(function () {
console.log(this);
});
setTimeout(()=>{
console.log(this);
});
});
}
};
obj.aaa();
history.push({},title,url)
它可以改变url,类似于栈,浏览器中地址栏显示的总是栈顶url
history.back()
它类似于出栈操作,每次执行这个函数,都相当于执行浏览器中的返回操作
history.go(数值)
数值如果是负数,则相当于浏览器中的返回操作,如果是正数,则相当于浏览器中的前进
history.forward()
相当于history.go(1)
histrory.back()相当于history.go(-1)
history.forward()相当于history.go(1)
history.replaceState({},title,url)
会替代上一个url,并且浏览器中不能通过前进或后退来回到之前的url
就是将页面在服务器渲染完之后整个渲染好的页面传到浏览器,在浏览器中只能看到html+css
浏览器中显示的网页中的大部分内容,都是由前端写的js代码在浏览器中执行,最终渲染出来的网页。
搭建vue-router步骤:
(一)安装vue-router
我这里使用脚手架自动安装了vue-router了,所以就不需要这一步了
npm install vue-router@3.0.1 --save-dev
(二)在模块化工程中使用它(因为是一个插件, 所以可以通过Vue.use()来安装路由功能)
第一步:导入路由对象,并且调用 Vue.use(VueRouter)
第二步:创建路由实例,并且传入路由映射配置
第三步:在Vue实例中挂载创建的路由实例
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
//通过Vue.use(插件) 来安装插件
Vue.use(Router)
//创建并导出router,vue-router只有挂载到vue实例里面,才能生效
export default new Router({
routes: [ //在这里面配置相关的映射信息
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
}
]
})
main.js
import Vue from 'vue'
import App from './App'
import router from './router' //导入router
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router, //挂载router
render: h => h(App)
})
第一步: 创建路由组件
第二步: 配置路由映射: 组件和路径映射关系
第三步: 使用路由: 通过
和
用于显示组件中的内容,如果没有
那么组件中的内容就显示不出来
写在哪,组件的内容就显示在哪
属性这个的作用相当于history.replaceState(),加了这个东西之后浏览器就不能进行前进或后退操作
当
对应的路由匹配成功时, 会自动给当前元素设置一个router-link-active的class, 设置active-class可以修改默认的名称.
在index.js中进行设置
注意:这里不能用history.pushState(),因为它会绕过路由,而我们需要的是进行路由跳转
也就是在路径中进行传参
在index.js的路由映射中配置
然后在App.vue中设置要传递的值
这个this.$route是在index.js中的routes[]中配置的其中一个,表示当前活跃的route
先打包项目
npm run build
生成dist文件夹
路由懒加载做了什么?
使用懒加载之前
组件在注册时,是采用这种方式注册的
打包后的js,应用程序的代码全部都放在app.801c2ae2e69a05c33dfc65f8.js里面
使用步骤:
(一)创建被嵌套的组件
homeMessage.vue
<template>
<div>
<ul>
<li>message1</li>
<li>message2</li>
<li>message3</li>
<li>message4</li>
<li>message5</li>
</ul>
</div>
</template>
<script>
export default {
name:'message'
}
</script>
homeNew.vue
<template>
<div>
<ul>
<li>new1</li>
<li>new2</li>
<li>new3</li>
<li>new4</li>
<li>new5</li>
</ul>
</div>
</template>
<script>
export default {
name:'new'
}
</script>
(三)使用路由: 通过
和
,
用于显示组件中的内容,如果没有那么组件中的内容就显示不出来写在哪,组件的内容就显示在哪
主要有两种方式:params和query
params:
一个例子:
普通的修改方式:
在每个页面中使用进行添加,这样比较麻烦
通过导航卫士:
导航钩子的三个参数解析:
router.afterEach()
不需要主动调用next()函数
**created:**一个dom创建并初始化之后就回调这个函数
mounted: 将组件编译并渲染完成后回调这个函数
updated: 对组件有什么更新都会回调这个函数,只要不跳转到其他页面,就会一直循环
destoryed: 如果跳转到其他页面,就会回调这个函数
<keep-alive>
<router-view/>
</keep-alive>
keep-alive可以让组件不被destroy
举个栗子:
在home这个页面中有两个组件,如果它现在页面中显示的是消息组件,而如果从home页面跳转到关于页面,那么这个home页面就会被destroy,如果再跳转回home页面,它自然就不会再显示消息组件了,因为它会重新被创建,而且它默认不是显示到消息组件的。
而如果是不被destory,并且它被够在跳转回home页面时,记住home页面中的那个最后记录的地址,自然就能跳转回home页面跳转到其他页面前的最后的模样。
keep-alive的属性:
exclude属性:可以排除掉不想一直被保留的组件
<template>
<div id="app">
<tab-bar>
<tab-bar-item>
<img slot="item-icon" src="./assets/img/tabbar/home.svg" alt="图片不见了"/>
<div slot="item-text">首页</div>
</tab-bar-item>
<tab-bar-item>
<img slot="item-icon" src="./assets/img/tabbar/category.svg" alt="图片不见了"/>
<div slot="item-text">分类</div>
</tab-bar-item>
<tab-bar-item>
<img slot="item-icon" src="./assets/img/tabbar/shopcart.svg" alt="图片不见了"/>
<div slot="item-text">购物车</div>
</tab-bar-item>
<tab-bar-item>
<img slot="item-icon" src="./assets/img/tabbar/profile.svg" alt="图片不见了"/>
<div slot="item-text">我的</div>
</tab-bar-item>
</tab-bar>
</div>
</template>
<script>
import TabBar from './components/tabbar/TabBar';
import TabBarItem from './components/tabbar/TabBarItem';
export default {
name: 'App',
components:{
TabBar,
TabBarItem
}
}
</script>
<style>
@import "./assets/css/base.css";
</style>
TabBar.vue
<template>
<div id="tab-bar">
<slot></slot>
</div>
</template>
<script>
export default {
name: "TabBar"
}
</script>
<style scoped>
#tab-bar{
display: flex;
background-color: #f6f6f6;
position: fixed;
left: 0;
right: 0;
bottom: 0;
box-shadow: 0 -1px 1px rgba(100,100,100,.08);
}
</style>
TabBarIItem
<template>
<div class="tab-bar-item">
<slot name="item-icon"></slot>
<slot name="item-text"></slot>
</div>
</template>
<script>
export default {
name: "TabBarItem"
}
</script>
<style scoped>
.tab-bar-item{
flex: 1;
text-align: center;
height: 49px;
}
.tab-bar-item img{
height: 24px;
width: 24px;
}
</style>
如果直接将属性添加在
上,那么在使用时,这些属性有些是会显示不出的,所以一般把这些属性写在它外面的上
1、创建不同tabbar要显示的视图
2、将不同的视图在index.js中进行映射配置
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
const home=()=>import('../view/home/home');
const category=()=>import('../view/category/category');
const profile=()=>import('../view/profile/profile');
const shopcart=()=>import('../view/shopcart/shopcart');
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
redirect:'/home'
},
{
path:"/home",
component:home
},
{
path:"/category",
component: category
},
{
path:"/shopcart",
component:shopcart
},
{
path:"/profile",
component:profile
}
]
})
3、在TabBarItem中配置配置路径跳转
4、在App.vue中传入不同TabBarItem对应的path
是一种异步编程的解决方案
在异步编程中,当网络请求非常复杂时,就会出现回调地狱。
我们来考虑下面的场景(有夸张的成分):
promise就可以用来解决这个问题
需求:在控制台上,每隔1s进行打印
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>promise的基本使用</title>
</head>
<body>
<script>
new Promise((resolve, reject) => {
//第一次网络请求的代码
setTimeout(()=>{
resolve()
},1000)
}).then(()=>{
//第一次拿到结果的处理代码
console.log('hello world');
console.log('hello world');
console.log('hello world');
console.log('hello world');
console.log('hello world');
console.log('hello world');
return new Promise((resolve, reject) => {
//第二次网络请求的代码
setTimeout(()=>{
resolve()
},1000)
})
}).then(()=>{
//第二次处理的代码
console.log('hello promise');
console.log('hello promise');
console.log('hello promise');
console.log('hello promise');
console.log('hello promise');
console.log('hello promise');
return new Promise((resolve,reject)=>{
//第三次网络请求的代码
setTimeout(()=>{
resolve()
},1000)
})
}).then(()=>{
console.log('hello vue');
console.log('hello vue');
console.log('hello vue');
console.log('hello vue');
console.log('hello vue');
console.log('hello vue');
})
</script>
</body>
</html>