Vue2 API-源码解析

news2025/1/16 17:43:31

目录

Vue.extend(option)

delimiters

functional 

Vue.component(id, Function | Object) 

Vue.directive( id, [definition] )

Vue.filter( id, function)

Vue.nextTick()

Vue.set()

Vue.delete(target, index/key)

Vue.compile(template)

Vue.observable(object)

provide/inject

extends、mixins


Vue.extend(option)

作用:返回一个vue子组件的构造函数

参数:创建vue实例的参数

<template>
  <div id="home">
    <div>home</div>
  </div>
</template>

<script>
import Vue from 'vue'

export default {
  name: "",
  mounted() {
    // 创建子组件构造函数 VueComponent
    var VueComponentFun = Vue.extend({
      template: "<p>{{firstName}} {{lastName}} aka {{alias}}</p>",
      data: function () {
        return {
          firstName: "Walter",
          lastName: "White",
          alias: "Heisenberg",
        };
      },
    });
    // 挂载到一个元素上。
    new VueComponentFun().$mount("#home");
  },
};
</script>

home节点被替换掉,渲染结果如下

源码:

  1. 调用Vue.prototype._init()进行数据初始化 - created周期
  2. 继承原型上的extend、mixin、use、component, directive, filter
    Vue.extend = function (extendOptions) {
        extendOptions = extendOptions || {};
        var Super = this;
        ......
        //创建子类(子组件构造函数),先调用父类的方法进行初始化
        var Sub = function VueComponent(options) {
            this._init(options);
        };
        //创建子类的原型对象
        Sub.prototype = Object.create(Super.prototype);
        Sub.prototype.constructor = Sub;

        Sub.options = mergeOptions(Super.options, extendOptions);
        Sub['super'] = Super;
        //对props属性做set、get拦截
        if (Sub.options.props) {
            initProps(Sub);
        }
        if (Sub.options.computed) {
            initComputed(Sub);
        }

        Sub.extend = Super.extend;
        Sub.mixin = Super.mixin;
        Sub.use = Super.use;
        //赋值生命周期
        ASSET_TYPES.forEach(function (type) {
            Sub[type] = Super[type];
        });
        ......

        return Sub;
    };

delimiters

作用:分隔符,定义 模板字符串的变量标识

上面的代码可改为

template: "<p @click='add'>{firstName} {lastName} aka {num}</p>",
delimiters: ['{', '}'],

functional 

作用:函数组件,没有响应式数据,也没有实例(this),使用functional:true生命,使用render生成Dom

优点: 1.使用render 函数返回虚拟节点使它们渲染的代价更小;2.不需要实例化

Vue.component('custom-component', Vue.extend({
  functional: true,
  props: {
    params: String,
  },
  render: function (h, context) {
    let props = context.props
    return h('div', { class: 'custom' }, [
      h('div', {
        domProps: {
          innerText: props.params,
        },
        class: ['custom_button'],
        on: {
          click: () => {
            console.log("click")
          },
        },
      })
    ])
  }
}))

Vue.component(id, Function | Object) 

作用:注册或获取全局组件

有下面两种方法生成组件

// 注册组件,传入一个扩展过的构造器
Vue.component('my-component', Vue.extend({ /* ... */ }))

// 注册组件,传入一个选项对象 (自动调用 Vue.extend)
Vue.component('my-component', { /* ... */ })

Vue.directive( id, [definition] )

作用:添加自定义指令,可以在绑定的元素未插入到Dom内时,判断Dom是否存在

参数:指令名称、函数

回调参数:

el:指令绑定到的元素

binding:指令接收的参数

  • value:指令绑定的对象
  • oldValue:指令绑定的对象修改之前的值
  • expression:字符串形式的指令表达式
Vue.directive('focus', {
  // 指令与元素成功绑定时调用
  bind: function (el, binding) {
  },
  // 当被绑定的元素插入到 DOM 中时……
  inserted: function (el, binding) {
  },
  // 命令所绑定的dom及数据有变化时,
  update: function (el, binding) {
  },
  // 指令所在组件的 VNode 及其子 VNode 全部更新后调用
  componentUpdated: function (el, binding) {
  },
  // 指令与元素解绑时调用
  unbind: function (el, binding) {
  }
})

 <div  v-focus="{name:a}"></div>

