php文件操作

  1. 文件操作,
  2. 目录操作(文件夹操作)

1.文件的读取

$res = file_get_contents('php3.txt');  //读  一般配合 file_put_contents 写使用

// $res =file_get_contents('http://www.baidu.com');

2.文件的写入

$a = file_get_contents('http://www.baidu.com'); //或者其他文件
$res =file_put_contents('php3.txt','写入方式二 常用');  //从头写入,覆盖  也可以是上面的$a
if($res){
    echo '写入成功';
}else{
    echo '写入失败';
}

3.文件的删除

// $res = unlink('6.txt');
// if($res){
//     echo '删除成功';
// }else{
//     echo '删除失败';
// }

php文件夹操作

//创建文件夹📂
// $rem = mkdir('test1');
// if($res){
//     echo '创建成功';
// }else{
//     echo '创建失败';
// }

读取文件夹📂

$xx = scandir('test'); //读取文件夹,以数组形式返回
foreach ($xx as $key => $value) {
    // $xx[$key] = iconv('gbk',"utf-8",$value); //如果中文文件夹乱码加上这个就好了
    $url = "test/".$value;
    if(is_file($url)){
        echo "<font color='red'>".$value.'</font><br>';
    }else{
        echo "<font color='green'>".$value.'</font><br>';
    }
}
// print_r ($xx);

删除文件夹

// $res = rmdir('test1');  //这个只能删除空文件夹


//删除文件夹及内部文件
function removeDir($path){
    $arr = scandir($path);
//    print_r($arr);die;
    if(count($arr)>2){
        //目录不为空
        for($i=2;$i<count($arr);$i++){
             $url = $path.'/'.$arr[$i];
            //$arr[$i] = 1.txt  test1
             if(is_dir($url)){
                 //为目录. 
                 removeDir($url);
             }else{
                 //是文件
                unlink($url);
             }
        }
    }
    $res = rmdir($path);
    return $res;
}
// removeDir($path)

获取文件的最后创建时间

//$res = filectime('1.txt')  //返回时间戳
//echo date('Y-m-d H:i:s',$res)

//file_exists: 判断文件是否存在;
if(!file_exists('test')){
    mkdir('test');
}

//判断是否可读
is_readable(filename);
//判断是否可写
is_writable(filename);

修改目录权限

chmod('test', 0755); //7=1+4+2   5=1+4  
// 1.执行权限(1)  2.读取(4) 3.可写(2)
//如果是手动创建的是不能用代码来更改权限的

页面跳转

header('Location:file.php') //跳转显示file.php文件

php入门

本地服务器

1.打开本地服务器

sudo apachectl start

2.进入服务器

/jas/资源库/webserver/Documents/    可以改权限

里面放文件访问,打开127.0.0.1

3.结束

sudo apachectl stop

XAMPP服务

1.打开阿帕奇

2.测试版本,在服务器里放入一个test.php文件

3.在test.php文件里写上

出现版本号

4.访问http://localhost/class/test/test.php

php语法入门

1.echo只能打印字符串和数字

echo "hello world!";
echo "<br>";
echo (111);//数字不加引号可以

2.变量声明

$a = "你好";
echo $a;

$b="hello";
$hello="hello jas";
echo $$b;                //hello jas

3.变量解析,字符串连接使用“.”

$c=”你好”;
$res1=”张三”;
echo $c.$res1; //你好张三

$res2="张三$c";//必须双引号才会解析
$res2="张三'$c'";//张三'你好'
echo $res2;

4.自动转换

$d=1;
$e="2";
echo gettype($d+$e);//整型integer
echo ($d+$e);//3

5.强制转换

echo gettype($e);  //string
echo gettype((int)$e);//integer

6.字符串定义方式二:

// 定界符,一般定义长字符串;注意,结尾顶头写,前后不许有空格
$str=<<<AAA
fdffdfdfdfdfdff
AAA;
echo $str;//fdffdfdfdfdfdff

7.php不会传值

$arr1=[1,2,3];
$arr2=$arr1;//想传值加&符号
$arr2[0]=5;
print_r($arr1);//Array ( [0] => 1 [1] => 2 [2] => 3 )


$arr1=[1,2,3];
$arr3=&$arr1;//想传值加&符号
$arr3[0]=5;
print_r($arr1);//Array ( [0] => 5 [1] => 2 [2] => 3 )

8.数组定义方式

$arr=array("张三","李四","王二");//索引数组
print_r($arr);    //Array ( [0] => 张三 [1] => 李四 [2] => 王二 )
var_dump();    // array(3) { [0]=> string(6) "张三" [1]=> string(6) "李四" [2]=> string(6) "王二" }

数组遍历

//遍历
echo "<hr/>"; 
$arr = array('武汉'=>'三大火炉之一','上海'=>'魔都');
foreach ($arr as $key => $value) {
    echo $key.':'.$value;
    echo "<hr/>"; 
}

$arr2 = array(
    '电子产品'=>array('iphone'=>'64g','华为'=>'32g'),
    '食品'=>array('旺旺'=>'雪饼','百事'=>'可乐'),
);

