1、普通监听(无法监听到第一次绑定的变化)

<input type="text" v-model="userName"/>  
//监听   当userName值发生变化时触发
watch: {
    userName (newName, oldName) {
        console.log(newName)
    }
}

2、普通监听(可监听到第一次绑定的变化)

<input type="text" v-model="userName"/>  
watch: {
    userName: {
        handler (newName, oldName) {
            console.log(newName)
        },
        immediate: true
    }
}

3、深度监听(可监听对象内属性变化)

<input type="text" v-model="cityName.name" />
data (){
    return {
        cityName: {name:'北京'}
    }
},
watch: {
    cityName: {
        handler(newName, oldName) {
            console.log(newName)
        },
        immediate: true,
        deep: true
    }
}

安装gateway-worker

composer require workerman/gateway-worker
composer require workerman/gatewayclient

创建 Workerman 启动文件
创建一个 artisan 命令行工具来启动 Socket 服务端,在 app/Console/Commands 目录下建立命令行文件。

php artisan make:command GatewayWorkerServer

GatewayWorkerServer 文件

<?php
 
namespace App\Console\Commands;
 
use Illuminate\Console\Command;
use GatewayWorker\BusinessWorker;
use GatewayWorker\Gateway;
use GatewayWorker\Register;
use Workerman\Worker;
 
 
class GatewayWorkerServer extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'workman {action} {--d}';
 
    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Start a Workerman server.';
 
    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }
 
    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        //
        global $argv;
        $action = $this->argument('action');
 
        $argv[0] = 'artisan workman';
        $argv[1] = $action;
        $argv[2] = $this->option('d') ? '-d' : '';   //必须是一个-,上面定义命令两个--,后台启动用两个--
 
        $this->start();
    }
 
    private function start()
    {
        $this->startGateWay();
        $this->startBusinessWorker();
        $this->startRegister();
        Worker::runAll();
    }
 
    private function startBusinessWorker()
    {
        $worker                  = new BusinessWorker();
        $worker->name            = 'BusinessWorker';
        $worker->count           = 1;
        $worker->registerAddress = '127.0.0.1:1236';
        $worker->eventHandler    = \App\GatewayWorker\Events::class;
    }
 
    private function startGateWay()
    {
        $gateway = new Gateway("websocket://0.0.0.0:2346");
        $gateway->name                 = 'Gateway';
        $gateway->count                = 1;
        $gateway->lanIp                = '127.0.0.1';
        $gateway->startPort            = 2300;
        $gateway->pingInterval         = 30;
        $gateway->pingNotResponseLimit = 0;
        $gateway->pingData             = '{"type":"ping"}';
        $gateway->registerAddress      = '127.0.0.1:1236';
    }
 
    private function startRegister()
    {
        new Register('text://0.0.0.0:1236');
    }
 
       //php artisan workman start --d  之后    打开浏览器F12 将内容复制到console里return就行
       /* ws = new WebSocket("ws://192.168.1.118:2346");
        ws.onopen = function() {
            ws . send('{"name":"one","user_id":"111"}');
            ws . send('{"name":"two","user_id":"222"}');
        };
        ws.onmessage = function(e) {
            console.log("收到服务端的消息:" + e.data);
        };
        ws.onclose = function(e) {
            console.log("服务已断开" );
        };*/
 
}

创建一个 app/GatewayWorker/Events.php 文件来监听处理 workman 的各种事件。

<?php
/**
 * Created by PhpStorm.
 * User: ls
 * Date: 2020/3/25
 * Time: 16:09
 */
namespace App\GatewayWorker;
 
use GatewayWorker\Lib\Gateway;
use Illuminate\Support\Facades\Log;
 
class Events
{
 
    public static function onWorkerStart($businessWorker)
    {
        echo "onWorkerStart\r\n";
    }
 
    public static function onConnect($client_id)
    {
        Gateway::sendToClient($client_id, json_encode(['type' => 'onConnect', 'client_id' => $client_id]));
        echo "onConnect\r\n";
    }
 