Vue.filter( id, function)

作用:过滤器

参数:被处理的值、接受的其他传参(多个)

//main.js
Vue.filter('capitalize', function (value, a) {
  // 被处理的值、参数...
  if (!value) return "";
  return value + a;
})

//home.vue
<template>
  <div id="home">
    <!-- 大括号绑定,页面显示11 -->
    <div>{{ a | capitalize(10) }}</div> 
    <!-- v-bind绑定 -->
    <A :pd="b | capitalize"></A>
  </div>
</template>

<script>
import A from "./A.vue";
export default {
  name: "",
  components: {
    A,
  },
  data() {
    return {
      a: 1,
    };
  },
};
</script>

源码:['component', 'directive', 'filter'] 直接返回回调函数

function initAssetRegisters(Vue) {
    ASSET_TYPES.forEach(function (type) {
        // @ts-expect-error function is not exact same type
        Vue[type] = function (id, definition) {
            if (!definition) {
                return this.options[type + 's'][id];
            }
            else {
                ......
                if (type === 'component' && isPlainObject(definition)) {
                    // @ts-expect-error
                    definition.name = definition.name || id;
                    // this.options._base = Vue构造函数,就是直接调用Vue.extend
                    definition = this.options._base.extend(definition);
                }
                if (type === 'directive' && isFunction(definition)) {
                    definition = { bind: definition, update: definition };
                }
                // 给当前实例this添加{id: definition}
                this.options[type + 's'][id] = definition;
                return definition;
            }
        };
    });
}

Vue.nextTick()

作用:在 DOM 更新循环结束之后执行延迟回调,vue修改数据时不能及时反映到页面上,需要一轮事务处理,才能获取到页面上修改过的值

参数:callback()、this

用法:

// 修改数据
vm.msg = 'Hello'
// DOM 还没有更新
Vue.nextTick(function () {
  // DOM 更新了
})

// 作为一个 Promise 使用 (2.1.0 起新增,详见接下来的提示)
Vue.nextTick()
  .then(function () {
    // DOM 更新了
  })

注:使用第二种方法时,需要在支持Promise的环境中(IE不支持)

 源码:

     如果浏览器支持Promise,则使用Promise.resolve()返回一个Promise 对象(微任务),因为微任务会等待主线程的同步任务执行完毕,再执行微任务队列。微任务队列就是下列callbacks数组,这里面会放入回调函数,如果一次同步任务中有多个nextTick,则callback中会有多个回调函数。这些回调函数会在then()回调中执行。

var p_1 = Promise.resolve();
    timerFunc = function () {
        p_1.then(flushCallbacks);

        if (isIOS)
            setTimeout(noop);
    };
function nextTick(cb, ctx) {
    // cb: 回调函数  ctx: this指向
    var _resolve;
    // 回调函数放入数组,如果短时间内多次调用nextTick,则数组中有多个回调函数
    callbacks.push(function () {
        if (cb) {
            try {
                cb.call(ctx);
            }
            catch (e) {
                handleError(e, ctx, 'nextTick');
            }
        }
        else if (_resolve) {
            _resolve(ctx);
        }
    });
    // 执行回调函数; 
    if (!pending) {
        pending = true;
        timerFunc();
    }
    // 支持.then写法
    if (!cb && typeof Promise !== 'undefined') {
        return new Promise(function (resolve) {
            _resolve = resolve;
        });
    }
}

var timerFunc; 
// 实现nextTick用了两种方法,Promise.then or MutationObserver
if (typeof Promise !== 'undefined' && isNative(Promise)) {
    // 浏览器支持Promise的情况,使用Promise
    // 创建微任务,微任务会等到主线程的代码执行完毕,再执行,所以p_1.then实现了nextTick的功能
    var p_1 = Promise.resolve();
    timerFunc = function () {
        p_1.then(flushCallbacks);

        if (isIOS)
            setTimeout(noop);
    };
    isUsingMicroTask = true;
}
else if (!isIE &&
    typeof MutationObserver !== 'undefined' &&
    (isNative(MutationObserver) ||
        // PhantomJS and iOS 7.x
        MutationObserver.toString() === '[object MutationObserverConstructor]')) {
    // Use MutationObserver where native Promise is not available,
    // e.g. PhantomJS, iOS7, Android 4.4
    var counter_1 = 1;
    var observer = new MutationObserver(flushCallbacks);
    var textNode_1 = document.createTextNode(String(counter_1));
    observer.observe(textNode_1, {
        characterData: true
    });
    timerFunc = function () {
        counter_1 = (counter_1 + 1) % 2;
        textNode_1.data = String(counter_1);
    };
    isUsingMicroTask = true;
}
else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {
    timerFunc = function () {
        setImmediate(flushCallbacks);
    };
}
else {
    timerFunc = function () {
        setTimeout(flushCallbacks, 0);
    };
}