foreach ($arr2 as $key => $value) {
    foreach ($value as $key1 => $value1) {
        echo $key.'-'.$key1.'-'.$value1."<hr/>";
    }
}

数组操作

$arr = array('张三','李四','王二');
unset($arr[0]); //删除arr中的第一个
print_r($arr); 
echo "<hr/>";

//is_type  判断是否是某种类型,会返还boolean值
echo is_array($arr);
echo "<hr/>";

echo in_array('李四',$arr); //判断 张三是否在array中
echo "<hr/>";

运算符等其他操作

//运算符等基本语法和JS基本都是一样的,来列列不同点
$a = 4;
echo '$a+=5 ---'.$a+=5;  //9
echo '<hr>';
echo '$a.=5 ---'.$a.=5;  //95

// && == and(与)   || == or(或)   !(非)  xor(亦或)
//  !=  ==  <> (不等于)
echo '<hr>';
$a = mt_rand(1,10);  //随机一个1-10的数  包含1和10
echo $a;
echo '<hr>';

$b = $a <= 5 ? '小于5' : '大于5';  //记得要用一个新的值保存
echo $b;
echo '<hr>';

//有返还至的函数
// 5!= 5*4*3*2*1   阶乘

function jiechen($num){
    if($num>0){
        return jiechen($num-1)*$num;
    }else{
        return 1;
    }
}

echo jiechen(5);

echo '<hr>';
$a = 5;
function test(){
    global $a;
    echo $a;  //不能直接获取到外面的$a 需要用全局变量设置一下,或者传参

    $GLOBALS['b'] =$a;  //传递函数里面的变量到外面
}
test();
echo '<hr>';
echo $GLOBALS['b'];

echo '<hr>';
function digui(){
    static $a=5;  //静态变量,常驻内存,每次执行函数$a都存在不会被重新赋值
    if($a>0){
        echo $a;
        $a--;
        digui();
    }else{
        return false;
    }
}
digui();

echo '<hr>';
$arr = [1,2,3];
$arr[] ='zhangsan';  //向数组中添加张三到最后,  也是方式三定义数组
array_unshift($arr,'lisi');
array_push($arr,'wanger');
print_r($arr);

$arr =range(1,10);   //生成一个1-10的数组  只能是整数
count($arr);  //数组长度

echo '<hr>';
$str = 'a,b,c,d';
strlen($str); //字符串长度  注意 一个中文字符站三个字节,长度是三
$arr=explode(',',$str);  //相当于split
print_r($arr);
$str = implode('-',$arr);
echo $str;

$arr = ['a','c','d','b'];
sort($arr); //顺序
rsort($arr);//倒序

// $res = strops($str,'a');  //找a出现的位置
// $res = str_replace('x','y',$res); // 把$res中 x替换为y

echo '<hr>';
$arr = array(1=>'zhangsan');
$str = json_encode($arr);   //转为字符串
echo $str;
echo '<hr>';
$arr = json_decode($str);  //字符串解码为对象
print_r($arr);

$a = '<h1>这是解析后的好</h1>';  //直接输出会以标签的方式显示
echo htmlspecialchars($a);  //将以字符串的方式返还成实体

数据库基本操作一

本文先来谈谈MYSQL内部SQL语言的基本操作

MySQL是一种关联数据库管理系统,关联数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。MySQL所使用的 SQL 语言是用于访问数据库的最常用标准化语言。搭配 PHP 和 Apache 可组成良好的开发环境。

先来安装下xampp->通过网址localhost/phpmyadmin进入mysql管理系统

数据库的操作

数据库的操作无非是增删改查,下面就是针对这几条简单的进行罗列…

创建数据库

如下所示点击new 然后填入自己的数据库名字,后面的排序规则这里选utf8_general_ci,
这里选ci的原因是ci是 case insensitive, 即 "大小写不敏感", a 和 A 会在字符判断中会被当做一样的;方便查询..

创建数据表

字段数选择比我们要创建的列表书+1,为了设置唯一id,username选择VARCHAR,勾选非空说明可以为空,id一栏勾选A_I注释,然后会弹出一框框,表明自增索引,直接执行就OK了

增加数据

//增加数据
INSERT INTO 数据表名(字段一,字段二,字段三) VALUES (值一,值二,值三)
INSERT INTO   users(username,pwd,age) VALUES('张三',123,25);
如下所示,点击SQL,输入SQL语法添加相关数据,点击右下的执行即可创建一条属于你自己的数据

删除数据

//DELETE FROM 表名  WHERE  条件;  
DELETE FROM users WHERE username='李四';

修改数据

//修改 
//UPDATE 表名 SET 设置的内容 WHERE 条件; 
UPDATE `users` SET `username`='李四',`pwd`=11111,`age`=222  WHERE id=1 
//(注意:最后条件不写会全部都改掉)

查询数据

单表查询:

