一、标签的ref属性
vue很少获取DOM元素,但该操作也不可避免。vue使用ref属性来获取DOM元素。vue里的ref属性是id属性的替代者,用来给元素或子组件注册引用信息,使用ref属性识别页面元素或子组件之后,被标识的元素或子组件会被所在的组件实例对象收集,挂载在所在组件实例对象的$refs属性上。
例如:
<!-- 标记html标签属性 -->
<h1 ref="xxx">...</h1>
<!-- 标记子组件 -->
<School ref="xxx">...</School>
获取标识的元素或子组件:
this.$refs.xxx
其中,this为被标记的元素或子组件所在的组件实例对象。
1.1 使用ref属性标记html标签元素,获取的是真实的DOM元素;ref属性应用在组件标签上,获取的是对应组件实例对象。
<template>
<div class="demo">
<h2>学校:{{name}}h2>
<h2>地址:{{address}}h2>
div>
template>
<script>
export default {
name:'MySchool',
data(){
return{
name:'SGG',
address:'Beijing'
}
}
}
script>
<template>
<div >
<h1 ref="hello"> Hello Worldh1>
<MySchool ref="myschool">MySchool>
<button @click="showH1">showH1button>
<button @click="showMySchool">showMySchoolbutton>
div>
template>
<script>
//导入子组件
import MySchool from '../components/MySchool.vue'
export default {
name:'Show',
component:{
MySchool
},
methods:{
showH1(){
console.log("hello...")
console.log(this.$refs.hello)
console.log(this.$refs)
},
showMySchool(){
console.log("myschool...")
console.log(this.$refs.myschool)
console.log(this.$refs)
}
}
}
script>
效果如下:
修改代码如下:
效果如下:
二、vue的computed和watch的区别
watch和computed都是以Vue的依赖追踪机制为基础的,不同的是,computed中定义的是变量(类似于data中的变量,只是computed里定义的变量依赖data中的变量,即是data中属性的计算结果,所以computed又被称为计算属性,且随着data中变量的变化而变化),而watch中定义的是变量变化时触发的回调方法。
例如:
<template>
<body>
<div id="qqq" >
<div >number1:{{number1}}div>
<div >number2:{{number2}}div>
<div >number3:{{number3}}div>
<button @click="addNUmber1"> number1加1button>
<button @click="addNUmber2"> number2加1button>
div>
body>
template>
<script>
import QRCode from 'qrcodejs2';
export default {
name: "qrCode",
data() {
return {
number1:10,
number2:20
}
},
computed:{
number3:function(){
return this.number1+this.number2;
}
},
watch:{
"number1":function(newVal,oldVal){
console.log("number1由"+oldVal+"变为"+newVal);
},
"number2":function(newVal,oldVal){
console.log("number2由"+oldVal+"变为"+newVal);
},
"number3":function(newVal,oldVal){
console.log("number3由"+oldVal+"变为"+newVal);
}
},
methods: {
addNUmber1:function(){
this.number1++;
},
addNUmber2:function(){
this.number2++;
}
}
}
script>
上例中,computed中定义的计算属性number3依赖属性number1和number2,且随它们的变化而变化。watch中定义了三个方法,分别是在number1、number2、number3三个变量发生变化时触发的,且方法有两个参数,第一个参数为变量新的值,第二个参数为变量原来的值。
效果如下:
点击“number1加1”按钮:
number1的值发生了变化,number3的值随之变化,且触发了watch中number1和number3对应的方法。
二、vuex
2.1 vuex概念
vuex是一个专门为vue.js应用程序开发的状态管理模式,它采用集中式存储管理应用的所有组件的状态。Vuex也集成了Vue的官方调试工具devtools extension,提供了诸如零配置的time-travel调试,状态快照导入导出等高级调试工具。
理解“状态管理模式”、“集中式存储管理”:将状态看成变量,前面两个名词的作用就是把多个组件需要共享的变量全部存储到一个对象里面;然后将这个对象放在顶层的Vue实例中,让其他组件可以使用;这样多个组件就可以共享这个对象中的所有属性了。换就话说,Vuex是可以让多个组件相互共享状态的插件。
vuex中只会放在多个界面间需要共享的多个状态,如:用户的登录状态、用户名称、头像、地理位置、商品的收藏、购物车中的物品等,这些状态信息可以放在统一的地方进行保存和管理,且它们是响应式的(响应式是指数据发生变化时,界面也跟着刷新),比如在组件A申请对store中的值B进行改变,那么改变之后,store中的其他方法、其他组件只要用到值B的都会立即做出改变。
将vuex. $store对象挂载到App.js中的Vue对象后,所有的Vue组件都会有 $store对象。
Devtools是为Vue开发提供的一个浏览器插件,会记录每次修改store中的state的状态(有多个组件修改state时是哪个组件修改了state),但只能跟踪同步操作(由mutation处理),不能跟踪异步操作(由Actions处理)。
2.2 State的概念
可以把State理解为一个存储数据的区域,像是组件中的data。Vuex采用“单一状态树”,一个对象包含应用的全部层级状态,Vuex是作为一个“唯一数据源”存在,一个Vue应用仅包含一个store实例。
2.2.1 State获取状态
在Vuex组件中获取Vuex状态,即获取state中的数据:
单个状态通过this. $store.state.变量名(“变量名”指state中存在的变量)的方式来访问状态;
多个状态通过mapState获取,
import {mapState} from 'vuex';
computed:{
//将state中的变量映射为组件中的计算属性
...mapState(['state中的变量名','state中的变量名']);
}
2.2.2 this.$store.commit()与this. $store.dispatch()
一般vuex中的mutation 中的方法都是同步方法,提交mutation时不能有异步操作。并且只能在Action中处理异步操作。然后到mutations中修改state。this. $store.commit()提交的是mutations中的方法,this. $store.dispatch()提交的是actions中的方法.
一个例子如下:
首先是使用vuex,先下载依赖,注意vue2只能用vuex@3的版本,否则会报错:
npm install vuex@3 --save
在项目中新建store文件夹和index.js目录:
index.js的内容如下:
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const store = new Vuex.Store(
{
state:{
//state中保存的公共数据
num:10
},
getters:{
getPrice(state){
return state.num * 10;
}
},
mutations:{
changeNum(state, payload){
state.num += payload;
}
},
actions:{
changeNum({commit},payload){
setTimeout(
()=>{
commit('changeNum',payload)
},1000
);
}
}
}
);
export default store;
需要在main.js文件中注册:
之后就可以在任意组件中使用store了:
<template>
<body>
<div id="qqq" >
商品数量:{{this.$store.state.num}}个<br>
商品单价:10元<br>
订单金额:{{this.$store.getters.getPrice}}元<br>
<button @click="$store.commit('changeNum',5)">同步更新:数量+5button>
<button @click="$store.dispatch('changeNum',-5)">异步更新:数量-5button>
div>
body>
template>
<script>
import QRCode from 'qrcodejs2';
export default {
name: "qrCode",
data() {
return {
}
}
}
script>
效果如下:
点击左侧的按钮:
点击右侧的按钮,一秒后页面变化:
对上面的例子进行说明:
(1)store对象中getters与vue对象中的computed类似,方法定义的是计算属性,方法的参数为state。
(2)this.$ store.commit()可以同步调用mutations中定义的方法,this.$store.commit()的第一个参数指定调用的方法名,第二个参数传给mutations中定义的方法的第二个参数。this. $store.dispatch()与this. $ store.commit()类似,只不过它是异步调用。
2.3 that.$nextTick()
vue中数据和dom渲染是异步的,vue对象中的数值改变时dom渲染未完成,此时获取进行dom操作不是最新的,此时调用this. $nextTick()方法主要用在随数据改变而改变的dom应用场景中。
例如:
<template>
<section>
<h1 ref="hello">{{ value }}h1>
<button type="danger" @click="get">点击button>
section>
template>
<script>
export default {
data() {
return {
value: "Hello World ~",
};
},
methods: {
get() {
this.value = "你好啊";
console.log(this.$refs["hello"].innerText); // Hello World ~
// 如果直接这样打印,打印出来的结果不是我们想要的 "你好啊";,而是 Hello World ~,因为this.value = ‘ Hello World ~’ 它是异步的
this.$nextTick(() => {
console.log(this.$refs["hello"].innerText); // 你好啊
});
},
},
mounted() {},
created() {},
};
script>
上图中的效果是点击按钮,过一段很短时间按钮上方的文字由“Hello World ”变为“你好啊”,且控制台分别输出“Hello World`”和“你好啊”。
说明:this. $nextTick()就是等页面dom中的数据渲染完之后,再执行回调函数中的方法。
created()中使用的方法时,dom还没有渲染,如果此时在函数中进行dom赋值数据(或者其他dom操作)时是无用的。所以,此时this. $nextTick()会被大量使用,而与created对应的是mounted()则是在dom完全渲染后才开始渲染数据,所以在mounted()中操作dom基本不会存在渲染问题。
三、css中的transform属性
transform意为“改变、变形”,主要用于设置元素的形状改变,实现元素的2D或3D转换;该属性可以配合属性值(转换函数)来将元素进行旋转rotate、扭曲skew、缩放scale、移动translate、矩阵变形matrix以及不变换none。
3.1 旋转rotate(angle)
通过指定的角度参数对原元素指定一个2D旋转。angle是指旋转角度(单位为deg),如果设置的值为正数表示顺时针旋转,如果设置的值为复数,则表示逆时针旋转。
例如:
transform:rotate(45deg);//顺时针旋转30度
注意:旋转时默认以元素的中心点为基点进行旋转,可以通过transform-origin属性定义旋转的基点位置。
transform-origin属性:定义旋转的基点
语法:
transform-origin:x-axis y-axis z-axis;
默认值:
transform-origin:50% 50% 0
例如:
//实现以图形右下角为基点旋转30度的效果
transform-origin:100% 100%;
transform:rotate(45deg);
3.2 translate移动
translate(x,y):定义2D移动转化
x是第一个过渡值参数,y是第二个过渡值参数。如果未被提供,则值为0.也就是translate(x,y)表示对象进行平移,按照设定的x,y参数值,当值为负数时,反方向移动物体,其基点默认为元素中心点,也可以根据transform-origin进行改变基点。
例如:
transform:translate(50px,50px);//向右下方移动
transform:translateX(50px);//向右侧移动
transform:translateY(50px);//向下方移动
3.3 scale缩放
scale(x,y):定义2D缩放,x表示水平缩放的倍数,y表示垂直缩放的倍数 ,y是一个可选参数,如果没有设置y值,则表示x,y两个方向上的缩放倍数是一样的,并以x为准。
例如:
transform:scale(0.7,0.3);
transform-origin:100% 100%;
transform:scale(0.7,0.3);//以右下角为基点进行缩放
transform:scaleX(0.7);//在x轴方向(水平方向)进行缩放转换
transform:scaleY(0.7);//在y轴方向(垂直方向)进行缩放转换
3.4 skew扭曲
skew(x-angle,y-angle):定义沿着x和y轴进行2D倾斜转换。skew是用来对元素进行扭曲变形,第一个参数是水平方向扭曲角度,第二个参数是垂直方向扭曲角度。其中第二个参数是可选参数,如果没有第二个参数,那么y轴为0deg。
transform:skew(10deg,10deg);
transform-origin:100% 100%;//设置变形基点
transform:skewX(10deg);//沿着x轴的2d倾斜转换
transform:skewY(10deg);//沿着y轴的2d倾斜转换
四、setInterval()
setInterval()是JavaScript中的一个内置函数,它用于在指定的时间间隔内重复执行一段代码,实现周期性操作。
语法如下:
setInterval(function,milliseconds,param1,params,...)
参数说明:
function:必需,要重复执行的函数或代码块;
milliseconds:必需,重复执行的时间间隔(以毫秒为单位);
param1,param2,…:可选,传递给要执行的函数的参数,如果无需传递参数,则忽略此参数。
注意:
(1)如果setInterval()函数的第一个参数是一个函数,那么该函数会在每个时间间隔后被调用,直到计时器被取消。如果setInterval()函数的时间间隔设为0或负数,那么该函数会立即执行第一个参数所表示的函数或代码,并且不会周期性地执行。
(2)setInterval()方法会返回一个计时器ID,可以通过该计时器ID来取消计时器地执行,方法如下:
intervalId = setInterval(
function(){
console.log(new Date().toLocaleTimeString())
},1000
);
clearInterval(intervalId);
上例中intervalId是一个变量,用于保存setInterval()方法返回的计时器对象的ID,调用clearInterval()方法后,就可以取消计时器的执行。
例如:
var counter = 0;
maxNum = 5;
function myFunc() {
var date = new Date();
console.log(date.toLocaleTimeString());
counter++;
if (counter == maxNum) {
clearInterval(intervalId);
console.log('已打印' + maxNum + "次");
}
}
var intervalId = setInterval(myFunc, 1000);