Vue.set()

作用:向具有响应式的对象中添加property,且新的property具有响应式。在创建的过程中对该属性进行依赖收集

<template>
  <div id="home">
    <div id="customComA">{{ obj }}</div>
    <div id="customComB">{{ arr }}</div>
  </div>
</template>

<script>
import Vue from "vue";

export default {
  name: "",
  data() {
    return {
      obj: { name: "zz" },
      arr: [1, 2]
    };
  },
  mounted() {
    // 无效
     this.obj.age = 15
     this.arr[1] = 10

    // Vue.set
    Vue.set(this.obj, 'age', 15)
    Vue.set(this.obj, 1, 10)
  },
};
</script>

 源码实现:

  1. 对Array对象进行修改,对元素进行响应式化
  2. 对Object类型进行赋值,对赋值的新元素进行响应式
function set(target, key, val) {
    // obj|arr , key|index
    if (process.env.NODE_ENV !== 'production' && (isUndef(target) || isPrimitive(target))) {
        warn$2("Cannot set reactive property on undefined, null, or primitive value: ".concat(target));
    }
    if (isReadonly(target)) {
        process.env.NODE_ENV !== 'production' && warn$2("Set operation on key \"".concat(key, "\" failed: target is readonly."));
        return;
    }
    var ob = target.__ob__;
    // 对Array对象进行修改,对元素进行响应式化
    if (isArray(target) && isValidArrayIndex(key)) {
        target.length = Math.max(target.length, key);
        target.splice(key, 1, val);
        // when mocking for SSR, array methods are not hijacked
        if (ob && !ob.shallow && ob.mock) {
            observe(val, false, true);
        }
        return val;
    }
    // object修改属性值
    if (key in target && !(key in Object.prototype)) {
        console.log("obj")
        target[key] = val;
        return val;
    }
    if (target._isVue || (ob && ob.vmCount)) {
        process.env.NODE_ENV !== 'production' &&
            warn$2('Avoid adding reactive properties to a Vue instance or its root $data ' +
                'at runtime - declare it upfront in the data option.');
        return val;
    }
    // 对空值的赋值不做其他处理
    if (!ob) {
        target[key] = val;
        return val;
    }
    // object对象新增属性值
    defineReactive(ob.value, key, val, undefined, ob.shallow, ob.mock);
    if (process.env.NODE_ENV !== 'production') {
        ob.dep.notify({
            type: "add" /* TriggerOpTypes.ADD */,
            target: target,
            key: key,
            newValue: val,
            oldValue: undefined
        });
    }
    else {
        ob.dep.notify();
    }
    return val;
}

Vue.delete(target, index/key)

作用:删除属性,并触发有关dom的改变

对于Array,使用 target.splice(key, 1);

对于Object,使用 delete target[key]; 并触发监听器ob.dep.notify()

源码:

function del(target, key) {
    if (process.env.NODE_ENV !== 'production' && (isUndef(target) || isPrimitive(target))) {
        warn$2("Cannot delete reactive property on undefined, null, or primitive value: ".concat(target));
    }
    // 数组类型的直接操作
    if (isArray(target) && isValidArrayIndex(key)) {
        target.splice(key, 1);
        return;
    }
    var ob = target.__ob__;
    
    ......

    if (!hasOwn(target, key)) {
        return;
    }
    // Object类型
    delete target[key];
    if (!ob) {
        return;
    }
    // 通知删除的该元素关联的依赖
    if (process.env.NODE_ENV !== 'production') {
        ob.dep.notify({
            type: "delete" /* TriggerOpTypes.DELETE */,
            target: target,
            key: key
        });
    }
    else {
        ob.dep.notify();
    }
}

Vue.compile(template)

作用:将一个模板字符串编译成 render 函数(VNode)