    public static function onWebSocketConnect($client_id, $data)
    {
        echo "onWebSocketConnect\r\n";
    }
 
    public static function onMessage($client_id, $message)
    {
        Gateway::sendToClient($client_id, json_encode(['type' => 'onMessage', 'client_id' => $client_id, 'name' => json_decode($message)->name]));
 
        echo "onMessage\r\n";
    }
 
    public static function onClose($client_id)
    {
        Log::info('Workerman close connection' . $client_id);
        echo "onClose\r\n";
    }
 
}

启动 Workerman 服务端
在命令行里面执行,支持的命令大概有 start|stop|restart,其中 --d 的意思是 daemon 模式,后台守护进程。

php artisan workman start --d

客户端js html代码测试一下

var ws = new WebSocket("ws://192.168.1.118:2346");
ws.onopen = function() {
    ws . send('{"name":"one","user_id":"111"}');
    ws . send('{"name":"two","user_id":"222"}');
};
ws.onmessage = function(e) {
    console.log("收到服务端的消息:" + e.data);
};
ws.onclose = function(e) {
    console.log("服务已断开" );
}

**如果用到ssl,本地测试时
本地可以用openssl生成自定义证书**

yum install openssl yum install openssl-devel
openssl req -newkey rsa:2048 -nodes -keyout key.pem -x509 -days 3650 -out certificate.pem

在执行此命令后,将被提示输入一些信息,例如国家/地区、州、城市、公司等。在输入完这些信息后,将生成名为 key.pem 和 certificate.pem 的文件。key.pem 文件包含 SSL 密钥,certificate.pem 文件包含 SSL 证书。

$ws_domain = env('WS_DOMAIN'); // ws_domain最好不要直接用主域名 用子域
$context = array(
    'ssl' => array(
        // 请使用绝对路径
        'local_cert'                 => '/micro/conf/nginx/conf.d/cert/'.$ws_domain.'.pem', // 也可以是crt文件
        'local_pk'                   => '/micro/conf/nginx/conf.d/cert/'.$ws_domain.'.key',
        'verify_peer'                => false,
        // 'allow_self_signed' => true, //如果是自签名证书需要开启此选项
    )
);

$gateway = new Gateway("websocket://0.0.0.0:12396", $context);// 外部连接 用0.0.0.0
$gateway->name                 = 'Gateway';
$gateway->transport            = 'ssl';
$gateway->count                = 2;
$gateway->lanIp                = '127.0.0.1';
$gateway->startPort            = 2300;
$gateway->pingInterval         = 50;
$gateway->pingNotResponseLimit = 0;
$gateway->pingData             = '{"type":"ping"}';
$gateway->registerAddress      = '127.0.0.1:1236';   // Worker

//2
$gateway2 = new Gateway("websocket://127.0.0.1:15396"); // 内部连接 用127.0.0.1
$gateway2->name                 = 'Gateway2';
$gateway2->count                = 1;
$gateway2->lanIp                = '127.0.0.1';
$gateway2->startPort            = 5300;
$gateway2->pingInterval         = 30;
$gateway2->pingNotResponseLimit = 0;
$gateway2->pingData             = '{"type":"ping"}';
$gateway2->registerAddress      = '127.0.0.1:1236';   // Worker

解决 webpack-dev-server 不能使用 IP 访问

webpack 是众所周知很好用的打包工具,在开发 vue 项目时,vue-cli 就集成了 webpack。
我们启一个服务:npm run dev
然后在浏览器可是使用 http://localhost:8080 访问,但是当我们遇到移动端项目时,需要在手机端访问,所以要把 localhost 换成本地 IP 地址,例如:http://192.168.x.xx:8080,你会发现移动端无法使用 IP 访问。
解决方案

第一种方法:
找到 your-project/build/webpack.dev.conf.js

// const HOST = process.env.HOST
const HOST = '192.168.x.xx:8080'

然后保存,重新启动一下服务,会发现 PC 地址栏已经变成:
http://192.168.x.xx:8080 了,然后手机试一试,没问题。

