今天给朋友们带来更改this指向的三种方法,以及它们的区别:
一:call用法
window.color = 'red';
document.color = 'yellow';
var s1 = {color: 'blue'};
function changeColor () {
console.log(this.color);
}
changeColor.call() //不传参数默认指向window
changeColor.call(window) //指向window
changeColor.call(document) //指向document
changeColor.call(this) //构造函数的this如果打括号调用默认指向window
changeColor.call(s1) //指向s1对象
//例二:
var Pet = {
words: '...',
speak: function (say) {
console.log(say + '' + this.words)
}
}
Pet.speak('123') //输出123...
var Dog = {
words: 'WangWangWang'
}
Pet.speak.call(Dog,'123') //输出123WangWangWang
二:apply用法:
window.number = 'one';
document.number = 'two';
var s1 = {number: 'three'};
function changeNum() {
console.log(this.number)
}
changeNum.apply(); //one
changeNum.apply(window); //one
changeNum.apply(document);//two
changeNum.apply(this);//one
changeNum.apply(s1);//three
//例二:
function Pet(words){
this.words = words;
this.speak = function(){
console.log(this.words)
}
}
function Dog(words){
Pet.call(this,words);//结果wang
// Pet.apply(this,arguments);//结果wang
}
var dog = new Dog('wang');
dog.speak(); //wang
apply与call的区别:
接收的参数不同
apply()方法接收俩个参数,一个是函数运行的作用域(this),另一个是参数数组。
call()方法第一个参数和apply()方法的一样,但是传递给函数的参数必须一 一列举出来。
语法:
apply([thisObj [,argArray]]);
调用一个对象的一个方法,另一个对象替换当前对象
call([thisObj [,arg1[,arg2[…,argn]]]]);
说明:
如果thisObj是null或者undefined的时候,默认指向window。
如果argArray不是一个有效数组或不是arguments对象,那么将导致一个TypeError,如果没有提供argArray和thisObj任何一个参数,那么Global对象将用作thisObj。
call方法可以用来代替另一个对象的一个方法,call方法可以将一个函数的对象上下文从初始的上下文改变为thisObj指定的新对象,如果没有提供thisObj参数,那么Global对象被用于thisObj。
三:bind的用法:
var obj = {
name: 'WuXiaoDi'
}
function printName() {
console.log(this.name)
}
var wuXiaoDi = printName.bind(obj)
console.log(wuXiaoDi) //function(){...}
wuXiaoDi() //WuXiaoDi
//例二:
function fn(a, b, c) {
console.log(a, b, c);
}
var fn1 = fn.bind(null, 'Dot');
fn('A', 'B', 'C'); //A B C
fn1('A', 'B', 'C'); // Dot A B
fn1('B', 'C'); // Dot B C
fn.call(null, 'Dot'); // Dot undefined undefined
//例三:实现函数珂里化
var add = function(x) {
return function(y) {
return x + y;
};
};
var increment = add(1);
var addTen = add(10);
increment(2) //3
addTen(2) //12
小总结:
Function.prototype.bind(thisArg) - - ES5
能够返回一个新函数,该新函数的主体与原函数主体一致,但当新函数被调用执行时,函数体中的this指向的是thisArg所表示的对象。
Function.prototype.call(this.Arg,val1,val2, …)
调用函数执行,在函数执行时将函数体中的this指向修改为thisArg所表示的对象
val1, val2, … 表示传递给调用函数的实际参数列表
Function.prototype.apply(thisArg, array|arguments)
调用函数执行,在函数执行时将函数体中的this指向修改为thisArg所表示的对象,
array|arguments 表示调用函数的参数列表,使用数组或类数组的格式
区别:
bind与call和apply的区别:
返回值的区别:
bind的返回值是一个函数,而call和apply是立即调用。
参数使用的区别:
bind与call一样是从第二个参数开始将想要传递的参数一 一写入。但call是把第二个及以后的参数作为fn方法的实参传进去,而fn1方法的实参实则是在bind中参数的基础上再往后排。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
一、搭建cli
1.事先安装好cnpm(淘宝镜像)
npm install -g cnpm --registry=https://registry.npm.taobao.org
1
2.cnpm install -g vue-cli
全局安装vue脚手架工具。(下载一次就好)
3.vue init webpack your_project_name
创建一个脚手架项目(每次创建需要)
eg:这时在命令行中有需要你填的信息{
你的项目名;
你的项目描述;
还有你想是否下载的插件(y/n);
}
4.使用 npm run dev来运行项目
就这样,一个简单的vue开发项目模板就这样下载完成了。
eg:
i 是install 的简写。
全局安装依赖:
cnpm i 依赖名
1
局部安装依赖:
cnpm i -D 依赖名
1
二、vue-router
一般事先安装模板时,已经安装上了。
可以查看package.json中。
如果没有安装
cnpm i -D vue-router
1
安装好之后,在src目录中会生成一个router目录,里面放着index.js,
一般有两种配置
第一种:
import Vue from 'vue';
import Router from 'vue-router';
Vue.use(Router);
export default new Router({
routes: [
// 一进入就显示页面
{
path: '/',
redirect: '/index'
},
{
path: '/',
component: pather => require(['../components/common/bodys.vue'], pather),
meta: { title: '主体' },
children:[
{
path: '/index',
component: pather => require(['../components/page/index.vue'], pather),
meta: { title: '系统首页' }
},
{
path: '/biaoge',
component: pather => require(['../components/page/biaoge.vue'], pather),
meta: { title: '基础表格' }
},
{
path: '/Tab',
component: pather => require(['../components/page/Tab.vue'], pather),
meta: { title: 'tab选项卡' }
},
{
path: '/jibenbiaodan',
component: pather => require(['../components/page/jibenbiaodan.vue'], pather),
meta: { title: '基本表单' }
},
{
path: '/fuwenben',
component: pather => require(['../components/page/fuwenben.vue'], pather),
meta: { title: '富文本编辑器' }
},
{
path: '/bianjiqi',
component: pather => require(['../components/page/bianjiqi.vue'], pather),
meta: { title: 'markdown编辑器' }
},
{
path: '/shangchuan',
component: pather => require(['../components/page/shangchuan.vue'], pather),
meta: { title: '文件上传' }
},
{
path: '/scharts',
component: pather => require(['../components/page/scharts.vue'], pather),
meta: { title: 'schart图表' }
},
{
path: '/tuozhuai',
component: pather => require(['../components/page/tuozhuai.vue'], pather),
meta: { title: '拖拽列表' }
},
{
path: '/quanxianceshi',
component: pather => require(['../components/page/quanxianceshi.vue'], pather),
meta: { title: '权限测试', permission: true }
}
]
},
{
path: '/login',
component: pather => require(['../components/page/login.vue'], pather)
},
{
path: '/cuowu404',
component: pather => require(['../components/page/cuowu404.vue'], pather)
},
{
path: '/cuowu403',
component: pather => require(['../components/page/cuowu403.vue'], pather)
},
{
path: '*',
redirect: '/404'
}
],
// 去掉#号
mode:"history"
})
第二种:
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
}
]
})
三、axios
先安装
cnpm i -D axios
1
然后在main.js写入
import axios from 'axios'
Vue.prototype.$axios = axios
1
2
3
这样就可以在组件中使用axios 获取数据了
loadData(){
this.$axios.get(['https://free-api.heweather.com/v5/weather?city=qingdao&key=1b47b16e4aa545eaa55a66f859ac0089'])
.then((response) => {
// success
console.log(response.data);
})
.catch((error) => {
//error
console.log(error);
})
},
四、vuex
1、安装
cnpm i -D vuex
1
2、然后需要手动创建一个文件夹store在src目录当中,
接着在store文件夹中创建store.js
例:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 0
},
mutations: {
increment: state => state.count++,
decrement: state => state.count--,
}
})
1
2
3
4
5
6
7
8
9
10
11
12
13
3、然后在main.js引入注册
import Vuex from 'vuex'
import store from './store/store'
Vue.use(Vuex)
new Vue({
el: '#app',
router,
store,
components: { App },
template: '<App/>'
})
比如在headers.vue使用vuex
<template>
<div class="headers">
<p>{{count}}</p>
<button @click="increment">+</button>
<button @click="decrement">-</button>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
name: 'headers',
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
},
methods: {
increment(){
this.$store.commit('increment')
},
decrement(){
this.$store.commit('decrement')
}
},
computed:{
count(){
return this.$store.state.count
},
}
}
</script>
<style scoped lang="scss" >
</style>
五、sass
1、需要安装sass
(1)安装node-sass
(2)安装sass-loader
(3)安装style-loader 有些人安装的是 vue-style-loader 其实是一样的!
cnpm install node-sass --save-dev
cnpm install sass-loader --save-dev
cnpm install style-loader --save-dev
1
2
3
2、接着需要更改build文件夹下面的webpack.base.config.js
'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')
function resolve (dir) {
return path.join(dirname, '..', dir)
}
module.exports = {
context: path.resolve(dirname, '../'),
entry: {
app: './src/main.js'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
}
},
module: {
rules: [
{
test: /.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
},
{
test: /.(png|jpe?g|gif|svg)(\?.)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
},
{ //从这一段上面是默认的!不用改!下面是没有的需要你手动添加,相当于是编译识别sass!
test: /.scss$/,
loaders: ["style", "css", "sass"]
}
]
},
node: {
// prevent webpack from injecting useless setImmediate polyfill because Vue
// source contains it (although only uses it if it's native).
setImmediate: false,
// prevent webpack from injecting mocks to Node native modules
// that does not make sense for the client
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty'
}
}
3、在你需要使用sass的地方写入即可
<style lang="scss" scoped="" type="text/css">
$primary-color: #333;
body {
color: $primary-color;
}
</style>
六、vue UI库
这里已著名的Element组件库为例
https://element.eleme.cn/#/zh-CN/component/carousel
1、安装
npm i element-ui -S
1
2、使用
在main.js写入
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)
1
2
3
4
3、然后在组件使用就可以了
例:轮播图
<template>
<el-carousel indicator-position="outside">
<el-carousel-item v-for="item in 4" :key="item">
<h3>{{ item }}</h3>
</el-carousel-item>
</el-carousel>
</template>
<style>
.el-carouselitem h3 {
color: #475669;
font-size: 18px;
opacity: 0.75;
line-height: 300px;
margin: 0;
}
.el-carouselitem:nth-child(2n) {
background-color: #99a9bf;
}
.el-carousel__item:nth-child(2n+1) {
background-color: #d3dce6;
}
</style>
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
在java的学习中,当接触到类这一章的时候,就会避免不了的接触到this关键字。
首先,this关键字指向的是当前对象的引用
作用:
this.属性名称
指的是访问类中的成员变量,用来区分成员变量和局部变量(重名问题)
class Test_08{
public static void main(String [] args){
//调用无参构造函数,
Person p1 = new Person();
p1.setAge(20);
p1.setName("张三");
p1.setGender("男");
System.out.println(""+p1.getName()+" 今年"+p1.getAge()+"岁 性别为:"+p1.getGender());
}
}
class Person{
private String name;
private int age;
private String gender;
Person(){}
Person(String name,int age,String gender){
this.name = name;
this.age = age;
this.gender = gender;
}
public void setName(String name){
name = name;
}
public String getName(){
return name;
}
public void setAge(int age){
age = age;
}
public int getAge(){
return age;
}
public void setGender(String gender){
gender = gender;
}
public String getGender(){
return gender;
}
}
对Test_08运行后发现,调用的set方法并没有对 对象中的变量进行赋值,是因为,传入的参数变量名与类中属性变量名重复,因此我们在set方法和有参构造方法中加上了this.类属性名称,这样就可以完成对 对象变量的赋值。如下图:
this.方法名称
用来访问本类的成员方法
this();
访问本类的构造方法
()中可以有参数的 如果有参数 就是调用指定的有参构造
注意事项:
1.this() 不能使用在普通方法中 只能写在构造方法中
2.必须是构造方法中的第一条语句
例如,当我们把this()放在有参构造函数的末尾时,例如用this("哈哈");我们先不管语法是否有错误,试着按照程序的运行来判断一下结果,我们可以看出,当在创建对象时,假定调用含有this(“哈哈”)的构造函数,则刚开始存放的值,会被this(“哈哈”)调用的只含有一个参数的构造函数覆盖,也就是说,最后的name会变成“哈哈”,这是与我们的初衷相违背的,而且运行结果也是报错,
当我们换到构造方法的第一句时,则不会有这种错误,因为它并不会影响到后面name的赋值。
我们接下来把this语句放在构造函数的第一句位置,
就不会有报错
————————————————
版权声明:本文为CSDN博主「BetterShon」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42386014/article/details/81138684
实现导航的左右滑动类似于腾讯新闻,网易等导航,一下贴上代码:
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Untitled Document</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<style>
body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,form,input,p,th,td,table,textarea,select{margin:0;padding:0;}
h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}
th,em{font-style:normal;font-weight:normal;}
ol,ul{list-style:none;}
table{border-collapse:collapse;border-spacing:0;}
img,a img{border:0;}
body{font:12px 'Microsoft YaHei',Arial;color:#666;background-color:#eee;}
.nav{width:100%;overflow:hidden;margin:0 auto;height:35px;position:relative; line-height:35px;background-color:#000;}
.nav ul{position:absolute;left:0;top:0;width:640px;z-index:1;}
.nav ul li{width:80px; float:left; overflow:hidden;}
.nav a{color:#fff;width:100%; display:block; text-decoration:none; text-align:center;}
</style>
<body>
<div class="nav" id="nav">
<ul>
<li><a href="#">菜单1</a></li>
<li><a href="#">菜单2</a></li>
<li><a href="#">菜单3</a></li>
<li><a href="#">菜单4</a></li>
<li><a href="#">菜单5</a></li>
<li><a href="#">菜单6</a></li>
<li><a href="#">菜单7</a></li>
<li><a href="#">菜单8</a></li>
<li><a href="#">菜单9</a></li>
<li><a href="#">菜单10</a></li>
</ul>
</div>
<script>
window.Swipe = function(b, a) {
if (!b) {
return null
}
this.options = a || {};
this.index = this.options.startSlide || 0;//开始的导航页的第几屏
this.speed = this.options.speed || 300;//速度
this.lwidth = this.options.width || 80;//导航li宽度
this.delay = this.options.auto || 0;//自动滚动菜单速度0为不自动滚动
this.container = b;//在那个容器内
this.element = this.container.children[0];//
this.setup();
if (this.delay != 0) {
this.begin();
}
if (this.element.addEventListener) {
this.element.addEventListener("touchstart", this, false);
this.element.addEventListener("touchmove", this, false);
this.element.addEventListener("touchend", this, false);
this.element.addEventListener("touchcancel", this, false);
this.element.addEventListener("webkitTransitionEnd", this, false);
this.element.addEventListener("msTransitionEnd", this, false);
this.element.addEventListener("oTransitionEnd", this, false);
this.element.addEventListener("transitionend", this, false);//监听过度动画是否结束
window.addEventListener("resize", this, false)
}
};
Swipe.prototype = {
//设置其基本样式
setup: function() {
this.slides = this.element.children;
this.width = Math.ceil(("getBoundingClientRect" in this.container) ? this.container.getBoundingClientRect().width: this.container.offsetWidth);
if (!this.width||this.slides.length < 1) {//没有子节点,获取不到屏幕宽度均返回
return null
}
this.element.style.width = Math.ceil(this.slides.length this.lwidth) + "px";
var a = this.slides.length;
while (a--) {
var b = this.slides[a];
b.style.width = this.lwidth + "px";
}
this.slide(this.index, 0);
},
slide: function(a, c) {
var b = this.element.style;
if (c == undefined) {
c = this.speed
}
//过度效果需要花费时间
b.webkitTransitionDuration = b.MozTransitionDuration = b.msTransitionDuration = b.OTransitionDuration = b.transitionDuration = c + "ms";
this.index = a
//console.log(a this.width,Math.ceil((this.slides.lengththis.lwidth)/this.width));
if(a this.width>(Math.ceil((this.slides.lengththis.lwidth)/this.width)-1)this.width){
// b.MozTransform = b.webkitTransform = "translate3d(" + -((Math.ceil((this.slides.lengththis.lwidth)/this.width)-1) this.width) + "px,0,0)";
// b.msTransform = b.OTransform = "translateX(" + -((Math.ceil((this.slides.lengththis.lwidth)/this.width)-1) this.width) + "px)";
return false;
}
else{
b.MozTransform = b.webkitTransform = "translate3d(" + -(a this.width) + "px,0,0)";
b.msTransform = b.OTransform = "translateX(" + -(a this.width) + "px)";
}
},
getPos: function() {
return this.index
},
//前一个,
prev: function(a) {
this.delay = a || 0;
clearTimeout(this.interval);
// console.log(this.index);
if (this.index) {
this.slide(this.index - 1, this.speed)
//console.log( this.index);
} else {
this.slide(this.length - 1, this.speed)
}
},
//后一个
next: function(a) {
this.delay = a || 0;
clearTimeout(this.interval);
if (this.index < this.length - 1) {
this.slide(this.index + 1, this.speed)
} else {
this.slide(0, this.speed)
}
},
begin: function() {
var a = this;
console.log(a);
this.interval = (this.delay) ? setTimeout(function() {
a.next(a.delay)
},
this.delay) : 0
},
stop: function() {
this.delay = 0;
clearTimeout(this.interval)
},
resume: function() {
this.delay = this.options.auto || 0;
this.begin()
},
handleEvent: function(a) {
switch (a.type) {
case "touchstart":
this.onTouchStart(a);
break;
case "touchmove":
this.onTouchMove(a);
break;
case "touchcancel":
case "touchend":
this.onTouchEnd(a);
break;
case "webkitTransitionEnd":
case "msTransitionEnd":
case "oTransitionEnd":
case "transitionend":
this.transitionEnd(a);
break;
case "resize":
this.setup();
break
}
},
transitionEnd: function(a) {
if (this.delay) {
this.begin()
}
},
onTouchStart: function(a) {
this.start = {
pageX: a.touches[0].pageX,
pageY: a.touches[0].pageY,
time: Number(new Date())
};
// console.log(this.start)
this.isScrolling = undefined;
this.deltaX = 0;
this.element.style.MozTransitionDuration = this.element.style.webkitTransitionDuration = 0;
a.stopPropagation()
},
onTouchMove: function(a) {
if (a.touches.length > 1 || a.scale && a.scale !== 1) {
return
}
this.deltaX = a.touches[0].pageX - this.start.pageX;
if (typeof this.isScrolling == "undefined") {
//判断是横向还是树向滑动
this.isScrolling = !!(this.isScrolling || Math.abs(this.deltaX) < Math.abs(a.touches[0].pageY - this.start.pageY))
}
if (!this.isScrolling) {
a.preventDefault();
clearTimeout(this.interval);
this.deltaX = this.deltaX / ((!this.index && this.deltaX > 0 || this.index == this.length - 1 && this.deltaX < 0) ? (Math.abs(this.deltaX) / this.width + 1) : 1);
this.element.style.MozTransform = this.element.style.webkitTransform = "translate3d(" + (this.deltaX - this.index * this.width) + "px,0,0)";
a.stopPropagation()
}
},
onTouchEnd: function(c) {
var b = Number(new Date()) - this.start.time < 250 && Math.abs(this.deltaX) > 20 || Math.abs(this.deltaX) > this.width / 2,
a = !this.index && this.deltaX > 0 || this.index == this.length - 1 && this.deltaX < 0;
if (!this.isScrolling) {
this.slide(this.index + (b && !a ? (this.deltaX < 0 ? 1: -1) : 0), this.speed)
}
c.stopPropagation()
}
};
//开始调用插件
var slider=new Swipe(document.getElementById('nav'),{speed:500,auto:0,width:100,col:4,});
</script>
</body>
</html>
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
app.vue
<template>
<div id="app">
<transition :name="transitionName">
<keep-alive >
<router-view v-if="$route.meta.keepAlive" class="Router"></router-view>
</keep-alive>
</transition >
<transition :name="transitionName">
<router-view v-if="!$route.meta.keepAlive" class="Router"></router-view>
</transition >
<Play></Play>
</div>
</template>
<script>import Play from './components/play'
export default {
name: 'App',
data () {
return {
transitionName: 'slide-left'
}
},
watch: {
'$route' (to, from) {
// 切换动画
let isBack = this.$router.isBack // 监听路由变化时的状态为前进还是后退
if (isBack === true) {
this.transitionName = 'slide-right'
// from.meta.keepAlive = false
// to.meta.keepAlive = true
} else {
// from.meta.keepAlive = true
// to.meta.keepAlive = false
// this.transitionName = 'slide-left'
if (this.$route.path.split('/').length < 3) {
this.transitionName = 'slide-fade'
} else {
this.transitionName = 'slide-left'
}
}
this.$router.isBack = false
}
},
components: {
Play
}
}
</script>
<style>
.Router {
font-family: Roboto, Lato, sans-serif;
position: absolute;
width: 100%;
height: 100%;
padding-bottom: 60px;
transition: all .377s ease;
box-sizing: border-box;
overflow: auto;
}
.slide-left-enter,
.slide-right-leave-active {
opacity: 0;
-webkit-transform: translate(100%, 0);
transform: translate(100%, 0);
}
.slide-left-leave-active,
.slide-right-enter {
opacity: 0;
-webkit-transform: translate(-100%, 0);
transform: translate(-100% 0);
}
.ovf {
overflow: hidden;
}
.center {
width: 95%;
margin: 0 auto;
overflow-y: hidden;
}
li {
list-style: none;
}
</style>
路由配置
{
path: '/playListDetail/:id',
name: 'playListDetail',
component: pather => require(['../components/playListDetail.vue'], pather),
meta: {
title: '歌单详情',
keepAlive: true,
isBack: false
}
},
返回事件
back () {
this.$router.go(-1)
this.$router.isBack = true
}
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
在我们开发的过程中,应该始终考虑性能。而本文列举了有效提高系统性能的12个方法,如果朋友们有更多的技巧请在吴小迪的博客下方评论,谢谢。
性能是创建网页或应用程序时最重要的一个方面。没有人想要应用程序崩溃或者网页无法加载,或者用户的等待时间很长。根据Kissmetrics,47%的访问者希望网站在不到2秒的时间内加载,如果加载过程需要3秒以上,则在40%的访问者会离开网站。
考虑到以上这些数字,你在创建Web应用程序时应始终考虑性能。为了帮助你开始,以下提供了有效提高应用程序性能的12种方法:
一:在浏览器中缓存
要这样做有俩种选择。第一种是使用JavaScript Cache API,我们可以安装service worker来使用它。第二种是使用HTTP协议缓存。
访问某个对象通常要用脚本。通过把重复访问的对象存储在用户定义的变量中,以及在后续对该对象的引用中使用变量,可以立即实现性能的提升。
二:定义执行的上下文
为了有效地衡量你在程序中加入的任何改进,你必须创建一组定义良好的环境,以便测试代码性能。
对所有JavaScript引擎的所有版本进行性能测试和优化实际上是不可行的。但是,在单一的环境中进行测试并非一个好习惯,因为你可能会得到片面的结果。因此,建立多个定义良好的环境并测试代码是否有效非常重要。
三:删除未使用的JavaScript
此步骤不仅会缩短传输时间,还会缩短浏览器分析和编译代码所需的时间。为此,你必须考虑以下几点:
如果你检测到一个用户未使用的功能,最好删除所有与之相关的JavaScript代码,这样网站的加载速度会更快,用户也有更好的体验。
还有可能,你错误地加入了一个并不需要的库,或者你有依赖项,这些依赖项提供的功能在所有浏览器中原本就有,那么你无需再增加多余的代码。
四:避免使用太多内存
你应该始终给内存加一条限制,那就是只有绝对必须的内容才能使用内存,因为你无法知道运行应用程序的设备到底需要多少内存。只要你的代码要求浏览器保留新的内存,浏览器的垃圾收集器就会被执行,并停止JavaScript的运行。如果经常发生这种情况,页面将变慢。
五:推迟不必要的JS加载
用户希望页面快速加载,但并非所有函数都需要在页面的初始加载时就可用。如果用户必须执行某个操作才能执行某个函数(例如,通过单击某个元素或更改选项卡),那么你可以将该函数的加载推迟到初始页面加载之后。
通过这种方式,你可以避免加载和编译那些会延迟页面初始显示的 JavaScript 代码。页面完全加载后,我们可以再开始加载这些功能,以便它们在用户开始交互时立即可用。在 RAIL 模型中,Google 建议将此延迟加载以 50 毫秒为单位进行,这样就不会影响用户与页面的交互。
六:避免内存泄漏
如果内存正在泄漏,则加载的页面将保留越来越多的内存,并最终占用设备的所有可用内存并严重影响性能。你可能见过此类故障(并且可能对此类故障感到懊恼),例如在带有轮播或图像滑动条的页面上。
在 Chrome 开发者工具中,你可以通过在“性能”标签中记录时间线来分析你的网站是否存在内存泄漏。通常,内存泄漏的原因是,你从页面中删除了 DOM,但有一些变量还在引用这些 DOM,因此,垃圾收集器无法消除它们。
七:适当的使用Web worker
当你执行耗时很长的代码时,请使用 Web worker。根据 Mozilla 开发人员网络 (MDN) 文档:“Web Worker 可以在与 Web 应用程序的主执行线程分开的后台线程中运行脚本操作。这样做的好处是你可以在一个单独的线程中执行耗时又费力的的处理,同时让主(通常为 UI)线程运行而不被阻塞或减慢。”
Web worker 允许代码执行处理器密集型计算,而不阻塞用户界面线程。Web Worker 允许你生成新线程并将工作委托给这些线程以获得的性能。这样,通常会阻碍其他任务且需要长时间运行的任务将被传递给 worker,从而让主线程可以在无阻碍的情况下运行。
八:适当将DOM元素保存在局部变量中
访问 DOM 会很慢。如果要多次读取某元素的内容,最好将其保存在局部变量中。但记住重要的是,如果稍后你会删除 DOM 的值,则应将变量设置为“null”,不然会导致内存泄漏。
九:优先访问局部变量
JavaScript 首先搜索以查看变量是否存在于本地,然后才在更高级别的作用域内逐步搜索到全局变量为止。将变量保存在本地作用域内能让 JavaScript 更快地访问它们。
局部变量是基于最具体的作用域的,并且可能会穿过多个级别的作用域,因此查找这一动作可能导致出现通用的查询。在一个它前面没有变量声明的局部变量中定义函数作用域时,需要在每个变量之前加上 let 或 const,以便定义当前作用域,防止查找并加速代码执行。
十:避免使用全局变量
因为脚本引擎在从函数或其他作用域内引用全局变量时需要逐一查看作用域,所以当本地作用域丢失时,该变量将被销毁。如果全局作用域中的变量无法在脚本的生命周期内持续存在,则性能将得到改善。
十一:实施一些优化方案
始终使用计算复杂度的算法和最佳的数据结构来解决任务。
重写算法以获得相同的结果和更少的计算。
避免递归调用。
给重复的函数加入变量、计算和调用。
分解和简化数学公式。
使用搜索数组:用它们来获取基于另一个的值,而不是使用 switch/case 语句。
使条件总是更有可能为真,以更好地利用处理器的推测执行。
如果可以,请使用位级运算符替换某些操作,因为这些运算符的处理周期较短。
十二:使用工具检测问题
Lighthouse 是一个很好的网页性能工具,它可以帮助你审核性能、可访问性、最佳实践和 SEO。谷歌 PageSpeed 旨在帮助开发人员了解网站的性能优化和潜在可改进的方面。这些组件旨在识别网站是否符合 Google Web 性能最佳实践,以及将调整过程自动化。
在 Chrome 中,你还可以使用主菜单中的“更多工具”选项来查看每个选项卡使用的内存和 CPU。对于更高级的分析,你可以使用 Firefox 或 Chrome 中的开发人员工具“性能”视图来分析不同的指标,例如:
devtools 的性能分析允许你在加载页面时模拟 CPU 消耗、网络和其他指标,以便识别和修复问题。
为了更深入地了解,建议你使用 JavaScript Navigation Timing API,它允许你详细测量代码的每个部分从编程本身中获取的内容。
对于基于 Node.js 构建的应用程序,NodeSource Platform 也是一种非常好、影响低的方式,它可以在非常精细的级别上探索应用程序性能。
全面的 Node.js 指标可帮助你识别内存泄漏源或其他性能问题,并更快地解决这些问题。
最后的说明在代码的可读性和优化之间保持平衡很重要。代码由计算机解释,但我们需要确保代码将来可以由我们自己或其他人维护,因此它们需要易于理解。
请记住:应始终考虑性能,但不应将性能凌驾于错误检测和功能添加之上。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
本文主要记录几种提升基于深度学习的图像语义分割精度的方法,以防忘记!
By zhengzibing2011, 2017年10月21日-星期六
1
1.图像语义分割面临的挑战
(1).特征分辨率减小:主要是由神经网络中的重复最大池化和降采样(stride跨越)操作造成的,而采用此种操作的原因是
A.降维,以免参数过多难以优化;
B.基于DL的语义分割是从用于分类任务的CNN转化而来,而在分类任务中,分类器要求对输入的空间变换具有不变性,池化恰能满足这样的要求。
(2).不同scale下的目标存在的状况:主要是目标在multi-scale图像中的状态造成的,因为在同一种尺度下,不同目标的特征往往响应并不相同。如需要在较大的尺度下才能较好地提取图像中比较小的目标,而较大的目标为了获取全局性信息也必须在较小的尺度下才能实现。
(3). CNN的空间不变性造成定位精度的下降:对于分割任务而言,由于pooling操作引起的分类器对输入的空间变换具有不变性丢失空间信息,内在的限制了分割的空间精度。
2.潜在的解决方法
FCN作为将CNN应用于semantic segmentation的forerunner,贡献巨大。但不可回避,其提出的方法具有一些不足。为保证却终的feature map不至于过小,FCN的conv1引入pad=100,引入了较大的噪声;
32倍upsample(deconvolution)非常粗糙,而且deconvolution的filter不可学习; skip architecture虽能有效提高精度,但需要3次训练即FCN-32s->FCN-16s->FCN-8s。除skip architecture外。随着研究的深入,针对以上挑战,有以下几种方法解决:
(1). Encoder-Decoder结构
采用此种思想的代表为DeconvNet,SegNet,其基本思想是采用一种对称结构将由于pooling操作而减小的feature map通过逐步的upsample逐渐恢复到原图像大小,同时在upsample阶段,融合了subsample中pooling index,具体细节可参见原文。
(2). Atrous convolution
feature map的减小是由于pooling造成的,为确保一定精度的feature map,能否不使用或减少使用pooling呢?理论上是可行的,但如果这样做会使得需要优化的参数过多,重要的是难以基于以前的model进行fine-tuning,atrous convolution解决了这个问题。
在DeepLab中令pool4,pool5的stride=1,再加上1 padding,这样经过pooling后feature map大小不变,但后层的感受野发生了变化,为使感受野不变,后面的卷积层使用atrous convolution,其作用是在不增加参数的前提下,增加感受野。因此,解决了feature map空间分辨率下降的问题。
(3). ASPP
针对不同scale下的目标存在的状况问题,可通过两种方法解决:
A.标准的多尺度处理方法,用共享相同参数的并行CNN的分支,从不同尺度的Input image中提取score map,然后进行双线性差值,最终对它们进行融合,在不同尺度上获得每个位置的最大响应。训练和测试时均这样处理,比较繁琐的是需要计算输入图像的每个尺度在各layer上的特征响应。
B.基于任意尺度上的区域都可以用在这个单一尺度上重采样卷积特征进行有效地分类的思想,使用多个不同采样率上的多个并行多空卷积,每个采样率上提取的特征再用单独的分支处理,融合生成最后的结果。
(4). FC-CRF
CRF几乎可以用于所有的分割任务中图像精度的提高。CNN可用于对图像中的目标进行分类并预测出目标的大致位置,但并不能真正描绘他们的边界。因此,将DCNN的识别能力和全连接CRF优化定位精度耦合在一起,能成功的处理定位挑战问题,生成了的语义分割结果。全连接CRF理论较为复杂,在此不作阐述。类似的概率图模型(PGM)还有MRF,G-CRF(高斯-条件随机场)。
3.总结
目前,暂且先记录以上4种提高分割精度的方法。后续若有新的方法,予以追加!
————————————————
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
JS的作用域一共有三个范围,分别是:
全局作用域
定义在所有函数之外的变量,其作用范围是在整个脚本中
局部作用域(函数作用域)
使用var定义在函数内部的变量,其作用范围是整个函数结构,超出函数 {} 花括号的范围则不能使用。
块级作用域
ES6声明变量的方式:let / const
let 变量名 = 变量值;
const 变量名 = 变量值;
PS:注意: 使用const修饰的变量,赋值确定后,不允许再重新赋值。(一般修饰常量或者数组对象之类的)
而且必须给予初始值。
const修饰数组对象后虽然不可以再对变量进行等号赋值了,但是还是可以用数组和对象的方法去改变它的内部结构。
IIFE(立即调用函数表达式 - - 自执行匿名函数):
英文全名:(Immediately Invoked Function Expression)
语法:
//这三种都属于IIFE写法
(function () {})();
(function () {}());
+function () {}();
//作用与ES6当中的let是一样的,只不过用这个语法是为了解决个别浏览器的兼容问题。
1
2
3
4
5
声名提升:
将使用var定义的变量声名提升到对应作用域的最顶部,赋值部分位置不变。
使用ES6的let与const没有声名提升。
函数的定义也存在声名提升:
如果是声名的方式定义的函数,将整个函数(声名及函数主体)都提升到作用域的最顶部。
如果是表达式的方式定义的函数,只提升声名,不提升赋值(函数主体部分)
示例:
//在声名函数前面输出它。输出的结果就是整个声名函数的内容
console.log(testArg)
function testArg(a, b, c){
console.log(arguments)
}
1
2
3
4
5
输出结果:
//在函数表达式之前输出函数
console.log(testArg)
var testArg = function(a, b, c) {
console.log(arguments)
}
1
2
3
4
5
输出结果:
这就是声名提升的特点,只提升声名部分,不提升赋值部分。大家一定要牢牢记住哦~
————————————————
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
很多朋友在开发的过程中要把ECharts图标做成自适应浏览器宽高的效果。于是去翻看ECharts官网发现了resize方法,结果用了之后发现没用,而且根本不知道什么原因。
解决办法:
不能给ECharts的容器设置固定的宽高。
宽度要写百分比
高度要写vh
然后再搭配resize方法才可以实现根据浏览器大小而改变大小的功能
示例代码:
let ECharts = echarts.init(document.getElementById('wrapBox'));
//ECharts的配置项和数据
let option = {
title: {
text: 'demo'
},
tooltip: {},
legend: {
data: ['dataSource']
},
xAxis: {
data: ['aa', 'bb', 'cc']
},
yAxis: {},
series: [{
name: 'dataSource',
type: 'bar',
data: [2, 5, 6],
}]
};
//配置图表数据及配置项
ECharts.setOption(option);
//根据浏览器大小改变大小
window.onresize = () => {
ECarts.resize();
//如果有多个表变动在下方依次写下去就可以了
}
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
推荐使用 vue-wechat-title
vue-wechat-title作用
Vuejs 单页应用在iOS系统下部分APP的webview中 标题不能通过 document.title = xxx 的方式修改 该插件只为解决该问题而生(兼容安卓)
已测试APP
微信
QQ
支付宝
淘宝
安装
npm install vue-wechat-title --save
1
用法
1,在 main.js 中引入
import VueWechatTitle from 'vue-wechat-title'
Vue.use(VueWechatTitle)
1
2
2,在路由文件 index.js 中给每个路由添加 title
// 挂载路由
const router = new Router({
mode: 'history',
routes:[
{
path: '/',
name: 'Index',
component: Index,
meta: {
title: '首页' // 标题设置
}
},
{
path: '/lists',
name: 'Lists',
component: Lists,
meta: {
title: '列表' // 标题设置
}
}
]
});
3,在 app.vue 中修改 router-view 组件
<router-view v-wechat-title='$route.meta.title'></router-view>
1
自定义加载的图片地址 默认是 ./favicon.ico 可以是相对或者绝对的
<div v-wechat-title="$route.meta.title" img-set="/static/logo.png"></div>
1
ok !重启看看
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
蓝蓝设计的小编 http://www.lanlanwork.com