//把解析的模板渲染,挂载到.home节点上
let res = Vue.compile("<div class='wrapper'>{{ msg }}</div>");
new Vue({
  data: {
    msg: "hello",
  },
  render: res.render,
  // staticRenderFns: res.staticRenderFns,
}).$mount(".home");

源码: 

var _a = createCompiler(baseOptions)

执行createCompiler函数,即createCompilerCreator函数,即执行 createCompiler函数,同时对baseCompile、compile函数进行缓存;

Vue.compile = compileToFunctions;
Vue.compile("<div class='wrapper'>{{ msg }}</div>");

1.执行createCompileToFunctionFn(compile),即compileToFunctions函数,判断缓存中是否有该模板的编译结果,如果有,取出返回;没有则执行compile函数,之后把获取到的编译结果res.render转化为函数形式,编译结果res写入缓存

2.执行compile函数,先执行baseCompile编译模板template,再在编译结果compiled上添加errors、tips(与options有关,没传入,暂不考虑)

3.执行baseCompile函数,把template模板字符串处理成ast(树状数据结构,未注入真实数据),调用generate把ast转化为render渲染函数字符串形式,返回{ast, render,staticRenderFns)

部分简略源码:

function createCompileToFunctionFn(compile) {
     // compile, 一开始就被缓存的参数
    var cache = Object.create(null);  //对解析的模板进行缓存
    return function compileToFunctions(template, options, vm) {
        /**
         * template: <div class='wrapper'><div>{{ msg }}</div></div>
         * option未传
         */
        console.log("1----compileToFunctions")
        ......
        var key = template;
        if (cache[key]) {
            return cache[key];
        }
        // compile
        var compiled = compile(template, options);
        ......
        var res = {};
        var fnGenErrors = [];
        res.render = createFunction(compiled.render, fnGenErrors);
        res.staticRenderFns = compiled.staticRenderFns.map(function (code) {
            return createFunction(code, fnGenErrors);
        });
        ......
        return (cache[key] = res);
    };
}

function createCompilerCreator(baseCompile) {
    // baseCompile, 一开始就被缓存的参数
    return function createCompiler(baseOptions) {
        // 先调用createCompiler,什么都不执行,只返回return {compile, compileToFunctions}
        function compile(template, options) {
            console.log("2----compile")
            var finalOptions = Object.create(baseOptions);
            ......
            var compiled = baseCompile(template.trim(), finalOptions);
            if (process.env.NODE_ENV !== 'production') {
                detectErrors(compiled.ast, warn);
            }
            compiled.errors = errors;
            compiled.tips = tips;
            return compiled;
        }
        return {
            compile: compile,
            compileToFunctions: createCompileToFunctionFn(compile)
        };
    };
}

var createCompiler = createCompilerCreator(
    function baseCompile(template, options) {
        console.log("3----baseCompile")
        var ast = parse(template.trim(), options);  // 把template字符串处理成树状数据结构,未注入真实数据
        var code = generate(ast, options); // code: {render, staticRenderFns}
        return {
            ast: ast,
            render: code.render, // render函数
            staticRenderFns: code.staticRenderFns
        };
});
//入口
var _a = createCompiler(baseOptions), compileToFunctions = _a.compileToFunctions;
Vue.compile = compileToFunctions;

Vue.observable(object)

作用:让一个对象可响应,返回的对象可以直接用于渲染函数和计算属性内,并且会在发生变更时触发相应的更新。也可以作为最小化的跨组件状态存储器

1.使用计算属性

<template>
  <div id="home">
    <!-- 点击可改变obj、arr, 并能响应页面 -->
    <div @click="changeObj">obj: {{ obj  }}</div>
    <div @click="changeArr">arr: {{ arr  }}</div>
  </div>
</template>

<script>
import Vue from "vue";
// 需要使用computed做中介,供页面使用
const state = Vue.observable({ arr: [1,2,3], obj: {name: 'haha', age: 10} });
console.log("state: ", state); //响应式数据

export default {
  name: "",
  data() {
    return {
    };
  },
  computed: {
    obj(){
      return state.obj
    },
    arr(){
      return state.arr
    }
  },
  methods: {
    changeObj(){
      state.obj.age++
    },
    changeArr(){
      state.arr.push(10)
    },
    pushRouter(){
      this.$router.push("/b")
    }
  },
};
</script>

