如何手动实现一个Vue 以及 如何在浏览器上运行ES6项目

本文详细介绍了一个模仿Vue及其项目目录结构的ES6项目实践,包括使用Webpack进行项目打包,解析Vue实现原理,并通过个人学习网易云课堂内容,构建了一个可运行在浏览器的ES6项目。项目涉及的主要技术包括Webpack、Vue原理、ES6语法等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

模仿Vue以及Vue项目目录,实现一个可运行在浏览器的ES6项目

主要是webpack打包工具,以及vue实现的原理

vue原理部分,个人学习自网易云课堂

项目地址:

https://github.com/lovefive5/vue_es6.git

项目目录:

效果图: 

webpack 打包配置

const path = require('path')  //引入path
const HTMLPlugin = require('html-webpack-plugin')

module.exports = {
    mode: 'production',
    entry: './src/main.js',
    output: {
        path: path.resolve(__dirname, 'dist/'),
        filename: 'bundle.js'
    },
    module: {
        rules: [
            {
                test: /\.styl$/,
                use: [
                    'style-loader',
                    'css-loader',
                    {
                        loader: 'stylus-loader'
                    }
                ]
            },
            {
                test: /\.css$/,
                use: [
                    {
                        loader: 'style-loader',
                        options: {
                        }
                    },
                    {
                        loader: 'css-loader',
                        options: {
                            modules: false
                        }
                    }
                ]
            },
            //图片文件打包loader
            {
                test: /\.(jpg|jpeg|png)$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            //placeholder 占位符
                            outputPath: 'images',
                            name: '[name]_[hash].[ext]',
                            limit: 1048 * 2 
                        }
                    }
                ]
            }
        ]
    },
    plugins: [
        new HTMLPlugin({
            title: "webpack-study",
            filename: 'index.html',
            template: './public/index.html'
        })
    ],
    devServer: {
        contentBase: path.join(__dirname, 'dist'),
        port: 3000,
        hot: true
    }
}

 Vue实现

import Watch from './watch'

/**
 * 封装 Vue 类库
 * 实现双向绑定,以及函数调用
 * tips:函数调用肯定有坑啊
 */
class Vue {
    constructor(options) {
        this.options = options //实例化的 vue 配置
        this.$data = this.options.data //获取配置中的数据
        this.$el = document.querySelector(this.options.el) //获取指定节点的 Dom 对象
        this._observerable = {} //观察者容器
        this.$command = this.Command() //Vue默认提供的指令集合
        this.$methods = this.options.methods //
        this.Observerable(this.$data) //进行数据劫持处理
        this.Complite(this.$el) //进行指令处理
    }
    /**
     * Vue 进行数据劫持
     * @param {*} data 
     */
    Observerable(data) {
        for (let key in data) {
            this._observerable[key] = [] //指定观察者容器存储的类型为数组,即一个指令(v-text)的所有观察者

            let val = data[key] //获取对象中的值

            const watch = this._observerable[key]//获取观察者对象数组
            /**
             * 双向绑定的原理 , 修改对象上的属性
             * 相当于Java中的 setter getter
             */
            Object.defineProperty(this.$data, key, {
                //取出对象中的值
                get() {
                    return val
                },
                //设置对象里的值,此处实现自定义方法
                //每当设置值时,都会对已存储的 watch 进行遍历,然后调用Watch对象的update方法,从而修改Dom
                set(newVal) {
                    if (newVal !== val) {
                        val = newVal
                        watch.map(item => item.update())
                    }
                }
            })
        }
    }
    Complite(ele) {
        //获取#app下面的子节点
        const nodes = ele.children
        //对子节点进行遍历,找到含有指令的标签
        Array.from(nodes).map(element => {
            //如果当前遍历出的字节点还有子元素。则递归查找
            if (element.children.length > 0) {
                this.Complite(element)
            }

            this.$command.map(item => {
                //获取指令对象
                const val = element.getAttribute(item.command)
                if (element.hasAttribute(item.command)) {
                    if (item.type != 3 && this._observerable[val] === undefined) {
                        console.error("设定的:" + val + " 不存在")
                        return;
                    }
                    switch (item.type) {
                        case 1:
                            this._observerable[val].push(new Watch(this, element, val, item.operating))
                            break
                        case 2:
                            this._observerable[val].push(new Watch(this, element, val, item.operating))
                            //设置input事件,实时更新 vue-data 中指定指令的值
                            element.addEventListener('input', () => {
                                this.$data[val] = element.value
                            })
                            break
                        case 3:
                            //重新绑定 this 对象
                            const fun = this.$methods[val].bind(this.$data)
                            element.addEventListener('click', fun)
                            break
                    }
                }
            })
        })
    }
    //默认的指令集合
    Command() {
        return [
            {
                command: 'v-html',
                operating: 'innerHTML',
                type: 1
            },
            {
                command: 'v-text',
                operating: 'innerText',
                type: 1
            },
            {
                command: 'v-model',
                operating: 'value',
                type: 2
            },
            {
                command: 'v-on:click',
                operating: '',
                type: 3
            },
        ]
    }
}

