tradingview基本的结构-Vue

个人提醒

这是适用于我自己的代码结构,用的JS API,无法给源码。同时,接通数据的方法中,接通前提是保证数据的正确性,调用方法的顺序不要搞反,有数据才能配置Datafeed,有了Datafeed才能初始化,最后附上中文开发文档的链接吧

代码结构

获取后台数据

这部分主要是把数据用变量存起来,这个数据是自己的数据和tv还未相关(如果想省事直接在配置Datafeed里写也可以),简单来说,你要做的就是从自己的接口中拿数据。本人存在了变量bars中,下面部分能看到,结构如下

                    ret => {
                    // ret.data.tvData是接口中存的数据
                        let barsLength = ret.data.tvData.length;
                        if (barsLength !== 0) {
                            this.bars.s = 'ok';
                        } else {
                            this.bars.s = 'no_data';
                        }
                        ret.data.tvData.forEach(item => {
                            this.bars.t.push(+item.d); // 我这里是13位的时间戳
                            this.bars.c.push(+item.c_p);
                            this.bars.o.push(+item.o_p);
                            this.bars.h.push(+item.h_p);
                            this.bars.l.push(+item.l_p);
                            this.bars.v.push(+item.v);
                        })
                    }

配置Datafeed

与数据相关的主要部分在getBars ,这个部分想要搞透彻可以去看tradingview的一个Datafeed.js文件,里面的方法也可以直接复制过来,再根据自己的需求修改就能用。

		createFeed: function() {
            let this_vue = this;
            let Datafeed = {};
            Datafeed.Container = function(updateFrequency) {
                this._configuration = {
                    supports_search: false,
                    supports_group_request: false,
                    supported_resolutions: [
                        '1',
                        '3',
                        '5',
                        '15',
                        '30',
                        '60',
                        '120',
                        '240',
                        '360',
                        '720',
                        '1D',
                        '3D',
                        '1W',
                        '1M'
                    ],
                    supports_marks: true,
                    supports_timescale_marks: true,
                    exchanges: ['myExchange']
                };

                this._barsPulseUpdater = new Datafeed.DataPulseUpdater(this, updateFrequency || 10 * 1000);
                // this._quotesPulseUpdater = new Datafeed.QuotesPulseUpdater(this);

                this._enableLogging = true;
                this._callbacks = {};

                this._initializationFinished = true;
                this._fireEvent('initialized');
                this._fireEvent('configuration_ready');
            };

            Datafeed.DataPulseUpdater = function(datafeed, updateFrequency) {
            // 实时获取数据(不想实时刷新可以在这里设置)
                this._datafeed = datafeed;
                this._subscribers = {};

                this._requestsPending = 0;
                var that = this;

                var update = function() {
                    if (that._requestsPending > 0) {
                        return;
                    }
                    for (var listenerGUID in that._subscribers) {
                        var subscriptionRecord = that._subscribers[listenerGUID];
                        var resolution = subscriptionRecord.resolution;
                        var datesRangeRight = parseInt(new Date().valueOf() / 1000);
                        var datesRangeLeft = datesRangeRight - that.periodLengthSeconds(resolution, 50);
                        that._requestsPending++;

                            (function(_subscriptionRecord) { // eslint-disable-line
                            that._datafeed.getBars(
                                _subscriptionRecord.symbolInfo,
                                resolution,
                                datesRangeLeft,
                                datesRangeRight,
                                function(bars) {
                                    that._requestsPending--;

                                    //	means the subscription was cancelled while waiting for data 表示在等待数据时已取消订阅
                                    if (!that._subscribers.hasOwnProperty(listenerGUID)) {
                                        return;
                                    }

                                    if (bars.length === 0) {
                                        return;
                                    }

                                    var lastBar = bars[bars.length - 1];

                                    if (
                                        !isNaN(_subscriptionRecord.lastBarTime) &&
                                        lastBar.time < _subscriptionRecord.lastBarTime
                                    ) {
                                        return;
                                    }

                                    var subscribers = _subscriptionRecord.listeners;

                                    //	BEWARE: this one isn't working when first update comes and this update makes a new bar. In this case
                                    //	_subscriptionRecord.lastBarTime = NaN
                                    var isNewBar =
                                        !isNaN(_subscriptionRecord.lastBarTime) &&
                                        lastBar.time > _subscriptionRecord.lastBarTime;

                                    //	Pulse updating may miss some trades data (ie, if pulse period = 10 secods and new bar is started 5 seconds later after the last update, the
                                    //	old bar's last 5 seconds trades will be lost). Thus, at fist we should broadcast old bar updates when it's ready.
                                    if (isNewBar) {
                                        if (bars.length < 2) {
                                            throw new Error(
                                                'Not enough bars in history for proper pulse update. Need at least 2.'
                                            );
                                        }

                                        var previousBar = bars[bars.length - 2];
                                        for (var i = 0; i < subscribers.length; ++i) {
                                            subscribers[i](previousBar);
                                        }
                                    }

                                    _subscriptionRecord.lastBarTime = lastBar.time;

                                    for (let i = 0; i < subscribers.length; ++i) {
                                        subscribers[i](lastBar);
                                    }
                                },

                                //	on error
                                function() {
                                    that._requestsPending--;
                                }
                            );
                        })(subscriptionRecord);
                    }
                };
                if (typeof updateFrequency !== 'undefined' && updateFrequency > 0) {
                    setInterval(update, updateFrequency);
                }
            };

            Datafeed.Container.prototype._fireEvent = function(event, argument) {
                if (this._callbacks.hasOwnProperty(event)) {
                    var callbacksChain = this._callbacks[event];
                    for (var i = 0; i < callbacksChain.length; ++i) {
                        callbacksChain[i](argument);
                    }

                    this._callbacks[event] = [];
                }
            };

            Datafeed.Container.prototype.onReady = function(callback) {
                let that = this;
                if (this._configuration) {
                    setTimeout(function() {
                        callback(that._configuration);
                    }, 0);
                } else {
                    this.on('configuration_ready', function() {
                        callback(that._configuration);
                    });
                }
            };

            Datafeed.Container.prototype.resolveSymbol = function(
                symbolName,
                onSymbolResolvedCallback,
                onResolveErrorCallback
            ) {
            // 这部分属于订阅必调用的函数,主要就是onSymbolResolvedCallback中的配置,按需求来
            // 没特殊需求这么写就可以
                this._logMessage('GOWNO :: resolve symbol ' + symbolName);
                Promise.resolve().then(() => {
                    function adjustScale() {
                        if (this_vue.last_price > 1000) {
                            return 100;
                        } else {
                            return 100000000;
                        }
                    }

                    this._logMessage('GOWNO :: onResultReady inject ' + 'AAPL');
                    onSymbolResolvedCallback({
                        name: this_vue.symbol, //不需要传参的可以写定值
                        timezone: 'Europe/Warsaw',
                        pricescale: adjustScale(),
                        minmov: 1,
                        minmov2: 0,
                        ticker: this_vue.symbol,
                        description: '',
                        session: '24x7',
                        type: 'bitcoin',
                        'exchange-traded': 'myExchange',
                        'exchange-listed': 'myExchange',
                        has_intraday: true,
                        has_weekly_and_monthly: false,
                        has_no_volume: false,
                        regular_session: '24x7'
                    });
                });
            };

            Datafeed.Container.prototype._logMessage = function(message) {
                if (this._enableLogging) {
                    var now = new Date();
                    console.log(
                        'CHART LOGS: ' + now.toLocaleTimeString() + '.' + now.getMilliseconds() + '> ' + message
                    );
                }
            };

            Datafeed.Container.prototype.getBars = function( // 可以说是重要部分了
                symbolInfo,
                resolution,
                rangeStartDate,
                rangeEndDate,
                onDataCallback,
                onErrorCallback
            ) {
                if (rangeStartDate > 0 && (rangeStartDate + '').length > 10) {
                    throw new Error(['Got a JS time instead of Unix one.', rangeStartDate, rangeEndDate]);
                }
                if (自己的条件判断) {
                	// 返回空值给tv数据请求
                    onDataCallback([], { noData: true });
                    return;
                }
                // 下面部分就是将数据传给tradingview
                var data = this_vue.bars;
                var nodata = data.s === 'no_data';
                if (data.s !== 'ok' && !nodata) {
                    if (!onErrorCallback) {
                        onErrorCallback(data.s);
                    }
                    return;
                }
                var bars = [];
                var barsCount = nodata ? 0 : data.t.length;
                var volumePresent = typeof data.v !== 'undefined';
                var ohlPresent = typeof data.o !== 'undefined';
                for (var i = 0; i < barsCount; ++i) {
                    var barValue = {
                        time: data.t[i],
                        close: data.c[i]
                    };

                    if (ohlPresent) {
                        barValue.open = data.o[i];
                        barValue.high = data.h[i];
                        barValue.low = data.l[i];
                    } else {
                        barValue.open = barValue.high = barValue.low = barValue.close;
                    }

                    if (volumePresent) {
                        barValue.volume = data.v[i];
                    }

                    bars.push(barValue);
                }
                // 返回给tv数据请求
                onDataCallback(bars, { noData: nodata, nextTime: data.nb || data.nextTime });
            };

            Datafeed.Container.prototype.subscribeBars = function(
                symbolInfo,
                resolution,
                onRealtimeCallback,
                listenerGUID,
                onResetCacheNeededCallback
            ) {
                this._barsPulseUpdater.subscribeDataListener(
                    symbolInfo,
                    resolution,
                    onRealtimeCallback,
                    listenerGUID,
                    onResetCacheNeededCallback
                );
            };

            Datafeed.Container.prototype.on = function(event, callback) {
                if (!this._callbacks.hasOwnProperty(event)) {
                    this._callbacks[event] = [];
                }

                this._callbacks[event].push(callback);
                return this;
            };

            Datafeed.DataPulseUpdater.prototype.periodLengthSeconds = function(resolution, requiredPeriodsCount) {
                // 区间间隔时间
                var daysCount = 0;

                if (resolution === 'D') {
                    daysCount = requiredPeriodsCount;
                } else if (resolution === 'M') {
                    daysCount = 31 * requiredPeriodsCount;
                } else if (resolution === 'W') {
                    daysCount = 7 * requiredPeriodsCount;
                } else {
                    daysCount = (requiredPeriodsCount * resolution) / (24 * 60);
                }

                return daysCount * 24 * 60 * 60;
            };

            Datafeed.DataPulseUpdater.prototype.subscribeDataListener = function(
                symbolInfo,
                resolution,
                newDataCallback,
                listenerGUID
            ) {
                this._datafeed._logMessage('Subscribing ' + listenerGUID);

                if (!this._subscribers.hasOwnProperty(listenerGUID)) {
                    this._subscribers[listenerGUID] = {
                        symbolInfo: symbolInfo,
                        resolution: resolution,
                        lastBarTime: NaN,
                        listeners: []
                    };
                }
                this._subscribers[listenerGUID].listeners.push(newDataCallback);
            };

            Datafeed.DataPulseUpdater.prototype.unsubscribeDataListener = function(listenerGUID) {
                this._datafeed._logMessage('Unsubscribing ' + listenerGUID);
                delete this._subscribers[listenerGUID];
            };

            Datafeed.Container.prototype.unsubscribeBars = function(listenerGUID) {
                this._barsPulseUpdater.unsubscribeDataListener(listenerGUID);
            };
            return new Datafeed.Container();
        }