SELECT 字段 FROM 表名 WHERE 条件语句;
SELECT username FROM `users` (查询所有的名字)
SELECT * FROM `users` WHERE username LIKE '%三'  AND age=12  
//%占位符 找到所有的叫  “某三” 的人(占位符只需要一个就够了)
SELECT * FROM `users` ORDER BY id DESC;  查询结果DESC倒叙排列
SELECT * FROM `users` ORDER BY age ASC;  按年龄正序查询
SELECT * FROM  users LIMIT 2,2;  //分页用的限制查询 从第3条查询2条数据(0是第一条数据)
SELECT COUNT(*) FROM users  //查询数据条数 

联表查询:

//联表查询
SELECT * FROM 表名1 JOIN 表名2 ON 条件; 

//把2个表中id相同的展示出来(显示公共部分)
SELECT * FROM users JOIN product ON users.id = product.id;  
//这样取值的时候有两个相同的id,会出问题,选择的时候不能用*要像下面这样去
SELECT users.id,users.age,product.name FROM ...

//以JOIN 左边的users为主表,将联合的结果添加到users中,并显示users
SELECT * FROM users LEFT JOIN product ON users.id = product.id;  

//简写
SELECT * FROM users AS u JOIN product ASp ON u.id = p.id; 

查询条件

条件可以有 AND OR NOT BETWEEN..AND IN > < ...等等很多:

DELETE  FROM `users` WHERE id=4 OR id=6
DELETE  FROM `users` WHERE id>8
DELETE  FROM `users` WHERE id IN(5,6)
...

OVER

日历

原生JS打造简版日历

先来个预览:简版日历📅

布局

HTML:

<div class="container">
    <ul class="week">
        <li>星期日</li>
        <li>星期一</li>
        <li>星期二</li>
        <li>星期三</li>
        <li>星期四</li>
        <li>星期五</li>
        <li>星期六</li>
    </ul>
    <ul class="wrap">
        <li>12</li>
    </ul>
</div>

<div class="box">
    <button class="preY">上一年</button>
    <button class="nextY">下一年</button>
    <button class="preM">上个月</button>
    <button class="nextM">下个月</button>
</div>

<div class="show">12</div>

CSS:

<style>
    ul,ol,li{
        margin:0;
        padding: 0;
        list-style: none;
    }
    body{
        background: #000;
    }
    .container{
        width: 420px;
        color: olive;
    }
    .container li{
        width: 48px;
        float: left;
        border:1px solid #ccc;
        border-radius: 10px;
        font-size: 16px;
    }
    .week li{
        text-align: center;
        height: 25px;
        line-height: 25px;
        padding: 2px;
        background: green;
        color: white;
    }
    .wrap li{
        width:48px;
        float: left;
        height:48px;
        text-align: center;
        line-height: 48px;
        margin:2px;
        cursor: pointer;
    }

    .box{
        position: absolute;
        top: 360px;
    }
    button{
        padding: 10px;
        font-size:20px;
        color: olive;
    }
    .show{
        position: absolute;
        left: 500px;
        top: 100px;
        color: gold;
        font-size: 80px;
    }
</style>

JS实现

var wrap =document.querySelector('.wrap');
var preM =document.querySelector('.preM');
var preY =document.querySelector('.preY');
var nextM =document.querySelector('.nextM');
var nextY =document.querySelector('.nextY');
var show =document.querySelector('.show');

var _Date = new Date();
//显示的年月
var show_year = _Date.getFullYear();
var show_month = _Date.getMonth();

//当前的年月日
var now_year = _Date.getFullYear();
var now_month = _Date.getMonth();
var date = _Date.getDate();
var inner =date; //初始化显示的日期

setDate();
preY.onclick=function(){
    show_year--;
    setDate();
}
nextY.onclick=function(){
    show_year++;
    setDate();
}
preM.onclick=function(){
    show_month--;
    if (show_month<0) {
        show_month=11;
        show_year--;
    }
    setDate();
}
nextM.onclick=function(){
    show_month++;
    if (show_month>0) {
        show_month=0;
        show_year++;
    }
    setDate();
}

function setDate(){
    wrap.innerHTML='';  //清空列表

    var today = new Date(show_year,show_month,1); //获取本年本月第一天
    var num = today.getDay(); //获取本月第一天是周几
    for(var i=0; i<num ; i++){
        wrap.appendChild(document.createElement('li')) //本月第一天之前添加空白标签
    }

    //本月最后一天通过下个月第0天可以获取到
    var last_date = new Date(show_year,show_month+1,0).getDate();

    //循环添加本月的日期列表,并将现在的当天设置背景颜色
    for(var i=0; i<last_date; i++){
        var li = document.createElement('li');
        li.innerHTML = i+1;

        //如果显示的年月等于当前的年月,且当前日期等于循环的添加的li,改为选中状态
        if( date == i+1 && show_year ==now_year && show_month == now_month){
            li.style.background='red';
            li.style.color='white';
        }
        wrap.appendChild(li);    
    }

    //设置每个li可以点击
    var li = wrap.getElementsByTagName('li');
    var length =li.length;
    for(var i=0; i<length; i++){
        li.index =i;
        li[i].onclick=function(){
            if(this.innerHTML){
                for(var j=0; j<length; j++){
                    li[j].style.background='';
                    li[j].style.color='';
                }
                this.style.background='red';
                this.style.color='white';
                inner=this.innerHTML;
                show.innerHTML=`${show_year}年${show_month}月${inner}日`;
            }
        }
    }
    //设置显示时间
    show.innerHTML=`${show_year}年${show_month}月${inner}日`;
}