2.把该步骤单独封装为文件,使用计算属性,可作为跨组件状态存储器使用 

// store.js
import Vue from "vue";
const state = Vue.observable({ arr: [1,2,3], obj: {name: 'haha', age: 10} });
export default state

//A页面
<template>
   <div>arr: {{ arr }}</div>
</template>

<script>
import state from "@/store/replaceStore.js";
export default {
  computed: {
    arr() {
      return state.arr;
    },
  },
};
</script>

源码:

function initGlobalAPI(Vue) {
  ......
  Vue.observable = function (obj) {
      observe(obj);
      return obj;
  };
  ......
}

function observe(value, shallow, ssrMockReactivity) {
  // 已经有响应式对象,直接retuen响应式对象
  if (value && hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {
      return value.__ob__;
  }
  ......
  return new Observer(value, shallow, ssrMockReactivity);
}

function Observer(value, shallow, mock) {
  if (shallow === void 0) { shallow = false; }
  if (mock === void 0) { mock = false; }
  this.value = value;
  this.shallow = shallow;
  this.mock = mock;
  this.dep = mock ? mockDep : new Dep();
  this.vmCount = 0;
  // 给value添加属性{__ob__: Observer对象}, 表示该数据value已经被响应式
  def(value, '__ob__', this);
  if (isArray(value)) {
      if (!mock) {
          if (hasProto) {
              value.__proto__ = arrayMethods;
          }
          else {
              // 对数组进行拦截 
              for (var i = 0, l = arrayKeys.length; i < l; i++) {
                  var key = arrayKeys[i];
                  def(value, key, arrayMethods[key]);
              }
          }
      }
      if (!shallow) {
          this.observeArray(value);
      }
  }
  else {
     // 对每个属性进行响应式  
      var keys = Object.keys(value);
      for (var i = 0; i < keys.length; i++) {
          var key = keys[i];
          defineReactive(value, key, NO_INIITIAL_VALUE, undefined, shallow, mock);
      }
  }
}

provide/inject

作用:祖孙组件通信

provide:返回一个对象,或者一个返回对象的函数

inject:注入的字段名,可重命名

//返回一个对象
//父组件
provide: {
    msg: 'haha', //--非响应式
    name: this.name, //--简单类型,非响应式
    arr: this.arr, //--Array、Object类型,响应式
},
//子组件
inject: ["name"],

//返回一个函数
//父组件
provide: {
    name: () => this.subName, //--简单类型,响应式
},
//子组件
<template>
   <div>name: {{ name() }}</div>
</template>
inject: ["name"],

v-once

模板只渲染一次,不会根据数据的变化而重新渲染模板

<transition>

vue内部自定义组件,可以设置过渡效果

参数:

  • name,会根据name自动生成六个类名,表示不同的过渡阶段

extends、mixins

 作用:扩展另一个组件,与minxins原理类似

extends会比mixins先执行。执行顺序:extends > mixins > 组件

<template>
  <div id="home">
    <div>firstName: {{ firstName }}</div>
  </div>
</template>

<script>
export default {
  name: "",
  extends: {
    data: function () {
      return {
        firstName: "Walter"
      };
    },
    mounted() {
      // console.log("mounted: ", this);
    },
  },
};
</script>

源码:使用深搜的方法,把extends、mixin的对象扁平化到组件一级

function mergeOptions(parent, child, vm) {
    if (process.env.NODE_ENV !== 'production') {
        checkComponents(child);
    }
    if (isFunction(child)) {
        // @ts-expect-error
        child = child.options;
    }
    normalizeProps(child, vm);
    normalizeInject(child, vm);
    normalizeDirectives$1(child);

    if (!child._base) {
        if (child.extends) {
            parent = mergeOptions(parent, child.extends, vm);
        }
        if (child.mixins) {
            for (var i = 0, l = child.mixins.length; i < l; i++) {
                parent = mergeOptions(parent, child.mixins[i], vm);
            }
        }
    }
    var options = {};
    var key;
    // 映射parent的key到一级
    for (key in parent) {
        mergeField(key);
    }
     // 映射child的key(parent没有的)到一级
    for (key in child) {
        if (!hasOwn(parent, key)) {
            mergeField(key);
        }
    }
    function mergeField(key) {
        var strat = strats[key] || defaultStrat;
        options[key] = strat(parent[key], child[key], vm, key);
    }
    // 把扁平化的数据返回
    return options;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/415585.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

相机的内参和外参介绍

注&#xff1a;以下相机内参与外参介绍除来自网络整理外全部来自于《视觉SLAM十四讲从理论到实践 第2版》中的第5讲&#xff1a;相机与图像&#xff0c;为了方便查看&#xff0c;我将每节合并到了一幅图像中 相机与摄像机区别&#xff1a;相机着重于拍摄静态图像&#x…

智安网络|Ddos攻击原理和防范方法,你值得拥有

这几年网络越来越容易崩溃&#xff0c;今天不是这个网站崩&#xff0c;就是那个网站进不去&#xff0c;去年各个省份的健康码也接连崩溃&#xff0c;大家在寒风冷冽的冬天排队几小时做核酸&#xff0c;为什么现在的APP、网页都那么容易崩&#xff1f;还是同样的理由&#xff0c…

[Java·算法·困难]LeetCode10. 正则表达式匹配

每天一题&#xff0c;防止痴呆题目示例分析思路1题解1&#x1f449;️ 力扣原文 题目 给你一个字符串 s 和一个字符规律 p&#xff0c;请你来实现一个支持 . 和 * 的正则表达式匹配。 . 匹配任意单个字符 * 匹配零个或多个前面的那一个元素 所谓匹配&#xff0c;是要涵盖 整…

Doubbo

目录 1.简介 2.架构 3.配置监控中心 4.模拟服务提供者 5.模拟服务消费者 6.消费者的其他配置 6.1协议 6.2启动时检查 6.3超时和重试 6.4负载均衡 7.补充 1.简介 Apache Dubbo是一款高性能的Java RPC框架。其前身是阿里巴巴公司开源的一个高性能、轻量级的开源Java RP…

【Vue-Spring跨域Bug已解决】has been blocked by CORS policy: The value of the······

文章目录一.问题发现二.问题解决过程2.1 询问AI结果2.2 问题解决三.知识点一.问题发现 报错内容&#xff1a; p://localhost:8001/user/login’ from origin ‘http://localhost:3001’ has been blocked by CORS policy: The value of the ‘Access-Control-Allow-Credentia…

我决定给 ChatGPT 做个缓存层 Hello GPTCache

&#x1f31f; 写在前面黄老板的一句【AI 的 iPhone 时刻已至】震撼了半个科技圈。或许&#xff0c;应该把这句话再扩展一下&#xff1a;AI 的 iPhone 时刻早已势不可挡&#xff0c;它不是平静随和地跟大家 say hi&#xff0c;而是作为一个强悍的巨人携着一把名为 ChatGPT 的斧…

leetcode每日一题:数组专练篇第二期(2/2)

&#x1f61a;一个不甘平凡的普通人&#xff0c;日更算法学习和打卡&#xff0c;期待您的关注和认可&#xff0c;陪您一起学习打卡&#xff01;&#xff01;&#xff01;&#x1f618;&#x1f618;&#x1f618; &#x1f917;专栏&#xff1a;每日算法学习 &#x1f4ac;个人…

【LeetCode: 剑指 Offer II 089. 房屋偷盗(打家窃舍) | 暴力递归=>记忆化搜索=>动态规划】

&#x1f34e;作者简介&#xff1a;硕风和炜&#xff0c;CSDN-Java领域新星创作者&#x1f3c6;&#xff0c;保研|国家奖学金|高中学习JAVA|大学完善JAVA开发技术栈|面试刷题|面经八股文|经验分享|好用的网站工具分享&#x1f48e;&#x1f48e;&#x1f48e; &#x1f34e;座右…

Adept AI,颠覆“产品学“的产品

1.三体降临&#xff0c;产品学不存在了&#xff1f; 兄弟们&#xff0c;你们敢想象以后我们都会有用自己的贾维斯吗&#xff1f;我们不需要在安装一大堆APP&#xff0c;不需要适应各种APP交互&#xff0c;只需一句话你能快速达到你想要的目的吗&#xff1f;你能想象那种科幻大…

Nacos 客户端服务注册源码分析-篇二

Nacos 客户端服务注册源码分析-篇二 继续接上回&#xff0c;上回分析到 NacosNamingService 的整个注册的流程&#xff0c;其实是通过 NacosFactory.createNamingService 方法&#xff0c;反射获取 NacosNamingService 接口的实现类 NacosNamingService &#xff0c;而 NacosN…

基于粒子群算法的含风光燃储微网优化调度

说明书 MATLAB代码&#xff1a;基于粒子群算法的含风光燃储微网优化调度 关键词&#xff1a;微网优化调度 粒子群算法 风光燃储 参考文档&#xff1a;《基于多目标粒子群算法的微电网优化调度_王金全》仅参考部分模型&#xff0c;非完全复现 优势&#xff1a;代码注释详实&…

【通过Cpython3.9源码看看python中的大小整数】

小整数 /* interpreter state */#define _PY_NSMALLPOSINTS 257 #define _PY_NSMALLNEGINTS 5这是CPython中定义的两个常量&#xff0c;它们用于控制解释器状态中的小整数对象池。在CPython中&#xff0c;小整数对象池是一种优化机制&#xff0c;用于减少…

轨迹相似度整理

1 基于点之间的距离 1.1 欧几里得距离 优点&#xff1a;线性计算时间缺点&#xff1a;轨迹长度必须一样 1.2 DTW DTW 笔记&#xff1a; Dynamic Time Warping 动态时间规整 &#xff08;&DTW的python实现&#xff09; 【DDTW&#xff0c;WDTW】_UQI-LIUWJ的博客-CSDN博客 …

Golang流媒体实战之六:lal拉流服务源码阅读

欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码)&#xff1a;https://github.com/zq2599/blog_demos 《Golang流媒体实战》系列的链接 体验开源项目lal回源转推和录制lalserver的启动源码阅读Golang流媒体实战之五&#xff1a;lal推流服务源码阅读Golang流媒体…

大数据3 -Hadoop HDFS-分布式文件系统

目录 1.为什么需要分布式存储&#xff1f; 2. HDFS的基础架构 3. HDFS存储原理 4. NameNode是如何管理Block块的 5. HDFS数据的读写流程 1.为什么需要分布式存储&#xff1f; •数据量太大&#xff0c;单机存储能力有上限&#xff0c;需要靠数量来解决问题•数量的提升带…

【区块链】走进web3的世界-合约交互中的异常/边界处理

在以太坊智能合约中&#xff0c;异常处理是一个非常重要的问题&#xff0c;因为任何一个函数调用都有可能导致异常。常见的异常包括函数调用失败、无效参数、内部错误等。 在 Solidity 中&#xff0c;可以使用 require、assert 和 revert 等关键字来处理异常。这些关键字可以用…

第一章 序言:Pytorch在自然语言处理中的应用

01 序言&#xff1a;Pytorch在自然语言处理中的应用 目录01 序言&#xff1a;Pytorch在自然语言处理中的应用1. PyTorch简介2. 自然语言处理3. PyTorch在自然语言处理中的应用3.1 文本分类3.2 情感分析3.3 机器翻译4. 结论1. PyTorch简介 首先&#xff0c;我们需要介绍一下PyT…

WINDOWS消息

WINDOWS消息 Unit01消息队列 01消息队列概念 消息队列是用于存放消息的队列消息在队列中先进先出所有窗口程序都有消息队列程序&#xff08;GetMessage&#xff09;可以从队列中获消息 02消息队列分类 系统消息队列&#xff1a;由系统维护的消息队列&#xff08;这个队列非…

Qt的内存管理机制

QObject的parent设置为null 1.如果构造时直接指定了null&#xff0c;当前实例不会有父对象存在&#xff0c;Qt也不能自动析构该实例&#xff0c;除非实例超出作用域导致析构函数被调用&#xff0c;使用deletelater()函数&#xff0c;不建议使用delete 2.如果指定了parent&#…

关于电商商品数据API接口列表,你想知道的(详情页、Sku信息、商品描述、评论问答列表)

目录 一、商品数据API接口列表 二、商品详情数据API调用代码item_get 三、获取sku详细信息item_sku 四、获得淘宝商品评论item_review 五、数据说明文档 进入 一、商品数据API接口列表 二、商品详情数据API调用代码item_get <?php// 请求示例 url 默认请求参数已经URL…