初始化tradingview

		initOnReady() {
            const this_vue = this;
            var widget = (window.tvWidget = new TradingView.widget({
                // debug: true, // 这个对搞熟tv很有用
                fullscreen: true,
                symbol: this_vue.symbol, // 标题,这个与Datafeed中resolveSymbol中的要保持一致
                interval: '1', // 时间间隔,可以自定义
                container_id: 'tvPage', // 容器id
                datafeed: this_vue.Datafeed(),
                library_path: 'charting_library/',
                locale: this_vue.getParameterByName('lang') || 'en',
                charts_storage_api_version: '1.1',
                charts_storage_url: 'http://saveload.tradingview.com',
                client_id: this_vue.client_id, // 自己根据需求定,这是用于加载和保存的,不需要可以不写
                user_id: this_vue.chartId, // 与标签中的id一致
                load_last_chart: false, // 是否显示最后的保存状态
                theme: this_vue.getParameterByName('theme'),
                timeframe: '1D', // 设置图表的初始时间范围
                time_frames: [],
                disabled_features: [ // 可以根据自己的需求来
                    'left_toolbar', // 左边工具栏
                    'header_widget', // 头部工具栏
                    'timeframes_toolbar', // 左下方时间选择
                    'display_market_status', // 左上角表示状态的圆点
                    'legend_context_menu', // oclhv选择
                    'main_series_scale_menu', // 右下角的设置按钮
                    'control_bar', // 滚动
                    'pane_context_menu', // 长按出现的设置选项
                    'show_chart_property_page', // 双击蜡烛出现的样式设置页面
                    'use_localstorage_for_settings'
                ],
                enabled_features: [ // 可以根据自己的需求来
                	'dont_show_boolean_study_arguments',
                	'study_templates'
                ],
                overrides: { // 可以根据自己的需求来
                    'mainSeriesProperties.candleStyle.upColor': '#65BF7F', // 蜡烛颜色
                    'mainSeriesProperties.candleStyle.downColor': '#E15D63',
                    'mainSeriesProperties.candleStyle.wickUpColor': '#65BF7F', // 烛心颜色
                    'mainSeriesProperties.candleStyle.wickDownColor': '#E15D63',
                },
                studies_overrides: { // 可以根据自己的需求来
                    'volume.volume.color.0': 'rgba(225, 93, 99, 0.2)', // down对应指标
                    'volume.volume.color.1': 'rgba(101, 191, 127, 0.2)' // up对应指标
                },
                custom_css_url: 'bundles/chart.css' // chart.css文件一定要放在charting_library文件夹下
            }));
        },
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
wps-view-vue是一个基于Vue框架开发的文件在线预览组件,它可以帮助我们实现对blob格式文件的在线预览。下面我将详细介绍如何使用wps-view-vue来预览blob格式文件。 首先,我们需要在项目中引入wps-view-vue组件,可以通过npm或者其他方式进行安装。在Vue的组件中,我们可以使用import语句导入wps-view-vue组件。 ``` import WpsView from 'wps-view-vue' ``` 接下来,我们在Vue组件中使用wps-view-vue组件,并传入blob格式的文件数据作为参数。 ``` <template> <div> <wps-view :blob="fileBlob" /> </div> </template> <script> import WpsView from 'wps-view-vue' export default { components: { WpsView }, data() { return { fileBlob: null } }, mounted() { // 获取blob格式文件数据,可以是通过接口请求获取到的 // 这里假设我们通过axios发送请求获取到了blob格式的文件数据 axios.get('http://example.com/api/file', { responseType: 'blob' }) .then(response => { this.fileBlob = response.data }) .catch(error => { console.error(error) }) } } </script> ``` 以上代码中,我们将获取到的blob格式文件数据赋值给fileBlob变量,并作为参数传递给wps-view组件。 通过以上步骤,我们就可以在Vue项目中使用wps-view-vue组件实现对blob格式文件的在线预览了。wps-view-vue组件会根据文件类型选择合适的预览方式,确保用户可以在浏览器中直接查看和操作blob格式文件。这样可以提升用户的使用体验,并且方便用户对文件进行相关操作。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值