OVER

filter滤镜

今天分享一个滤镜小插件

使用方式非常简单,如下:

<!DOCTYPE html>  
<html>  
<head>  
    <title>Filter Demo</title>
    <link rel="stylesheet" href="filter.css">
</head>  
<body>
    <div class="kelvin">
          <img src="http://una.im/CSSgram/img/lakegeneva.jpg">
    </div>
</body>  
</html> 

头部引入插件,对应图片加上类名,所有类名已写在图片左下角,点击预览查看

效果预览
文件在我的github:Jasonellen
或者直接点击下载:文件下载

Vue之路由和请求

Vue的路由就相当于一个a连接,完成点击跳转的功能依赖文件vue-router.js
Vue的http请求就是相当于ajax,依赖文件vue-resource.js

直接贴完成页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script src="vue.js"></script>
    <script src="vue-router.js"></script>
    <script src="vue-resource.js"></script>
    <style>
        a{   
            text-decoration: none;  //因为router-link编译后就是a
        }
    </style>
</head>

<body>

    <div id="app">
          <h1>Hello App!</h1>
          <p>
            <!-- 使用 router-link 组件来导航. -->
            <!-- 通过传入 `to` 属性指定链接. -->
            <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
            <router-link to="/foo">Go to Foo</router-link>
            <router-link to="/bar">Go to Bar</router-link>
            <!-- 自定义的组件模板 -->
            <self-component></self-component>
          </p>

          <!-- 路由出口 -->
          <!-- 路由匹配到的组件将渲染在这里 -->
        <router-view></router-view>
    </div>

    <div id="div"></div>
    <script>

    // 0. 如果使用模块化机制编程,導入Vue和VueRouter,要调用 vue.use(vuerouter)

    // 1. 定义(路由)组件。
    // 也可以从其他文件 import 进来
    const Foo = { template: '<div>foo</div>' }
    const Bar = Vue.component('self-component', { template: '<div>bar</div>' })

    // 2. 定义路由
    // 每个路由应该映射一个组件。 其中"component" 可以是
    const routes = [
      { path: '/foo', component: Foo },
      { path: '/bar', component: Bar }
    ]

    // 3. 创建 router 实例,然后传 `routes` 配置
    // 你还可以传别的配置参数, 不过先这么简单着吧。
    const route1 = new VueRouter({
      routes, // (缩写)相当于 routes: routes
    })

    // 4. 创建和挂载根实例。
    // 记得要通过 router 配置参数注入路由,
    const app = new Vue({
        //el:'#app',  和下面的$mount一样的效果
      router:route1,
      mounted:function(){
          //当然也可以是get
        this.$http.jsonp('http://rap.taobao.org/mockjsdata/8591/api',{
                params: { productCourseId: 234,productId:456} //参数列表
            })
            .then(function(response){
                return response.json();  //这里 == response.body
            })
            .then(function(response){
                console.log(response.data)
            })
      }
    }).$mount('#app')

    //post方式 不需要params,但是需要加一个参数对象emulateJSON:true
    this.$http.jsonp('http://rap.taobao.org/mockjsdata/8591/api',{
                productCourseId: 234,productId:456 //参数列表
            },{
                emulateJSON:true
            })
            .then(function(response){
                return response.json();  //这里 == response.body
            })
            .then(function(response){
                console.log(response.data)
            })
    </script>
</body>
</html>

Vue表单与组件

表单的数据绑定

文本:

<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>

多行文本:

<!--white-space:pre 使得空格不会被解析-->
<p style="white-space: pre">{{ message }}</p>
<textarea v-model="message" placeholder="add multiple lines"></textarea>

复选框:

<!--如果就一个复选框-->
<input type="checkbox" id="checkbox" v-model="checked">
<label for="checkbox">{{ checked }}</label>

<!--如果有多个复选框,应该绑定到同一个数组-->
<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
<label for="jack">Jack</label>
<input type="checkbox" id="john" value="John" v-model="checkedNames">
<label for="john">John</label>
<span>Checked names: {{ checkedNames }}</span>
new Vue({
      el: '...',
      data: {
        checkedNames: []
      }
})

单选框:

<!--不需要数组,邦定到同一个data变量上即可-->
<input type="radio" id="one" value="One" v-model="picked">
<label for="one">One</label>
<br>
<input type="radio" id="two" value="Two" v-model="picked">
<label for="two">Two</label>
<br>
<span>Picked: {{ picked }}</span>

表单传值===选中后绑定的data变量的值