第二种方法:
找到 your-project/package.json

"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js"

在这句话里面添加参数 --host 0,0,0,0

"dev": "webpack-dev-server --inline --host 0.0.0.0 --progress --config build/webpack.dev.conf.js"

然后在 PC 地址栏输入:http://192.168.x.xx:8080 or localhost or 0.0.0.0 都可以访问,手机使用 IP 访问也是没问题。

官网下载页面https://nodejs.org/en/download/ 选在对应系统下载地址,复制下载地址使用wget 进行下载

创建安装目录 我直接在/usr/local/src目录下进行,下面做软链接时会用到这个目录

# wget https://nodejs.org/dist/v12.18.3/node-v12.18.3-linux-x64.tar.xz

# xz -d node-v12.18.3-linux-x64.tar.xz

# tar -xvf node-v12.18.3-linux-x64.tar

cd node-v12.18.3-linux-x64/bin/

执行命令查看 node 版本

# ./node -v

v12.18.3
我的node 放在 /usr/local/src 目录下

ln -s /usr/local/src/node-v12.18.3-linux-x64/bin/node /usr/bin/node
ln -s /usr/local/src/node-v12.18.3-linux-x64/bin/npm /usr/bin/npm
ln -s /usr/local/src/node-v12.18.3-linux-x64/bin/npx /usr/bin/npx

如果之前装了nodejs 可以使用which node查看node之前的执行目录 把软连接改到这个地址

# node -v

显示版本号v12.18.3 表示完成

下面装一个cpm
npm安装安装插件比较慢,最好安装cnpm(淘宝NPM镜像):

npm install -g cnpm --registry=https://registry.npm.taobao.org

输入cnpm -v 提示结果为:cnpm: command not found,因为应为此时cnpm还是不是全局变量

输入命令:ln -s /node/node-v10.14.1-linux-x64/bin/cnpm /usr/bin/node(根据自己的node目录进行配置), 此时cnpm就是全局变量了,就可使 cnpm -v 就可以查看版本号了

cnpm install -g vue-cli

安装完后程序会输出你的安装目录 根据自己的node目录进行配置

ln -s /node/node-v10.14.1-linux-x64/bin/vue /usr/bin/vue

测试是否可用

vue -V

创建一个项目
使用命令行进行初始化。

vue create antd-demo

使用组件

 npm i --save ant-design-vue

完整引入

import Vue from 'vue'
import Antd from 'ant-design-vue'
import App from './App'
import 'ant-design-vue/dist/antd.css'
Vue.config.productionTip = false

Vue.use(Antd)

/* eslint-disable no-new */
new Vue({
  el: '#app',
  components: { App },
  template: '<App/>'
})

以上代码便完成了 Antd 的引入。需要注意的是,样式文件需要单独引入。

局部导入组件

import Vue from 'vue'
import { Button, message } from 'ant-design-vue'
import App from './App'

Vue.config.productionTip = false

/* v1.1.2 */
Vue.component(Button.name, Button)
Vue.component(Button.Group.name, Button.Group)

/* v1.1.3+ 自动注册Button下组件,如Button.Group */
Vue.use(Button)

Vue.prototype.$message = message

/* eslint-disable no-new */
new Vue({
  el: '#app',
  components: { App },
  template: '<App/>'
})

以上代码便完成了 Antd 的引入。需要注意的是,样式文件需要单独引入。

vue create is a Vue CLI 3 only command and you are using Vue CLI 2.9.6. 报错
原因:vue-cli版本是3以下的,却用了3的命令
解决办法:更新版本
先卸载原来的

cnpm uninstall -g vue-cli

然后下载一个新的

cnpm install -g @vue/cli

安装vue-antd-admin 引用basic分支基础模块
(如果要研究项目的话直接git clone -b basic https://gitee.com/iczer/vue-antd-admin)

git clone -b basic https://gitee.com/iczer/vue-antd-admin

$ npm install

注意用的是用npm run dev 去package.json中看有没有dev信息

$ npm run serve