export default Vue

Watch 观察者

/**
 * 观察者,
 * 通过数据变更,更新页面对象
 */
class Watch {
    /**
     * 
     * @param {*} vm vue实例对象 
     * @param {*} el 标签元素
     * @param {*} exp 指令
     * @param {*} val 指定对应的操作
     */
    constructor(vm, el, exp, val) {
        this.vm = vm
        this.el = el
        this.exp = exp
        this.val = val
        this.update()
    }
    update() {
        //Dom操作 input[value] = 'hello world'
        this.el[this.val] = this.vm.$data[this.exp]
    }
}

export default Watch

项目调用:

import Vue from './controller/vue'
import "./assets/style/main.css"

new Vue({
    el: "#app",
    data: {
        username: "",
        password: "",
        input_tips: ""
    },
    methods: {
        check() {
            this.input_tips = ''
            if (this.username == '' || this.username.length < 6) {
                this.input_tips = "<p style='color:red;'>账户名输入不规范</p>"
                return
            }
            if (this.password == '' || this.password.length < 6) {
                this.input_tips += "<p style='color:blue;'>密码输入不规范</p>"
                return
            }
        }
    }
})

<think>我们正在手动搭建Vue2项目。根据引用[3],首先需要确保安装了Node.js(版本不能高于18)和npm。步骤:1.安装Node.js:从官网下载并安装,然后检查版本:node-vnpm-v2.初始化项目:创建一个项目文件夹,进入并初始化npm项目。mkdirvue2-manual-setupcdvue2-manual-setupnpminit-y#-y表示默认配置3.安装webpack(构建工具)和webpack-cli(命令行工具):npminstallwebpack@4webpack-cli@3--save-dev4.安装Vue2及相关:npminstallvue@2--savenpminstallvue-loader@15vue-template-compiler--save-dev#vue-loader需要15版本以支持Vue25.创建项目基本结构:-创建src目录,并在其中创建main.js(入口文件)和App.vue(根组件)-创建index.html(主页面)6.配置webpack:-创建webpack.config.js文件-配置入口、输出、模块规则(处理.vue文件、css等)和插件7.安装必要的loader和插件:-处理css:css-loader,style-loader-处理vue文件:vue-loader(已安装)-处理其他资源(如图片、字体):file-loader或url-loader-插件:VueLoaderPlugin(从vue-loader中引入)8.配置babel(用于转换ES6语法):npminstallbabel-loader@babel/core@babel/preset-env--save-dev创建.babelrc文件9.在package.json中添加脚本命令(build和dev)。开发环境需要webpack-dev-server:npminstallwebpack-dev-server@3--save-dev10.编写代码并运行。详细步骤:1.项目结构:vue2-manual-setup/├──src/│├──App.vue│└──main.js├──index.html├──package.json├──webpack.config.js└──.babelrc2.index.html内容:<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Vue2ManualSetup</title></head><body><divid="app"></div><scriptsrc="./dist/bundle.js"></script></body></html>3.main.js内容:importVuefrom'vue';importAppfrom'./App.vue';newVue({el:'#app',render:h=>h(App)});4.App.vue内容:<template><div><h1>手动搭建Vue2项目</h1><p>这是一个手动搭建的Vue2项目</p></div></template><script>exportdefault{name:'App'}</script><stylescoped></style>5.webpack.config.js配置:constpath=require('path');const{VueLoaderPlugin}=require('vue-loader');module.exports={mode:'development',//或productionentry:'./src/main.js',output:{path:path.resolve(__dirname,'dist'),filename:'bundle.js'},module:{rules:[{test:/\.vue$/,loader:'vue-loader'},{test:/\.js$/,loader:'babel-loader',exclude:/node_modules/},{test:/\.css$/,use:['style-loader','css-loader']}]},plugins:[newVueLoaderPlugin()],devServer:{contentBase:path.join(__dirname,'dist'),compress:true,port:8080,open:true}};6..babelrc内容:{"presets":["@babel/preset-env"]}7.package.json中添加脚本:"scripts":{"build":"webpack","dev":"webpack-dev-server"}8.运行开发服务器:npmrundev9.打开浏览器访问:http://localhost:8080注意:如果遇到问题,可能是版本兼容性问题,请检查版本。引用说明:[^3]:提到了Node.js版本要求(不能高于18)以及安装命令。[^2]:提到了Vue文件组件的结构(template,script,style)。[^4]:提供了npm常用命令(安装依赖、运行项目等)。相关问题:1.如何处理Vue项目中的静态资源(如图片)?2.如何配置路由(VueRouter)在手动搭建的Vue2项目中?3.如何配置Vuex状态管理?</think>### 手动搭建 Vue 2 项目完整教程 以下是手动搭建 Vue 2 项目的详细步骤(基于 Webpack 4): #### 1. **环境准备** [^3] ```bash # 安装 Node.js(版本 ≤ 18.x) node -v # 验证安装 npm -v # 验证 npm # 创建项目目录 mkdir vue2-manual-project cd vue2-manual-project ``` #### 2. **初始化项目** ```bash npm init -y # 生成 package.json ``` #### 3. **安装核心依赖** [^2][^4] ```bash # Vue 2 核心 npm install vue@2.6.14 --save # Webpack 构建工具 npm install webpack@4 webpack-cli@3 webpack-dev-server@3 --save-dev # Vue文件组件支持 npm install vue-loader@15 vue-template-compiler --save-dev # Babel 转译 npm install babel-loader @babel/core @babel/preset-env --save-dev # CSS 处理 npm install css-loader style-loader --save-dev ``` #### 4. **创建项目结构** ``` vue2-manual-project/ ├── src/ │ ├── App.vue # 根组件 │ ├── main.js # 入口文件 │ └── components/ # 子组件目录 ├── public/ │ └── index.html # 主页面 ├── webpack.config.js # Webpack 配置 └── .babelrc # Babel 配置 ``` #### 5. **配置文件** **(1) `webpack.config.js`** [^2] ```javascript const { VueLoaderPlugin } = require('vue-loader'); module.exports = { mode: 'development', entry: './src/main.js', output: { filename: 'bundle.js', path: __dirname + '/dist' }, module: { rules: [ { test: /\.vue$/, loader: 'vue-loader' }, { test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ }, { test: /\.css$/, use: ['style-loader', 'css-loader'] } ] }, plugins: [new VueLoaderPlugin()], devServer: { contentBase: './public', port: 8080, hot: true } }; ``` **(2) `.babelrc`** ```json { "presets": ["@babel/preset-env"] } ``` #### 6. **编写核心文件** **(1) `public/index.html`** ```html <!DOCTYPE html> <html> <head> <title>Vue 2 手动搭建</title> </head> <body> <div id="app"></div> <script src="../dist/bundle.js"></script> </body> </html> ``` **(2) `src/App.vue`** [^2] ```vue <template> <div> <h1>{{ message }}</h1> <ChildComponent /> </div> </template> <script> import ChildComponent from './components/ChildComponent.vue'; export default { components: { ChildComponent }, data() { return { message: "手动搭建 Vue 2 成功!" } } } </script> <style scoped> h1 { color: #42b983; } </style> ``` **(3) `src/main.js`** ```javascript import Vue from 'vue'; import App from './App.vue'; new Vue({ render: h => h(App) }).$mount('#app'); ``` #### 7. **添加 npm 脚本** [^4] 在 `package.json` 中添加: ```json "scripts": { "dev": "webpack-dev-server", "build": "webpack --mode production" } ``` #### 8. **运行项目** ```bash npm run dev # 访问 http://localhost:8080 ``` #### 9. **项目优化**(可选) ```bash # 安装常用插件 npm install vue-router@3 vuex@3 axios --save ``` --- ### 关键注意事项 1. **版本兼容性** [^3] - Vue 2 需要 `vue-loader@15`(新版不兼容) - Node.js ≤ 18.x(避免兼容问题) 2. **单文件组件** [^2] - `.vue` 文件需包含 `<template>`, `<script>`, `<style>` 三个区块 - 使用 `vue-template-compiler` 编译模板 3. **开发效率** [^4] - `webpack-dev-server` 提供热重载 - 可通过 `npm install --registry=https://registry.npm.taobao.org` 加速依赖安装 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Auspicious5

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值