<!-- 当选中时,`picked` 为字符串 "a" -->
<input type="radio" v-model="picked" value="a">
<!-- `toggle` 为 true 或 false -->
<input type="checkbox" v-model="toggle">
<!-- 当选中时,`selected` 为字符串 "abc" -->
<select v-model="selected">
      <option value="abc">ABC</option>
</select>

<!--当然可以用v-bind:value 使得value也是动态的值-->
单选:
<input type="radio" v-model="pick" v-bind:value="a">
// 当选中时
vm.pick === vm.a

复选:
<input
  type="checkbox"
  v-model="toggle"
  v-bind:true-value="a"
  v-bind:false-value="b">

  // 当选中时
vm.toggle === vm.a
// 当没有选中时
vm.toggle === vm.b

列表:
<select v-model="selected">
    <!-- 内联对象字面量 -->
      <option v-bind:value="{ number: 123 }">123</option>
</select>
// 当选中时
typeof vm.selected // -> 'object'
vm.selected.number // -> 123

修饰符

<!-- 在 "change" 而不是 "input" 事件中更新 -->
<input v-model.lazy="msg" >

<!--自动将用户的输入值转为 Number 类型(如果原值的转换结果为 NaN 则返回原值)-->
<input v-model.number="age" type="number">

<!--自动过滤用户输入的首尾空格-->
<input v-model.trim="msg">

组件

基本使用

组件(Component)是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。在较高层面上,组件是自定义元素, Vue.js 的编译器为它添加特殊功能。在有些情况下,组件也可以是原生 HTML 元素的形式,以 is 特性扩展。

全局组件:

<div id="example">
      <my-component></my-component>
</div>
// 注册
Vue.component('my-component', {
      template: '<div>A custom component!</div>'
})
// 创建根实例
new Vue({
      el: '#example'
})

局部组件:仅实例/组件的作用域中可用:

var Child = {
template: ‘

A custom component!

}
new Vue({
components: {
// 将只在父模板可用
‘my-component’: Child,
App, // App组件 == ‘App’:App,
}
})
组件限制--is

源于<ul> , <ol>, <table> , <select> 限制其内部的元素
无效:
<table>
      <my-row>...</my-row>
</table>
有效:
<table>
      <tr is="my-row"></tr>
</table>

应当注意,如果您使用来自以下来源之一的字符串模板,这些限制将不适用:

<script type="text/x-template">
JavaScript内联模版字符串
.vue 组件

组件的使用。要确保在初始化根实例 之前 注册了组件

data 必须是函数

Vue.component('simple-counter', {
      data: function () {
        return {}
      }
})

每个组件都用它自己的data属性,互不干扰,除非组件共用外部的变量

<div id="example-2">
      <simple-counter></simple-counter>
      <simple-counter></simple-counter>
</div>
var data = { counter: 0 }
Vue.component('simple-counter', {
      template: '<button v-on:click="counter += 1">{{ counter }}</button>',
      // 但是我们为每一个组件返回了同一个对象引用
      data: function () {
        //return data   //两个组件的值一起变
        return {counter:0} //互不干扰
      }
})

组件间通信

父组件通过 props 向下传递数据给子组件,子组件通过 emit 给父组件发送消息。

props

常规使用

<!--注意属性值用‘-’   这里是静态的hello-->
<child my-message="hello!"></child>
Vue.component('child', {
      // 声明 props
      props: ['myMessage'],
      // 就像 data 一样,prop 可以用在模板内
      // 同样也可以在 vm 实例中像 “this.message” 这样使用
      template: '<span>{{ myMessage }}</span>'
})

<!--属性props动态值传递需要 v-bind -->
<!-- 传递实际的数字1,也可以是变量(例如data里的变量) -->
<comp v-bind:some-prop="1"></comp>

props需要默认值或验证
验证不通过也会正常显示,只是在后台报错,主要是给其他使用组件的朋友看的

Vue.component('example', {
      props: {
        // 基础类型检测 (`null` 意思是任何类型都可以)
        propA: Number,
        // 多种类型
        propB: [String, Number],
        // 必传且是字符串
        propC: {
              type: String,
              required: true
        },
        // 数字,有默认值
        propD: {
              type: Number,
              default: 100
        },
        // 数组/对象的默认值应当由一个工厂函数返回 *******必须是函数*****
        propE: {
              type: Object,
              default: function () {
                return { message: 'hello' }
              }
        },
        // 自定义验证函数
        propF: {
              validator: function (value) {
                return value > 10
              }
        }
      }
})

emit向父组件传递数据

<div id="counter-event-example">
      <p>{{ total }}</p>
              <!--组件的increment事件出发后执行实例的incrementTotal方法-->
      <button-counter v-on:increment="incrementTotal"></button-counter>

      <!--组件使用.native说明使用的是原生click事件不是绑定的事件-->
      <!--<my-component v-on:click.native="doTheThing"></my-component>-->

</div>
Vue.component('button-counter', {
                //1,组件内btn点击触发函数increment
      template: '<button v-on:click="increment">{{ counter }}</button>',
      data: function () {
        return {
              counter: 0
        }
      },
      methods: {
        increment: function () {
              this.counter += 1
              // 2,函数执行后触发组件的increment事件 //带了数据出去
              this.$emit('increment','传递的数据')
        }
      },
})
new Vue({
      el: '#counter-event-example',
      data: {
        total: 0,
        str='',
      },
      methods: {
          //实例方法执行,成功获取到组件内部传递的数据  //注意有参
        incrementTotal: function (a) {
              this.total += 1
              this.str = a  //this.str = '传递的数据'
        }
      }
})

插槽Slots–分发内容

slot标签中的任何内容都被视为备用内容。备用内容在子组件的作用域内编译,并且只有在宿主元素为空,且没有要插入的内容时才显示备用内容。

单个插槽:

//component组件
<div>
      <h2>I'm the child title</h2>
      <slot>如果没有分发内容则显示我。</slot>
</div>

//html
<div>
      <h1>I'm the parent title</h1>
      <my-component>
        <p>插入的内容</p>
      </my-component>
</div>

//渲染结果:
<div>
      <h1>I'm the parent title</h1>

      <div>
          <h2>I'm the child title</h2>
          <p>插入的内容</p>
    </div>
      <h2>I'm the child title</h2>
</div>

多个slot:用name分配:

//组件
<div class="container">
      <header>
            <slot name="header"></slot>
      </header>
     <main>
        <slot></slot>
      </main>
      <footer>
        <slot name="footer"></slot>
      </footer>
</div>

//html
<app-layout>
      <h1 slot="header">header</h1>
      <p>A paragraph for the main content.</p>
      <p slot="footer">footer</p>
</app-layout>

//渲染结果
<div class="container">
      <header>
        <h1>header</h1>
      </header>

      <main>
        <p>A paragraph for the main content.</p>
      </main>

      <footer>
        <p>footer</p>
      </footer>
</div>

切换组件显示

var vm = new Vue({
      el: '#example',
      data: {
        currentView: 'home'
      },
      components: {
            home: { /* ... */ },
        posts: { /* ... */ },
        archive: { /* ... */ }
      }
})
//keep-alive切换出去的组件保留在内存中,可以保留它的状态或避免重新渲染。
<keep-alive>
    <component v-bind:is="currentView">
      <!-- 组件在 vm.currentview 变化时改变! -->
    </component>
</keep-alive>

子组件索引

—获取其他不相关的组件并加以控制器内部实现
<div id="parent">
      <user-profile ref="profile"></user-profile>
</div>

var parent = new Vue({ el: '#parent' })
// 访问子组件
var child = parent.$refs.profile;

//然后就可以控制child的内部实现--
    如child.a=..
    child.fn();

尽管在 Vue 中渲染 HTML 很快,不过当组件中包含大量静态内容时,可以考虑使用 v-once 将渲染结果缓存起来

–注意使用v-once后内部值或者变量都只会执行一次,后续不会再变动,包括子节点

先到这里OVER

Vue数据绑定

文件安装

开发版本
生产版本

$ npm install vue

基本语法-无序😁

Vue实例

var app = new Vue({
      el: '#app',
      //实例代理属性data
      data: {
        message: 'Hello Vue!',
        seen: true,
        todos: [
              { text: 'Learn JavaScript' },
              { text: 'Learn Vue' },
              { text: 'Build something awesome' }
        ],
        html:'<p>这是插入的p标签</p>',
        ...
        filters: {
            capitalize: function (value) {
              if (!value) return ''
              value = value.toString()
              return value.charAt(0).toUpperCase() + value.slice(1)
           }
      },
      //计算属性
      computed:{
          reverseMessage:function(){...},
          //绑定fullName,没有参数默认执行getter,有参数默认执行setter
          fullName: {
            // getter
            get: function () {
                  return this.firstName + ' ' + this.lastName
            },
            // setter
            set: function (newValue) {
                  var names = newValue.split(' ')
                  this.firstName = names[0]
                  this.lastName = names[names.length - 1]
            }
          }
      },
      //方法
      methods:{
          myclick:function(){...}
      },
      watch:{
          seen:function(){...}
      },
      //钩子函数 
      //mounted当组件被挂载并解析完成后执行
      mounted:function(){
          ...
      },
      ...

})

内容绑定

//内容绑定
<div id="app">{{ message }}</div>

属性绑定

//绑定title属性到message上
<span v-bind:title="message"></span>

v-if

//执行的是append和remove 和show有本质的区别
//如果seen为true则now you see 显示,否则no see显示

Now you see me


no see

v-show

//执行的是 diplay:none 与 display:block
//不支持给组件设置 如

v-for循环

<ol>
    //建议提供key,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素
    <li v-for="(todo,index) in todos" :key="item.id>               {{ todo.text }}
       </li>
</ol>

//遍历对象不用一一对应,一参 键值,二参键名(可选),三参索引(可选)
<div v-for="(value, key, index) in object">
      {{ index }}. {{ key }} : {{ value }}
</div>

//取整数
<span v-for="n in 10">{{ n }}</span>
<li v-for="n in evenNumbers">{{ n }}</li> //计算属性
<li v-for="n in even(10)">{{ n }}</li>

//v-for 支持 <template> 循环渲染很多模板--数据需要绑定,不能自动传进组件里
<my-component
      v-for="(item, index) in items"
      v-bind:item="item"
     v-bind:index="index">
</my-component>

事件绑定

<button v-on:click="reverseMessage">Reverse Message</button>
//缩写
v-bind:href="url"  ==  :href="url"
v-on:click="reverseMessage"  ==  @click="reverseMessage"

表单双向绑定

  <input v-model="message">
  <p>{{ message }}</p>

  //需要换行?    white-space: pre直接空格/换行
  <p style="white-space: pre">{{ message }}</p>
<br>
<textarea v-model="message" placeholder="add multiple lines"></textarea>

标签插值

//span将被忽略
<div v-html='html'>{{html}}<span>11111</span></div>

模板表达式

//模板表达式中还可以使用 Math 和 Date不能访问用户定义的全局变量
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
//list- 是字符串 id是绑定的变量
<div v-bind:id="'list-' + id"></div>

过滤

//默认参数是message或message表达式的返回值
<div>{{ message | filterA | filterB }}</div>
//传入的参数表示过滤函数的第二参和第三参
{{ message | filterA('arg1', arg2) }}

事件修饰符


<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>

<!-- 修饰符可以串联  -->
<a v-on:click.stop.prevent="doThat"></a>

<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>

<!-- 添加事件侦听器时使用事件捕获模式 -->
<div v-on:click.capture="doThis">...</div>

<!-- 只当事件在该元素本身(而不是子元素)触发时触发回调 -->
<div v-on:click.self="doThat">...</div>

按键修饰符

<!-- 只有在 keyCode 是 13 时调用 vm.submit() -->
<input v-on:keyup.13="submit">

//记不住所有的code?用名字呗
<!-- 同上 -->
<input v-on:keyup.enter="submit">
//enter,tab,delete,esc,space,up,down,left,right

<!-- 没有想用的?自定义喽 -->
// 可以使用 v-on:keyup.f1
Vue.config.keyCodes.A = 112

对象/数组语法

//当对象的值isActive为真时 class将会有类名 对象的键  一直都有div的类名
v-bind:class="{ active: isActive, 'text-danger': hasError }" class=‘div’>

//activeClass和errorClass为真时才会被赋值给class
<div v-bind:class="[activeClass, errorClass]">

//样式绑定     --前缀vue会自动添加
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
...清晰的写法...
<div v-bind:style="styleObject"></div>    
data: {
      styleObject: {
        color: 'red',
        fontSize: '13px'
      }
}

数组方法

如下两项改变data不会重新渲染页面
1,vm.items[indexOfItem] = newValue
    改为:Vue.set(example1.items, indexOfItem, newValue)
    或:example1.items.splice(indexOfItem, 1, newValue)

2,vm.items.length = newLength
    改为:example1.items.splice(newLength)

小提示

  • 只有当data属性里的值改变才会重新渲染view视图
  • v-once:执行一次性地插值,当数据改变时,插值处的内容不会再更新,静态的使用快速
    • 计算属性是基于它的依赖缓存。计算属性只有在它的相关依赖(data)发生改变时才会重新取值。data不变多次访问计算属性会立即返回之前的计算结果,而不必再次执行函数!但是重新渲染的时候,method 调用总 会执行函数
  • 组件内部访问实例属性记得$emit..以便与代理的data属性区分

声明周期示意图


JS经典题

题目如下:

1,function fn(){
    getName = function(){alert('大木')};
    return this;
}

2,fn.getName = function(){ alert('大木2')}

3,fn.prototype.getName = function(){ alert('大木3')}

4,var getName = function(){ alert('大木4')}

5,function getName(){ alert('大木5')}

请输入如下结果

  1. fn.getName();
  2. getName();
  3. fn().getName()
  4. getName()
  5. new fn.getName()
  6. new fn().getName()
  7. new new fn().getName()

-

-

-

-

-

-

-

-

-

-

答案

  1. fn.getName(); ———- 大木2

  2. getName(); ————- 大木4

  3. fn().getName() ———- 大木

  4. getName() ————— 大木

  5. new fn.getName()——–大木2

  6. new fn().getName()—— 大木3

  7. new new fn().getName()–大木3

解析

  1. 该题首先定义了一个构造函数fn,fn内部定义了一个全局变量 getName 然后返回 this
  2. 给fn定义了一个静态属性getName,注意次属性只能由 fn函数自己调用
  3. 给构造函数fn原型链添加一个getName方法
  4. var 定义一个变量 getName
  5. 定义一个普通函数getName

JS变量解析方式是先将变量申明和函数申明放到作用域最顶部,函数和变量同名会用函数申明覆盖变量申明,然后再进行赋值操作,所以解析后代码如下

var getName; //无效,被覆盖

function getName(){ alert(‘大木5’)} //覆盖上面的变量申明

function fn(){
getName = function(){
alert(‘大木’ );
return tis;
}

fn.getName = function(){ alert(‘木2’)}

fn.prototype.getName = function(){ alert(‘木3’)}

getName = function(){ alert(‘大木4’)} //普通函数被重新指向一个新函数

第一问 fn.getName(); 是执行函数的静态变量  ---大木2
第二问 getName() 执行普通函数 ---大木4
第三问 fn().getName() ==先执行fn(),将全局变量getName指向新函数 alert('大木')
      返回this-->指向window,再执行window.getName()  --大木
第四问 getName() 直接执行被在fn内部改变指向后的getName --大木
第五问 new fn.getName() 是JS运算符优先级.语法高于new,所以是先执行(fn.getName)(),
      然后将执行后的函数实例化操作 --大木2
第六文 new fn().getName()--new 带参数(即 new Foo())和函数自调用(即先 Foo()),
      而 new 带参数的优先级是高于函数调用的! 所以此处执行顺序为(new fn()).getName()
      即fn数理化后执行原型链方法getName --大木3
第七问 同理先执行new fn()返回实例化对象A,new A.getName()同第五问==new(A.getName)()--大木3

注意点:

1,变量提升,同名函数申明会覆盖变量申明
2,“.”语法操作优先级高于 new语法操作
3,函数自调用 fn() 优先级 小于 new fn()

OVER

弹性球

本文实现JS原生弹性球

创造一个球先

HTML

<div class="ball"></div>    

CSS

<style>
    div{
        width:100px;
        height:100px;
        position: absolute;
        bottom:0;
        left:200px;
        background: url(img/ball.png) no-repeat;
    }
</style>

球球创建好了呢,如下:

ball

JS实现

获取元素,初始化设置

var ball = document.querySelector(".ball");

添加移除事件兼容性处理

function addHandler(element,type,handler){
    if(element.addEventListener){//检测是否为DOM2级方法
        element.addEventListener(type, handler, false);
    }else if (element.attachEvent){//检测是否为IE级方法
        element.attachEvent("on" + type, handler);
    } else {//检测是否为DOM0级方法
        element["on" + type] = handler;
    }
}
function removeHandler(element, type, handler){
    if (element.removeEventListener){
        element.removeEventListener(type, handler, false);
    } else if (element.detachEvent){
        element.detachEvent("on" + type, handler);
    } else {
        element["on" + type] = null;
    }
}         

封装函数

function gravBall(obj){
var timer = null;
var speedX =0, speedY=0,x=0,y=0;
var gapX =0, gapY=0;

    // obj.onmousedown = down;
    addHandler(obj,'mousedown',down);
    addHandler(obj,'mouseup',up);

    function down(ev){           
        clearInterval(timer); 
        var ev = ev || window.event;
        gapX = ev.clientX - obj.offsetLeft;
        gapY = ev.clientY - obj.offsetTop;
        addHandler(document,'mousemove',move);    
    }
    function up(){
        var currentX=0,currentY=0,l=0,t=0;
        removeHandler(document,'mousemove',move)
        clearInterval(timer); 
        timer = setInterval(function(){
            speedY +=3;  //一直有一个Y方向的增加,仿重力
            currentX = window.innerWidth - obj.offsetWidth;
            currentY = window.innerHeight - obj.offsetHeight;
            l = obj.offsetLeft + speedX;
            t = obj.offsetTop + speedY;
            //speedY +=3;  //放在这里就是先判断再+3,根本停不下来
            if(l > currentX){
                speedX *= -0.8;
                l =currentX;
            }
            if(l < 0){
                speedX *= -0.8;
                l = 0;
            }
            if(t > currentY){
                speedY *= -0.8;
                speedX *= 0.8;
                t = currentY;
            }
            if(t < 0){
                speedY *= -0.8;
                speedX *= 0.8;
                t = 0;
            }
            if( Math.abs(t-currentY)<1 && Math.abs(speedY)<1.5 && Math.abs(speedX)<1.5){
                clearInterval(timer);
            }
            obj.style.left = l  + "px";
            obj.style.top = t  + "px";
        },30)
    }

    function move(ev){
        var ev = ev || window.event;
        //难点一,记录当前速度 是最后一次的offsetLeft减去上一次的offsetLeft
        speedX = ev.clientX - x - gapX;
        speedY = ev.clientY - y - gapY;
        //记录本次的offsetLeft作为下一次移动的的上一次的offsetLeft;
        x = obj.offsetLeft;
        y = obj.offsetTop;
        var evX = ev.clientX;
        var evY = ev.clientY;
        if(ev.clientX<gapX || ev.clientX>window.innerWidth-gapX || ev.clientY<0 || ev.clientY>window.innerHeight){
            up();
        }
        obj.style.left = evX - gapX  + "px";
        obj.style.top = evY - gapY  + "px";
    }
}

OVER